deepfish-ai 2.0.4 → 2.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -4
- package/dist/generate-tool.md +1 -1
- package/dist/index.js +289 -73
- package/dist/serve/client/assets/index-CXCKvQL3.css +1 -0
- package/dist/serve/client/assets/index-Cr3CJSQU.js +1 -0
- package/dist/serve/client/index.html +4 -4
- package/dist/serve/pm2-server.js +17 -5
- package/dist/serve/server/entry-server.mjs +27 -14
- package/package.json +1 -1
- package/dist/serve/client/assets/index-DUHYC91l.js +0 -1
- package/dist/serve/client/assets/index-zcrdNLZs.css +0 -1
package/README.md
CHANGED
|
@@ -104,7 +104,7 @@ npm link
|
|
|
104
104
|
```bash
|
|
105
105
|
ai models add # 输入名称, 输入你的模型配置
|
|
106
106
|
ai config use 你输入的名称
|
|
107
|
-
ai
|
|
107
|
+
ai "帮我在当前目录写一篇关于未来科技的文章,用markdown格式输出"
|
|
108
108
|
```
|
|
109
109
|
|
|
110
110
|
## 4. 命令说明
|
|
@@ -115,7 +115,17 @@ ai ”帮我在当前目录写一篇关于未来科技的文章,用markdown格
|
|
|
115
115
|
ai "你的问题或指令"
|
|
116
116
|
```
|
|
117
117
|
|
|
118
|
-
直接输入自然语言,AI
|
|
118
|
+
直接输入自然语言,AI 将自动解析并执行对应操作。同一个目录下只会保持一个 Agent 会话,因此在当前目录中多次执行 `ai` 命令会复用同一个上下文。
|
|
119
|
+
|
|
120
|
+
示例:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
cd your-project
|
|
124
|
+
ai "你叫什么名字"
|
|
125
|
+
ai "我刚问了一个什么问题"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
第二次提问时,AI 会基于当前目录中的同一会话上下文回答你刚才问过的问题。
|
|
119
129
|
|
|
120
130
|
### 配置管理
|
|
121
131
|
|
|
@@ -219,8 +229,9 @@ MCP(Model Context Protocol)允许 AI 连接外部工具和服务。通过 `a
|
|
|
219
229
|
|
|
220
230
|
DeepFish 支持通过 Tool 和 Skill 扩展 AI 的能力。扩展文件可以放在当前工作目录的 `.deepfish-ai` 目录中,也可以放在全局配置目录中。
|
|
221
231
|
|
|
222
|
-
- **Tool 扩展**:用于定义 AI 可直接调用的自定义函数工具,适合封装 API
|
|
223
|
-
-
|
|
232
|
+
- **Tool 扩展**:用于定义 AI 可直接调用的自定义函数工具,适合封装 API 调用、数据库操作、文件处理等能力。可以使用 `ai tools generate xxx` 命令让 AI 根据描述生成 Tool。
|
|
233
|
+
- 在 Tool 函数中,可以通过调用 `this.createSubAgent(prompt: string)` 创建子 Agent,并将任务说明作为 `prompt` 传入。
|
|
234
|
+
- **Skill 扩展**:用于定义 AI 的工作流知识包,适合沉淀某类任务的执行步骤、规范和最佳实践。可以使用 `ai skills generate xxx` 命令让 AI 根据描述生成 Skill。
|
|
224
235
|
|
|
225
236
|
### 当前目录扩展
|
|
226
237
|
|
package/dist/generate-tool.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -8891,12 +8891,12 @@ async function handleModelUse(nameOrIndex) {
|
|
|
8891
8891
|
targetIndex = aiList.findIndex((item) => item.name === nameOrIndex);
|
|
8892
8892
|
}
|
|
8893
8893
|
if (targetIndex === -1) {
|
|
8894
|
-
logError(
|
|
8894
|
+
logError(`AI config not found: ${nameOrIndex}`);
|
|
8895
8895
|
return;
|
|
8896
8896
|
}
|
|
8897
8897
|
config2.currentModel = aiList[targetIndex].name;
|
|
8898
8898
|
writeConfig(config2);
|
|
8899
|
-
logSuccess(
|
|
8899
|
+
logSuccess(`Switched to AI config: ${aiList[targetIndex].name}`);
|
|
8900
8900
|
}
|
|
8901
8901
|
async function handleModelDel(nameOrIndex) {
|
|
8902
8902
|
const config2 = readConfig();
|
|
@@ -8913,7 +8913,7 @@ async function handleModelDel(nameOrIndex) {
|
|
|
8913
8913
|
targetIndex = aiList.findIndex((item) => item.name === nameOrIndex);
|
|
8914
8914
|
}
|
|
8915
8915
|
if (targetIndex === -1) {
|
|
8916
|
-
logError(
|
|
8916
|
+
logError(`AI config not found: ${nameOrIndex}`);
|
|
8917
8917
|
return;
|
|
8918
8918
|
}
|
|
8919
8919
|
const deletedName = aiList[targetIndex].name;
|
|
@@ -8923,7 +8923,7 @@ async function handleModelDel(nameOrIndex) {
|
|
|
8923
8923
|
config2.currentModel = "";
|
|
8924
8924
|
}
|
|
8925
8925
|
writeConfig(config2);
|
|
8926
|
-
logSuccess(
|
|
8926
|
+
logSuccess(`Deleted AI config: ${deletedName}`);
|
|
8927
8927
|
}
|
|
8928
8928
|
|
|
8929
8929
|
// src/cli/cli-model.ts
|
|
@@ -8936,7 +8936,7 @@ function registerModelsCommands(program) {
|
|
|
8936
8936
|
}
|
|
8937
8937
|
|
|
8938
8938
|
// src/cli/cli-core/skills.ts
|
|
8939
|
-
var
|
|
8939
|
+
var import_crypto6 = require("crypto");
|
|
8940
8940
|
var import_inquirer3 = __toESM(require("inquirer"));
|
|
8941
8941
|
var import_fs_extra19 = __toESM(require("fs-extra"));
|
|
8942
8942
|
var import_path19 = __toESM(require("path"));
|
|
@@ -8998,11 +8998,11 @@ function getConfig() {
|
|
|
8998
8998
|
// src/cli/cli-utils/init-agent.ts
|
|
8999
8999
|
var import_fs_extra18 = __toESM(require("fs-extra"));
|
|
9000
9000
|
var import_path18 = __toESM(require("path"));
|
|
9001
|
-
var
|
|
9001
|
+
var import_crypto5 = require("crypto");
|
|
9002
9002
|
|
|
9003
9003
|
// src/agent/AIAgent/index.ts
|
|
9004
|
-
var
|
|
9005
|
-
var
|
|
9004
|
+
var import_langchain17 = require("langchain");
|
|
9005
|
+
var import_deepagents2 = require("deepagents");
|
|
9006
9006
|
|
|
9007
9007
|
// src/agent/AIAgent/utils/langgraph-checkpoint-filesystem/filesystem-saver.ts
|
|
9008
9008
|
var import_path5 = require("path");
|
|
@@ -9284,17 +9284,10 @@ var BaseCheckpointSaver = class {
|
|
|
9284
9284
|
while (cursorConfig != null && remaining.size > 0) {
|
|
9285
9285
|
const tup = await this.getTuple(cursorConfig);
|
|
9286
9286
|
if (tup === void 0) break;
|
|
9287
|
-
if (tup.pendingWrites && tup.pendingWrites.length > 0) {
|
|
9288
|
-
const
|
|
9289
|
-
|
|
9290
|
-
|
|
9291
|
-
if (remaining.has(ch)) (perChannel[ch] ??= []).push(write);
|
|
9292
|
-
}
|
|
9293
|
-
for (const ch of Object.keys(perChannel)) {
|
|
9294
|
-
const block = perChannel[ch];
|
|
9295
|
-
block.sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0);
|
|
9296
|
-
for (let i = block.length - 1; i >= 0; i -= 1) collectedByCh[ch].push(block[i]);
|
|
9297
|
-
}
|
|
9287
|
+
if (tup.pendingWrites && tup.pendingWrites.length > 0) for (let i = tup.pendingWrites.length - 1; i >= 0; i -= 1) {
|
|
9288
|
+
const write = tup.pendingWrites[i];
|
|
9289
|
+
const ch = write[1];
|
|
9290
|
+
if (remaining.has(ch)) collectedByCh[ch].push(write);
|
|
9298
9291
|
}
|
|
9299
9292
|
for (const ch of Array.from(remaining)) if (Object.prototype.hasOwnProperty.call(tup.checkpoint.channel_values, ch)) {
|
|
9300
9293
|
seedByCh[ch] = tup.checkpoint.channel_values[ch];
|
|
@@ -9373,7 +9366,7 @@ var StorePathResolver = class {
|
|
|
9373
9366
|
getThreadPath(threadId) {
|
|
9374
9367
|
return (0, import_path4.join)(this.rootFolder, this.joinWithSplitter(threadId));
|
|
9375
9368
|
}
|
|
9376
|
-
getCheckpointNsPath(
|
|
9369
|
+
getCheckpointNsPath(_threadId, _checkpointNs) {
|
|
9377
9370
|
return (0, import_path4.join)(this.rootFolder);
|
|
9378
9371
|
}
|
|
9379
9372
|
getCheckpointFolderPath(threadId, checkpointNs, checkpointId) {
|
|
@@ -24235,7 +24228,7 @@ function date4(params) {
|
|
|
24235
24228
|
config(en_default());
|
|
24236
24229
|
|
|
24237
24230
|
// src/agent/AIAgent/index.ts
|
|
24238
|
-
var
|
|
24231
|
+
var import_eventemitter_super2 = require("eventemitter-super");
|
|
24239
24232
|
|
|
24240
24233
|
// src/agent/AIAgent/middleware/eventEmitMiddleware.ts
|
|
24241
24234
|
var import_langchain = require("langchain");
|
|
@@ -24632,9 +24625,15 @@ function toLangChainTool(func, description) {
|
|
|
24632
24625
|
zodProperties[key] = zodType;
|
|
24633
24626
|
}
|
|
24634
24627
|
const schema = external_exports.object(zodProperties);
|
|
24635
|
-
const wrappedFunc = async (args) => {
|
|
24628
|
+
const wrappedFunc = async (args, runtime) => {
|
|
24636
24629
|
try {
|
|
24637
|
-
const
|
|
24630
|
+
const boundFunc = func.bind({
|
|
24631
|
+
createSubAgent: (prompt) => {
|
|
24632
|
+
const subAgent = runtime.context.mainAgent.createSubAgent();
|
|
24633
|
+
return subAgent.execute(prompt);
|
|
24634
|
+
}
|
|
24635
|
+
});
|
|
24636
|
+
const result = await boundFunc(...Object.values(args));
|
|
24638
24637
|
if (typeof result === "object" && result !== null && "success" in result) {
|
|
24639
24638
|
return serializeToolResult(result);
|
|
24640
24639
|
}
|
|
@@ -24660,7 +24659,7 @@ function scanUserTools() {
|
|
|
24660
24659
|
if (import_fs_extra8.default.statSync(import_path8.default.resolve(toolsDir, file2)).isDirectory()) {
|
|
24661
24660
|
const subDirPath = import_path8.default.resolve(toolsDir, file2);
|
|
24662
24661
|
const subFiles = import_fs_extra8.default.readdirSync(subDirPath);
|
|
24663
|
-
const indexFile = subFiles.find((f) => f === "index" || f === "index.cjs");
|
|
24662
|
+
const indexFile = subFiles.find((f) => f === "index.js" || f === "index.cjs");
|
|
24664
24663
|
if (indexFile) {
|
|
24665
24664
|
const filePath = _scanDeepFishJsFile(import_path8.default.resolve(subDirPath, indexFile), indexFile);
|
|
24666
24665
|
if (filePath) {
|
|
@@ -24695,15 +24694,32 @@ function _scanDeepFishJsFile(filePath, fileName) {
|
|
|
24695
24694
|
return null;
|
|
24696
24695
|
}
|
|
24697
24696
|
function _loadToolsFromFile(filePath, tools) {
|
|
24698
|
-
|
|
24699
|
-
|
|
24700
|
-
|
|
24701
|
-
|
|
24702
|
-
|
|
24697
|
+
try {
|
|
24698
|
+
const toolModule = require(filePath);
|
|
24699
|
+
const { functions, descriptions } = toolModule;
|
|
24700
|
+
if (!functions || typeof functions !== "object" || !Array.isArray(descriptions)) {
|
|
24701
|
+
logWarning(`Skip invalid tool file: ${filePath}`);
|
|
24702
|
+
return;
|
|
24703
|
+
}
|
|
24704
|
+
descriptions.forEach((desc) => {
|
|
24705
|
+
if (!desc.type) {
|
|
24706
|
+
desc = {
|
|
24707
|
+
type: "function",
|
|
24708
|
+
function: desc
|
|
24709
|
+
};
|
|
24710
|
+
}
|
|
24711
|
+
const func = functions[desc.function.name];
|
|
24712
|
+
if (typeof func !== "function") {
|
|
24713
|
+
logWarning(`Skip tool "${desc.function.name}": implementation not found in ${filePath}`);
|
|
24714
|
+
return;
|
|
24715
|
+
}
|
|
24703
24716
|
const langChainTool = toLangChainTool(func, desc);
|
|
24704
24717
|
tools.push(langChainTool);
|
|
24705
|
-
}
|
|
24706
|
-
})
|
|
24718
|
+
});
|
|
24719
|
+
} catch (error51) {
|
|
24720
|
+
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
24721
|
+
logWarning(`Failed to load tool file: ${filePath}. ${message}`);
|
|
24722
|
+
}
|
|
24707
24723
|
}
|
|
24708
24724
|
|
|
24709
24725
|
// src/agent/tools/executeCommand.ts
|
|
@@ -24763,7 +24779,6 @@ var executeCommandTool = (0, import_langchain3.tool)(({ command, timeout }) => s
|
|
|
24763
24779
|
var import_langchain4 = require("langchain");
|
|
24764
24780
|
var import_path9 = __toESM(require("path"));
|
|
24765
24781
|
var import_fs_extra9 = __toESM(require("fs-extra"));
|
|
24766
|
-
var _require = require;
|
|
24767
24782
|
async function executeJSCode(code) {
|
|
24768
24783
|
logInfo("Executing JavaScript code: ");
|
|
24769
24784
|
logInfo(code);
|
|
@@ -24774,7 +24789,15 @@ async function executeJSCode(code) {
|
|
|
24774
24789
|
return result || "Code executed successfully, but __main() did not return anything."
|
|
24775
24790
|
})()`;
|
|
24776
24791
|
const fn = new Function("require", wrapped);
|
|
24777
|
-
const
|
|
24792
|
+
const _require = require;
|
|
24793
|
+
const newRequire = (modulePath) => {
|
|
24794
|
+
if (modulePath.startsWith("./")) {
|
|
24795
|
+
const resolvedPath = import_path9.default.resolve(process.cwd(), modulePath);
|
|
24796
|
+
return _require(resolvedPath);
|
|
24797
|
+
}
|
|
24798
|
+
return _require(modulePath);
|
|
24799
|
+
};
|
|
24800
|
+
const result = await fn(newRequire);
|
|
24778
24801
|
return result;
|
|
24779
24802
|
} catch (error51) {
|
|
24780
24803
|
logError(`Error executing code: ${error51.stack}`);
|
|
@@ -25029,13 +25052,17 @@ function wrapMcpTool(mcpTool) {
|
|
|
25029
25052
|
}
|
|
25030
25053
|
async function loadMcpToolsFromConfigPath(mcpFilePath) {
|
|
25031
25054
|
const jsonContent = import_fs_extra11.default.readJSONSync(mcpFilePath);
|
|
25032
|
-
|
|
25055
|
+
let mcpServers = jsonContent.mcpServers;
|
|
25033
25056
|
if (!mcpServers || Object.keys(mcpServers).length === 0) {
|
|
25034
25057
|
return [];
|
|
25035
25058
|
}
|
|
25036
25059
|
try {
|
|
25037
25060
|
for (const key of Object.keys(mcpServers)) {
|
|
25038
25061
|
const server = mcpServers[key];
|
|
25062
|
+
if (server.disabled) {
|
|
25063
|
+
delete mcpServers[key];
|
|
25064
|
+
continue;
|
|
25065
|
+
}
|
|
25039
25066
|
if (!server.transport) {
|
|
25040
25067
|
if (server.url) {
|
|
25041
25068
|
if (server.url.startsWith("ws://") || server.url.startsWith("wss://")) {
|
|
@@ -25052,6 +25079,9 @@ async function loadMcpToolsFromConfigPath(mcpFilePath) {
|
|
|
25052
25079
|
delete mcpServers[key];
|
|
25053
25080
|
}
|
|
25054
25081
|
}
|
|
25082
|
+
if (Object.keys(mcpServers).length === 0) {
|
|
25083
|
+
return [];
|
|
25084
|
+
}
|
|
25055
25085
|
logInfo(`Loading MCP tools from config path: ${mcpFilePath}`);
|
|
25056
25086
|
const client = new import_mcp_adapters.MultiServerMCPClient(jsonContent.mcpServers);
|
|
25057
25087
|
const tools = await client.getTools();
|
|
@@ -25508,15 +25538,22 @@ function getSkills() {
|
|
|
25508
25538
|
}
|
|
25509
25539
|
|
|
25510
25540
|
// src/agent/AIAgent/index.ts
|
|
25541
|
+
var import_os4 = __toESM(require("os"));
|
|
25542
|
+
|
|
25543
|
+
// src/agent/AIAgent/SubAIAgent.ts
|
|
25544
|
+
var import_langchain16 = require("langchain");
|
|
25545
|
+
var import_deepagents = require("deepagents");
|
|
25546
|
+
var import_eventemitter_super = require("eventemitter-super");
|
|
25511
25547
|
var import_os3 = __toESM(require("os"));
|
|
25512
|
-
var
|
|
25548
|
+
var import_crypto4 = require("crypto");
|
|
25549
|
+
var SubAIAgent = class extends import_eventemitter_super.EventEmitterSuper {
|
|
25513
25550
|
id = "";
|
|
25514
25551
|
opt = {};
|
|
25515
25552
|
tools = [];
|
|
25516
25553
|
dynamicTools = [];
|
|
25517
25554
|
skills = [];
|
|
25518
25555
|
mcp = [];
|
|
25519
|
-
subLevel =
|
|
25556
|
+
subLevel = 1;
|
|
25520
25557
|
agent = {};
|
|
25521
25558
|
messages = [];
|
|
25522
25559
|
basespace = "";
|
|
@@ -25525,12 +25562,10 @@ var AIAgent = class extends import_eventemitter_super.EventEmitterSuper {
|
|
|
25525
25562
|
sessionDirPath = "";
|
|
25526
25563
|
userStorePath = "";
|
|
25527
25564
|
agentRulesPath = "";
|
|
25528
|
-
roomClient = null;
|
|
25529
|
-
taskQueue = {};
|
|
25530
25565
|
isPrintThinking = true;
|
|
25531
25566
|
constructor(opt) {
|
|
25532
25567
|
super();
|
|
25533
|
-
this.id = opt.id || `agent-${
|
|
25568
|
+
this.id = opt.id || `agent-${(0, import_crypto4.randomUUID)()}`;
|
|
25534
25569
|
this.basespace = opt.basespace;
|
|
25535
25570
|
this.workspace = opt.workspace;
|
|
25536
25571
|
this.memoryFilePath = opt.memoryFilePath;
|
|
@@ -25544,19 +25579,16 @@ var AIAgent = class extends import_eventemitter_super.EventEmitterSuper {
|
|
|
25544
25579
|
this.tools = await getTools();
|
|
25545
25580
|
this.skills = [...getSkills(), ...this.opt.skills || []];
|
|
25546
25581
|
const model = getModel(this.opt.modelOpt);
|
|
25547
|
-
const checkpointer = new FileSystemSaver({
|
|
25548
|
-
rootFolder: this.sessionDirPath
|
|
25549
|
-
});
|
|
25550
25582
|
const contextSchema = external_exports.object({
|
|
25551
25583
|
agent_name: external_exports.string(),
|
|
25552
25584
|
encoding: external_exports.string(),
|
|
25553
25585
|
skills: external_exports.array(external_exports.string()).optional(),
|
|
25554
25586
|
memoryFilePath: external_exports.string().optional(),
|
|
25555
|
-
agentId: external_exports.string().optional()
|
|
25587
|
+
agentId: external_exports.string().optional(),
|
|
25588
|
+
mainAgent: external_exports.object().optional()
|
|
25556
25589
|
});
|
|
25557
25590
|
const agent = (0, import_langchain16.createAgent)({
|
|
25558
25591
|
model,
|
|
25559
|
-
checkpointer,
|
|
25560
25592
|
tools: this.tools,
|
|
25561
25593
|
contextSchema,
|
|
25562
25594
|
middleware: [
|
|
@@ -25593,7 +25625,6 @@ var AIAgent = class extends import_eventemitter_super.EventEmitterSuper {
|
|
|
25593
25625
|
systemPrompt: systemPrompt(this.workspace, import_os3.default.platform(), this.skills, this.memoryFilePath, this.agentRulesPath)
|
|
25594
25626
|
});
|
|
25595
25627
|
this.agent = agent;
|
|
25596
|
-
this.taskQueue = new TaskQueue(this.id);
|
|
25597
25628
|
this.initEvents();
|
|
25598
25629
|
}
|
|
25599
25630
|
async execute(input) {
|
|
@@ -25606,7 +25637,191 @@ var AIAgent = class extends import_eventemitter_super.EventEmitterSuper {
|
|
|
25606
25637
|
recursionLimit: 2e3,
|
|
25607
25638
|
subgraphs: true,
|
|
25608
25639
|
configurable: { thread_id: this.id },
|
|
25609
|
-
context: {
|
|
25640
|
+
context: {
|
|
25641
|
+
agent_name: "deepfish",
|
|
25642
|
+
encoding: this.opt.encoding,
|
|
25643
|
+
skills: this.skills,
|
|
25644
|
+
memoryFilePath: this.memoryFilePath,
|
|
25645
|
+
agentId: this.id,
|
|
25646
|
+
mainAgent: this
|
|
25647
|
+
}
|
|
25648
|
+
}
|
|
25649
|
+
);
|
|
25650
|
+
return new Promise(async (resolve) => {
|
|
25651
|
+
this.once("TASK_AFTER" /* TASK_AFTER */, (msg) => {
|
|
25652
|
+
resolve(msg);
|
|
25653
|
+
});
|
|
25654
|
+
for await (const [_namespace, mode, data] of stream) {
|
|
25655
|
+
if (mode === "messages") {
|
|
25656
|
+
const message = data[0].additional_kwargs.reasoning_content;
|
|
25657
|
+
this.emit("STREAM_CONTENT_OUTPUT" /* STREAM_CONTENT_OUTPUT */, message);
|
|
25658
|
+
}
|
|
25659
|
+
}
|
|
25660
|
+
});
|
|
25661
|
+
}
|
|
25662
|
+
initEvents() {
|
|
25663
|
+
const thinking = new Thinking();
|
|
25664
|
+
this.on("TASK_BEFORE" /* TASK_BEFORE */, () => {
|
|
25665
|
+
});
|
|
25666
|
+
this.on("TASK_AFTER" /* TASK_AFTER */, (msg) => {
|
|
25667
|
+
logInfo(msg);
|
|
25668
|
+
});
|
|
25669
|
+
this.on("MODEL_BEFORE" /* MODEL_BEFORE */, () => {
|
|
25670
|
+
});
|
|
25671
|
+
this.on("MODEL_AFTER" /* MODEL_AFTER */, () => {
|
|
25672
|
+
if (this.isPrintThinking) {
|
|
25673
|
+
thinking.stop();
|
|
25674
|
+
}
|
|
25675
|
+
});
|
|
25676
|
+
this.on("MODEL_ERROR" /* MODEL_ERROR */, (error51) => {
|
|
25677
|
+
if (this.isPrintThinking) {
|
|
25678
|
+
thinking.stop();
|
|
25679
|
+
}
|
|
25680
|
+
logError(error51?.message + "\n" + error51?.stack);
|
|
25681
|
+
});
|
|
25682
|
+
this.on("STREAM_CONTENT_OUTPUT" /* STREAM_CONTENT_OUTPUT */, (content) => {
|
|
25683
|
+
if (this.isPrintThinking) {
|
|
25684
|
+
if (content && typeof content === "string") {
|
|
25685
|
+
streamOutput(content, "#f2c97d");
|
|
25686
|
+
}
|
|
25687
|
+
} else {
|
|
25688
|
+
if (content && typeof content === "string") {
|
|
25689
|
+
thinking.start();
|
|
25690
|
+
} else {
|
|
25691
|
+
thinking.stop();
|
|
25692
|
+
}
|
|
25693
|
+
}
|
|
25694
|
+
});
|
|
25695
|
+
this.on("COMPRESS_MESSAGES_BEFORE" /* COMPRESS_MESSAGES_BEFORE */, (_currentLength) => {
|
|
25696
|
+
});
|
|
25697
|
+
this.on("COMPRESS_MESSAGES_AFTER" /* COMPRESS_MESSAGES_AFTER */, (_currentLength) => {
|
|
25698
|
+
});
|
|
25699
|
+
this.on("NEW_MESSAGE" /* NEW_MESSAGE */, (_msg) => {
|
|
25700
|
+
});
|
|
25701
|
+
this.on("USE_TOOL_BEFORE" /* USE_TOOL_BEFORE */, (_toolId, funcName, _funcArgs) => {
|
|
25702
|
+
log(`[Tool Call] ${funcName}`, "#c2a654");
|
|
25703
|
+
});
|
|
25704
|
+
this.on("USE_TOOL_RETURN" /* USE_TOOL_RETURN */, (_toolId, _funcName, _toolContent) => {
|
|
25705
|
+
logInfo(`[Tool Return] ${_funcName} returned: ${_toolContent}`);
|
|
25706
|
+
});
|
|
25707
|
+
this.on("USE_TOOL_ERROR" /* USE_TOOL_ERROR */, (_toolId, _funcName, _error) => {
|
|
25708
|
+
logError(`Error in tool ${_funcName}: ${_error instanceof Error ? _error.message : String(_error)}`);
|
|
25709
|
+
});
|
|
25710
|
+
this.on("USE_TOOL_AFTER" /* USE_TOOL_AFTER */, (_toolId, _funcName, _funcArgs) => {
|
|
25711
|
+
});
|
|
25712
|
+
}
|
|
25713
|
+
destory() {
|
|
25714
|
+
this.removeAllListeners();
|
|
25715
|
+
}
|
|
25716
|
+
};
|
|
25717
|
+
|
|
25718
|
+
// src/agent/AIAgent/index.ts
|
|
25719
|
+
var AIAgent = class extends import_eventemitter_super2.EventEmitterSuper {
|
|
25720
|
+
id = "";
|
|
25721
|
+
opt = {};
|
|
25722
|
+
tools = [];
|
|
25723
|
+
dynamicTools = [];
|
|
25724
|
+
skills = [];
|
|
25725
|
+
mcp = [];
|
|
25726
|
+
subLevel = 0;
|
|
25727
|
+
agent = {};
|
|
25728
|
+
messages = [];
|
|
25729
|
+
basespace = "";
|
|
25730
|
+
workspace = "";
|
|
25731
|
+
memoryFilePath = "";
|
|
25732
|
+
sessionDirPath = "";
|
|
25733
|
+
userStorePath = "";
|
|
25734
|
+
agentRulesPath = "";
|
|
25735
|
+
roomClient = null;
|
|
25736
|
+
taskQueue = {};
|
|
25737
|
+
isPrintThinking = true;
|
|
25738
|
+
constructor(opt) {
|
|
25739
|
+
super();
|
|
25740
|
+
this.id = opt.id || `agent-${Date.now()}`;
|
|
25741
|
+
this.basespace = opt.basespace;
|
|
25742
|
+
this.workspace = opt.workspace;
|
|
25743
|
+
this.memoryFilePath = opt.memoryFilePath;
|
|
25744
|
+
this.sessionDirPath = opt.sessionDirPath;
|
|
25745
|
+
this.userStorePath = opt.userStorePath;
|
|
25746
|
+
this.agentRulesPath = opt.agentRulesPath;
|
|
25747
|
+
this.isPrintThinking = opt.isPrintThinking;
|
|
25748
|
+
this.opt = opt;
|
|
25749
|
+
}
|
|
25750
|
+
async init() {
|
|
25751
|
+
this.tools = await getTools();
|
|
25752
|
+
this.skills = [...getSkills(), ...this.opt.skills || []];
|
|
25753
|
+
const model = getModel(this.opt.modelOpt);
|
|
25754
|
+
const checkpointer = new FileSystemSaver({
|
|
25755
|
+
rootFolder: this.sessionDirPath
|
|
25756
|
+
});
|
|
25757
|
+
const contextSchema = external_exports.object({
|
|
25758
|
+
agent_name: external_exports.string(),
|
|
25759
|
+
encoding: external_exports.string(),
|
|
25760
|
+
skills: external_exports.array(external_exports.string()).optional(),
|
|
25761
|
+
memoryFilePath: external_exports.string().optional(),
|
|
25762
|
+
agentId: external_exports.string().optional(),
|
|
25763
|
+
mainAgent: external_exports.object().optional()
|
|
25764
|
+
});
|
|
25765
|
+
const agent = (0, import_langchain17.createAgent)({
|
|
25766
|
+
model,
|
|
25767
|
+
checkpointer,
|
|
25768
|
+
tools: this.tools,
|
|
25769
|
+
contextSchema,
|
|
25770
|
+
middleware: [
|
|
25771
|
+
createAgentEventMiddleware(this),
|
|
25772
|
+
(0, import_langchain17.summarizationMiddleware)({
|
|
25773
|
+
model,
|
|
25774
|
+
trigger: { tokens: this.opt.modelOpt.maxContextLength || 1e5 },
|
|
25775
|
+
keep: { messages: 50 }
|
|
25776
|
+
}),
|
|
25777
|
+
(0, import_langchain17.humanInTheLoopMiddleware)({
|
|
25778
|
+
interruptOn: {
|
|
25779
|
+
install_package: {
|
|
25780
|
+
allowedDecisions: ["approve", "reject"]
|
|
25781
|
+
},
|
|
25782
|
+
readEmailTool: false
|
|
25783
|
+
}
|
|
25784
|
+
}),
|
|
25785
|
+
(0, import_langchain17.todoListMiddleware)(),
|
|
25786
|
+
(0, import_deepagents2.createPatchToolCallsMiddleware)(),
|
|
25787
|
+
(0, import_deepagents2.createSubAgentMiddleware)({
|
|
25788
|
+
defaultModel: model,
|
|
25789
|
+
subagents: [
|
|
25790
|
+
{
|
|
25791
|
+
name: "subagent",
|
|
25792
|
+
description: "This subagent can execute sub tasks.",
|
|
25793
|
+
systemPrompt: subSystemPrompt(this.workspace, import_os4.default.platform(), this.skills),
|
|
25794
|
+
tools: this.tools,
|
|
25795
|
+
model,
|
|
25796
|
+
middleware: []
|
|
25797
|
+
}
|
|
25798
|
+
]
|
|
25799
|
+
})
|
|
25800
|
+
],
|
|
25801
|
+
systemPrompt: systemPrompt(this.workspace, import_os4.default.platform(), this.skills, this.memoryFilePath, this.agentRulesPath)
|
|
25802
|
+
});
|
|
25803
|
+
this.agent = agent;
|
|
25804
|
+
this.taskQueue = new TaskQueue(this.id);
|
|
25805
|
+
this.initEvents();
|
|
25806
|
+
}
|
|
25807
|
+
async execute(input) {
|
|
25808
|
+
const humanMessage = new import_langchain17.HumanMessage(input);
|
|
25809
|
+
this.messages.push(humanMessage);
|
|
25810
|
+
const stream = await this.agent.stream(
|
|
25811
|
+
{ messages: this.messages },
|
|
25812
|
+
{
|
|
25813
|
+
streamMode: ["messages"],
|
|
25814
|
+
recursionLimit: 2e3,
|
|
25815
|
+
subgraphs: true,
|
|
25816
|
+
configurable: { thread_id: this.id },
|
|
25817
|
+
context: {
|
|
25818
|
+
agent_name: "deepfish",
|
|
25819
|
+
encoding: this.opt.encoding,
|
|
25820
|
+
skills: this.skills,
|
|
25821
|
+
memoryFilePath: this.memoryFilePath,
|
|
25822
|
+
agentId: this.id,
|
|
25823
|
+
mainAgent: this
|
|
25824
|
+
}
|
|
25610
25825
|
}
|
|
25611
25826
|
);
|
|
25612
25827
|
for await (const [_namespace, mode, data] of stream) {
|
|
@@ -25617,7 +25832,7 @@ var AIAgent = class extends import_eventemitter_super.EventEmitterSuper {
|
|
|
25617
25832
|
}
|
|
25618
25833
|
const newTask = this.taskQueue.getTask();
|
|
25619
25834
|
if (newTask) {
|
|
25620
|
-
log(`[
|
|
25835
|
+
log(`[Task Queue] New task found, executing: ${newTask.taskStr}`, "#7fded1");
|
|
25621
25836
|
await this.execute(newTask.taskStr);
|
|
25622
25837
|
}
|
|
25623
25838
|
}
|
|
@@ -25634,7 +25849,6 @@ var AIAgent = class extends import_eventemitter_super.EventEmitterSuper {
|
|
|
25634
25849
|
if (this.isPrintThinking) {
|
|
25635
25850
|
thinking.stop();
|
|
25636
25851
|
}
|
|
25637
|
-
streamOutput("\n");
|
|
25638
25852
|
});
|
|
25639
25853
|
this.on("MODEL_ERROR" /* MODEL_ERROR */, (error51) => {
|
|
25640
25854
|
if (this.isPrintThinking) {
|
|
@@ -25662,15 +25876,20 @@ var AIAgent = class extends import_eventemitter_super.EventEmitterSuper {
|
|
|
25662
25876
|
this.on("NEW_MESSAGE" /* NEW_MESSAGE */, (_msg) => {
|
|
25663
25877
|
});
|
|
25664
25878
|
this.on("USE_TOOL_BEFORE" /* USE_TOOL_BEFORE */, (_toolId, funcName, _funcArgs) => {
|
|
25665
|
-
log(`[
|
|
25879
|
+
log(`[Tool Call] ${funcName}`, "#c2a654");
|
|
25666
25880
|
});
|
|
25667
|
-
this.on("USE_TOOL_RETURN" /* USE_TOOL_RETURN */, (_toolId,
|
|
25881
|
+
this.on("USE_TOOL_RETURN" /* USE_TOOL_RETURN */, (_toolId, _funcName, _toolContent) => {
|
|
25882
|
+
logInfo(`[Tool Return] ${_funcName} returned: ${_toolContent}`);
|
|
25668
25883
|
});
|
|
25669
|
-
this.on("USE_TOOL_ERROR" /* USE_TOOL_ERROR */, (_toolId,
|
|
25884
|
+
this.on("USE_TOOL_ERROR" /* USE_TOOL_ERROR */, (_toolId, _funcName, _error) => {
|
|
25885
|
+
logError(`Error in tool ${_funcName}: ${_error instanceof Error ? _error.message : String(_error)}`);
|
|
25670
25886
|
});
|
|
25671
|
-
this.on("USE_TOOL_AFTER" /* USE_TOOL_AFTER */, (_toolId,
|
|
25887
|
+
this.on("USE_TOOL_AFTER" /* USE_TOOL_AFTER */, (_toolId, _funcName, _funcArgs) => {
|
|
25672
25888
|
});
|
|
25673
25889
|
}
|
|
25890
|
+
createSubAgent() {
|
|
25891
|
+
return new SubAIAgent(this.opt);
|
|
25892
|
+
}
|
|
25674
25893
|
destory() {
|
|
25675
25894
|
this.removeAllListeners();
|
|
25676
25895
|
}
|
|
@@ -25948,7 +26167,6 @@ function connectAgentRoom(agent) {
|
|
|
25948
26167
|
reconnectInterval: 0,
|
|
25949
26168
|
// Disable auto-reconnect during Promise phase
|
|
25950
26169
|
onReady: () => {
|
|
25951
|
-
logSuccess(`[agent-room] agent online: ${id}`);
|
|
25952
26170
|
done({ ok: true, client });
|
|
25953
26171
|
},
|
|
25954
26172
|
onError: (_c, code) => {
|
|
@@ -25975,7 +26193,6 @@ async function testServer() {
|
|
|
25975
26193
|
const res = await fetch(url2, { method: "GET" });
|
|
25976
26194
|
const text = await res.text();
|
|
25977
26195
|
if (text === "pong") {
|
|
25978
|
-
logSuccess(`Service already running: http://localhost:${port}`);
|
|
25979
26196
|
return true;
|
|
25980
26197
|
}
|
|
25981
26198
|
logError(`Port ${port} is occupied but /ping did not return expected result (received: ${text}), please check for port conflict`);
|
|
@@ -26063,7 +26280,7 @@ function initSession() {
|
|
|
26063
26280
|
initSessionDir(existingSession.id);
|
|
26064
26281
|
return existingSession;
|
|
26065
26282
|
}
|
|
26066
|
-
const agentId = (0,
|
|
26283
|
+
const agentId = (0, import_crypto5.randomUUID)();
|
|
26067
26284
|
const newSession = {
|
|
26068
26285
|
id: agentId,
|
|
26069
26286
|
name: import_path18.default.basename(workspace),
|
|
@@ -26116,15 +26333,15 @@ function getAgentId() {
|
|
|
26116
26333
|
// src/cli/cli-core/skills.ts
|
|
26117
26334
|
function handleSkillsLs() {
|
|
26118
26335
|
const skills = _getAllSkills();
|
|
26119
|
-
|
|
26336
|
+
logInfo("=".repeat(50));
|
|
26120
26337
|
if (skills.length === 0) {
|
|
26121
26338
|
logInfo("No skills registered yet");
|
|
26122
26339
|
} else {
|
|
26123
26340
|
skills.forEach((skill, index) => {
|
|
26124
|
-
|
|
26341
|
+
logInfo(`[${index}] ${skill.name} (${skill.isEnabled ? "enabled" : "disabled"})`);
|
|
26125
26342
|
});
|
|
26126
26343
|
}
|
|
26127
|
-
|
|
26344
|
+
logInfo("=".repeat(50));
|
|
26128
26345
|
}
|
|
26129
26346
|
async function handleSkillsAdd(name) {
|
|
26130
26347
|
logInfo(`Adding skill: ${name}`);
|
|
@@ -26136,7 +26353,7 @@ async function handleSkillsAdd(name) {
|
|
|
26136
26353
|
}
|
|
26137
26354
|
const { scope } = await import_inquirer3.default.prompt([
|
|
26138
26355
|
{
|
|
26139
|
-
type: "
|
|
26356
|
+
type: "select",
|
|
26140
26357
|
name: "scope",
|
|
26141
26358
|
message: "Select skill scope:",
|
|
26142
26359
|
choices: [
|
|
@@ -26190,7 +26407,7 @@ function handleSkillsDel(index) {
|
|
|
26190
26407
|
register = register.filter((item) => item.skillPath !== skill.skillPath);
|
|
26191
26408
|
import_fs_extra19.default.writeJSONSync(registerPath, register, { spaces: 2 });
|
|
26192
26409
|
}
|
|
26193
|
-
logSuccess(`Skill
|
|
26410
|
+
logSuccess(`Skill deleted: ${skill.name}`);
|
|
26194
26411
|
}
|
|
26195
26412
|
function handleSkillsEnable(index) {
|
|
26196
26413
|
const skills = _getAllSkills();
|
|
@@ -26250,8 +26467,8 @@ async function handleSkillsGenerate(target) {
|
|
|
26250
26467
|
return;
|
|
26251
26468
|
}
|
|
26252
26469
|
try {
|
|
26253
|
-
const
|
|
26254
|
-
if (!
|
|
26470
|
+
const isServerRunning = await testServer();
|
|
26471
|
+
if (!isServerRunning) {
|
|
26255
26472
|
logError("Failed to start service, please check config or port availability");
|
|
26256
26473
|
return;
|
|
26257
26474
|
}
|
|
@@ -26302,7 +26519,7 @@ function _updateRegister(skillsDir) {
|
|
|
26302
26519
|
const existItem = register.find((item) => item.skillPath === skillPath);
|
|
26303
26520
|
if (!existItem) {
|
|
26304
26521
|
newRegister.push({
|
|
26305
|
-
id: (0,
|
|
26522
|
+
id: (0, import_crypto6.randomUUID)(),
|
|
26306
26523
|
name: skillName,
|
|
26307
26524
|
isEnabled: true,
|
|
26308
26525
|
skillPath
|
|
@@ -26385,7 +26602,7 @@ async function handleToolsAdd(name) {
|
|
|
26385
26602
|
}
|
|
26386
26603
|
const { scope } = await import_inquirer4.default.prompt([
|
|
26387
26604
|
{
|
|
26388
|
-
type: "
|
|
26605
|
+
type: "select",
|
|
26389
26606
|
name: "scope",
|
|
26390
26607
|
message: "Select tool scope:",
|
|
26391
26608
|
choices: [
|
|
@@ -26434,8 +26651,8 @@ async function handleToolsGenerate(target) {
|
|
|
26434
26651
|
return;
|
|
26435
26652
|
}
|
|
26436
26653
|
try {
|
|
26437
|
-
const
|
|
26438
|
-
if (!
|
|
26654
|
+
const isServerRunning = await testServer();
|
|
26655
|
+
if (!isServerRunning) {
|
|
26439
26656
|
logError("Failed to start service, please check config or port availability");
|
|
26440
26657
|
return;
|
|
26441
26658
|
}
|
|
@@ -26496,7 +26713,7 @@ function registerServeCommands(program) {
|
|
|
26496
26713
|
openDirectory(url2);
|
|
26497
26714
|
return;
|
|
26498
26715
|
}
|
|
26499
|
-
logError(`Port ${port} is occupied but did not respond with expected content
|
|
26716
|
+
logError(`Port ${port} is occupied but did not respond with expected content (received: ${text})`);
|
|
26500
26717
|
} catch (err) {
|
|
26501
26718
|
logWarning("Service not started, please run `ai serve start`");
|
|
26502
26719
|
}
|
|
@@ -26537,7 +26754,7 @@ function handleTaskAdd(taskStr) {
|
|
|
26537
26754
|
const queue = getTaskQueue();
|
|
26538
26755
|
if (!queue) return;
|
|
26539
26756
|
queue.pushTask(taskStr.trim());
|
|
26540
|
-
logSuccess(
|
|
26757
|
+
logSuccess(`Task added: ${taskStr.trim()}`);
|
|
26541
26758
|
}
|
|
26542
26759
|
function handleTaskDel(indexStr) {
|
|
26543
26760
|
const index = parseInt(indexStr, 10);
|
|
@@ -26605,8 +26822,8 @@ async function handleInput(args) {
|
|
|
26605
26822
|
logError("No AI model configured, please run ai model use <name>");
|
|
26606
26823
|
return;
|
|
26607
26824
|
}
|
|
26608
|
-
const
|
|
26609
|
-
if (!
|
|
26825
|
+
const isServerRunning = await testServer();
|
|
26826
|
+
if (!isServerRunning) {
|
|
26610
26827
|
logError("Failed to start service, please check config or port availability");
|
|
26611
26828
|
return;
|
|
26612
26829
|
}
|
|
@@ -26642,8 +26859,8 @@ async function multiInput() {
|
|
|
26642
26859
|
logError("No AI model configured, please run ai model use <name>");
|
|
26643
26860
|
return;
|
|
26644
26861
|
}
|
|
26645
|
-
const
|
|
26646
|
-
if (!
|
|
26862
|
+
const isServerRunning = await testServer();
|
|
26863
|
+
if (!isServerRunning) {
|
|
26647
26864
|
logError("Failed to start service, please check config or port availability");
|
|
26648
26865
|
return;
|
|
26649
26866
|
}
|
|
@@ -26730,7 +26947,6 @@ function handleCacheList() {
|
|
|
26730
26947
|
}
|
|
26731
26948
|
catalog.forEach((item, index) => {
|
|
26732
26949
|
const desc = item.description.length > 20 ? item.description.slice(0, 20) + "..." : item.description;
|
|
26733
|
-
console.log(`[${index}] ${item.id} ${desc}`);
|
|
26734
26950
|
});
|
|
26735
26951
|
}
|
|
26736
26952
|
function handleCacheEdit(input) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*,:before,:after{box-sizing:border-box}html,body{min-height:100%;margin:0;padding:0}body{color:#2c3e50;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;letter-spacing:.01em;background:#f5f7fa;min-height:100vh;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,Hiragino Sans GB,Microsoft YaHei,sans-serif}.app-shell{max-width:1400px;margin:0 auto;padding:28px 20px 40px}.app-header{border-bottom:1px solid #ffffff0f;justify-content:space-between;align-items:flex-end;gap:24px;margin-bottom:24px;padding-bottom:18px;display:flex}.app-title{letter-spacing:.02em;color:#2c3e50;margin:0;font-size:1.4rem;font-weight:600}.app-subtitle{color:#6b7280;letter-spacing:.06em;margin:6px 0 0;font-family:SF Mono,JetBrains Mono,Consolas,monospace;font-size:.82rem}.status-pill{color:#6b7280;background:#f3f6fb;border:1px solid #e6e6e6;border-radius:999px;align-items:center;gap:8px;padding:6px 12px;font-family:SF Mono,JetBrains Mono,Consolas,monospace;font-size:.78rem;display:inline-flex}.status-dot{background:#94a3b8;border-radius:50%;width:8px;height:8px}.status-dot.is-connected{background:#38bdf8}.status-dot.is-connecting{background:#f59e0b}.status-dot.is-disconnected{background:#cbd5e1}.status-dot.is-error{background:#ef4444}@keyframes pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.55;transform:scale(.85)}}.panel{background:#fff;border:1px solid #e6e6e6;border-radius:10px;position:relative;overflow:hidden;box-shadow:0 6px 18px #1e293b0f}.panel:before{display:none}.panel-header{border-bottom:1px solid #f0f2f5;justify-content:space-between;align-items:center;padding:14px 18px;display:flex}.panel-title{color:#2c3e50;letter-spacing:.02em;align-items:center;gap:10px;margin:0;font-size:.95rem;font-weight:600;display:flex}.panel-title .badge{color:#3b82f6;background:#eef2ff;border:1px solid #3b82f61f;border-radius:6px;padding:2px 8px;font-family:SF Mono,JetBrains Mono,Consolas,monospace;font-size:.72rem;font-weight:500}.table-wrap{width:100%;overflow-x:visible}table.sessions{border-collapse:separate;border-spacing:0;table-layout:fixed;width:100%;font-size:.88rem}table.sessions thead th{text-align:center;color:#6b7280;background:0 0;border-bottom:1px solid #f0f2f5;padding:12px 18px;font-size:.8rem;font-weight:600}table.sessions thead th:first-child{width:300px}table.sessions tbody td{color:#2c3e50;vertical-align:middle;white-space:normal;text-align:center;border-bottom:1px solid #f0f2f5;padding:14px 18px}table.sessions tbody tr{transition:background .16s}table.sessions tbody tr:hover{background:#fbfbfd}table.sessions tbody tr:last-child td{border-bottom:none}table.sessions .th-actions,table.sessions .cell-actions{text-align:center;white-space:nowrap}table.sessions .cell-actions{justify-content:center;gap:8px;display:flex}.btn-delete{color:#ef4444;letter-spacing:.02em;cursor:pointer;background:0 0;border:1px solid #ef44441f;border-radius:6px;align-items:center;gap:6px;padding:8px 14px;font-family:SF Mono,JetBrains Mono,Consolas,monospace;font-size:.86rem;font-weight:600;transition:all .16s;display:inline-flex}.btn-delete:hover{box-shadow:none;background:#ef44440f}.btn-delete:active{transform:translateY(1px)}.btn-delete:disabled{opacity:.4;cursor:not-allowed}.btn-id{color:#3b82f6;letter-spacing:.02em;cursor:pointer;background:0 0;border:1px solid #3b82f624;border-radius:6px;align-items:center;gap:6px;padding:8px 14px;font-family:SF Mono,JetBrains Mono,Consolas,monospace;font-size:.86rem;font-weight:600;transition:all .16s;display:inline-flex}.btn-id:hover{box-shadow:none;background:#3b82f60f}.btn-id:active{transform:translateY(1px)}.cell-mono{color:#64748b;text-align:left;font-family:SF Mono,JetBrains Mono,Consolas,monospace;font-size:.86rem}table.sessions .cell-workspace{text-overflow:ellipsis;white-space:nowrap;text-align:left;width:300px;max-width:300px;overflow:hidden}.cell-name{color:#2c3e50;font-weight:600}.cell-time{color:#64748b;font-family:SF Mono,JetBrains Mono,Consolas,monospace;font-size:.86rem}.status-tag{letter-spacing:.04em;border-radius:999px;align-items:center;gap:6px;padding:3px 10px;font-family:SF Mono,JetBrains Mono,Consolas,monospace;font-size:.74rem;font-weight:500;display:inline-flex}.status-tag:before{content:"";background:currentColor;border-radius:50%;width:6px;height:6px;box-shadow:0 0 6px}.status-tag.is-online{color:#4ade80;background:#4ade8014;border:1px solid #4ade8040}.status-tag.is-offline{color:#94a3b8;background:#94a3b80f;border:1px solid #94a3b82e}.empty-state{color:#6b7280;flex-direction:column;justify-content:center;align-items:center;gap:10px;padding:60px 20px;font-size:.98rem;display:flex}.empty-state .icon{opacity:.6;font-size:1.6rem}@media (width<=720px){.app-shell{padding:24px 14px 40px}.app-header{flex-direction:column;align-items:flex-start}table.sessions thead th,table.sessions tbody td{padding:10px 12px}}.modal-backdrop{z-index:1200;background:#10182814;justify-content:center;align-items:center;padding:20px;display:flex;position:fixed;inset:0}.modal{background:#fff;border:1px solid #e6e6e6;border-radius:8px;width:100%;max-width:520px;padding:18px;box-shadow:0 8px 30px #1018280f}.modal-title{color:#2c3e50;margin:0 0 12px;font-size:1rem}.modal-body{color:#2c3e50;margin-bottom:18px;font-size:.98rem}.modal-id{color:#334155;word-break:break-all;background:#f8fafc;border:1px solid #e5e7eb;border-radius:8px;margin-bottom:18px;padding:12px;font-family:SF Mono,JetBrains Mono,Consolas,monospace}.modal-actions{justify-content:flex-end;gap:12px;display:flex}.btn{cursor:pointer;border:none;border-radius:8px;padding:8px 14px;font-weight:600}.btn:disabled{opacity:.6;cursor:not-allowed}.btn-cancel{color:#6b7280;background:0 0;border:1px solid #f0f2f5}.btn-confirm{color:#fff;background:linear-gradient(90deg,#3b82f6,#60a5fa);border:1px solid #3b82f60f;box-shadow:0 6px 18px #3b82f61f}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e={context:void 0,registry:void 0,effects:void 0,done:!1,getContextId(){return t(this.context.count)},getNextContextId(){return t(this.context.count++)}};function t(t){let n=String(t),r=n.length-1;return e.context.id+(r?String.fromCharCode(96+r):``)+n}function n(t){e.context=t}function r(){return{...e.context,id:e.getNextContextId(),count:0}}var i=(e,t)=>e===t,a=Symbol(`solid-track`),o={equals:i},s=null,c=oe,l=1,u=2,d={owned:null,cleanups:null,context:null,owner:null},f=null,p=null,m=null,h=null,g=null,_=null,v=null,y=0;function b(e,t){let n=g,r=f,i=e.length===0,a=t===void 0?r:t,o=i?d:{owned:null,cleanups:null,context:a?a.context:null,owner:a},s=i?e:()=>e(()=>T(()=>L(o)));f=o,g=null;try{return P(s,!0)}finally{g=n,f=r}}function x(e,t){t=t?Object.assign({},o,t):o;let n={value:e,observers:null,observerSlots:null,comparator:t.equals||void 0};return[O.bind(n),e=>(typeof e==`function`&&(e=p&&p.running&&p.sources.has(n)?e(n.tValue):e(n.value)),k(n,e))]}function S(e,t,n){let r=M(e,t,!1,l);m&&p&&p.running?_.push(r):A(r)}function C(e,t,n){c=ce;let r=M(e,t,!1,l),i=D&&ie(D);i&&(r.suspense=i),(!n||!n.render)&&(r.user=!0),v?v.push(r):A(r)}function w(e,t,n){n=n?Object.assign({},o,n):o;let r=M(e,t,!0,0);return r.observers=null,r.observerSlots=null,r.comparator=n.equals||void 0,m&&p&&p.running?(r.tState=l,_.push(r)):A(r),O.bind(r)}function T(e){if(!h&&g===null)return e();let t=g;g=null;try{return h?h.untrack(e):e()}finally{g=t}}function ee(e){C(()=>T(e))}function E(e){return f===null||(f.cleanups===null?f.cleanups=[e]:f.cleanups.push(e)),e}function te(e){if(p&&p.running)return e(),p.done;let t=g,n=f;return Promise.resolve().then(()=>{g=t,f=n;let r;return(m||D)&&(r=p||={sources:new Set,effects:[],promises:new Set,disposed:new Set,queue:new Set,running:!0},r.done||=new Promise(e=>r.resolve=e),r.running=!0),P(e,!1),g=f=null,r?r.done:void 0})}var[ne,re]=x(!1);function ie(e){let t;return f&&f.context&&(t=f.context[e.id])!==void 0?t:e.defaultValue}var D;function O(){let e=p&&p.running;if(this.sources&&(e?this.tState:this.state))if((e?this.tState:this.state)===l)A(this);else{let e=_;_=null,P(()=>F(this),!1),_=e}if(g){let e=this.observers;if(!e||e[e.length-1]!==g){let t=e?e.length:0;g.sources?(g.sources.push(this),g.sourceSlots.push(t)):(g.sources=[this],g.sourceSlots=[t]),e?(e.push(g),this.observerSlots.push(g.sources.length-1)):(this.observers=[g],this.observerSlots=[g.sources.length-1])}}return e&&p.sources.has(this)?this.tValue:this.value}function k(e,t,n){let r=p&&p.running&&p.sources.has(e)?e.tValue:e.value;if(!e.comparator||!e.comparator(r,t)){if(p){let r=p.running;(r||!n&&p.sources.has(e))&&(p.sources.add(e),e.tValue=t),r||(e.value=t)}else e.value=t;e.observers&&e.observers.length&&P(()=>{for(let t=0;t<e.observers.length;t+=1){let n=e.observers[t],r=p&&p.running;r&&p.disposed.has(n)||((r?!n.tState:!n.state)&&(n.pure?_.push(n):v.push(n),n.observers&&I(n)),r?n.tState=l:n.state=l)}if(_.length>1e6)throw _=[],Error()},!1)}return t}function A(e){if(!e.fn)return;L(e);let t=y;j(e,p&&p.running&&p.sources.has(e)?e.tValue:e.value,t),p&&!p.running&&p.sources.has(e)&&queueMicrotask(()=>{P(()=>{p&&(p.running=!0),g=f=e,j(e,e.tValue,t),g=f=null},!1)})}function j(e,t,n){let r,i=f,a=g;g=f=e;try{r=e.fn(t)}catch(t){return e.pure&&(p&&p.running?(e.tState=l,e.tOwned&&e.tOwned.forEach(L),e.tOwned=void 0):(e.state=l,e.owned&&e.owned.forEach(L),e.owned=null)),e.updatedAt=n+1,B(t)}finally{g=a,f=i}(!e.updatedAt||e.updatedAt<=n)&&(e.updatedAt!=null&&`observers`in e?k(e,r,!0):p&&p.running&&e.pure?(p.sources.has(e)||(e.value=r),p.sources.add(e),e.tValue=r):e.value=r,e.updatedAt=n)}function M(e,t,n,r=l,i){let a={fn:e,state:r,updatedAt:null,owned:null,sources:null,sourceSlots:null,cleanups:null,value:t,owner:f,context:f?f.context:null,pure:n};if(p&&p.running&&(a.state=0,a.tState=r),f===null||f!==d&&(p&&p.running&&f.pure?f.tOwned?f.tOwned.push(a):f.tOwned=[a]:f.owned?f.owned.push(a):f.owned=[a]),h&&a.fn){let e=a.fn,[t,n]=x(void 0,{equals:!1}),r=h.factory(e,n);E(()=>r.dispose());let i,o=()=>te(n).then(()=>{i&&=(i.dispose(),void 0)});a.fn=n=>(t(),p&&p.running?(i||=h.factory(e,o),i.track(n)):r.track(n))}return a}function N(e){let t=p&&p.running;if((t?e.tState:e.state)===0)return;if((t?e.tState:e.state)===u)return F(e);if(e.suspense&&T(e.suspense.inFallback))return e.suspense.effects.push(e);let n=[e];for(;(e=e.owner)&&(!e.updatedAt||e.updatedAt<y);){if(t&&p.disposed.has(e))return;(t?e.tState:e.state)&&n.push(e)}for(let r=n.length-1;r>=0;r--){if(e=n[r],t){let t=e,i=n[r+1];for(;(t=t.owner)&&t!==i;)if(p.disposed.has(t))return}if((t?e.tState:e.state)===l)A(e);else if((t?e.tState:e.state)===u){let t=_;_=null,P(()=>F(e,n[0]),!1),_=t}}}function P(e,t){if(_)return e();let n=!1;t||(_=[]),v?n=!0:v=[],y++;try{let t=e();return ae(n),t}catch(e){n||(v=null),_=null,B(e)}}function ae(e){if(_&&=(m&&p&&p.running?se(_):oe(_),null),e)return;let t;if(p){if(!p.promises.size&&!p.queue.size){let e=p.sources,n=p.disposed;v.push.apply(v,p.effects),t=p.resolve;for(let e of v)`tState`in e&&(e.state=e.tState),delete e.tState;p=null,P(()=>{for(let e of n)L(e);for(let t of e){if(t.value=t.tValue,t.owned)for(let e=0,n=t.owned.length;e<n;e++)L(t.owned[e]);t.tOwned&&(t.owned=t.tOwned),delete t.tValue,delete t.tOwned,t.tState=0}re(!1)},!1)}else if(p.running){p.running=!1,p.effects.push.apply(p.effects,v),v=null,re(!0);return}}let n=v;v=null,n.length&&P(()=>c(n),!1),t&&t()}function oe(e){for(let t=0;t<e.length;t++)N(e[t])}function se(e){for(let t=0;t<e.length;t++){let n=e[t],r=p.queue;r.has(n)||(r.add(n),m(()=>{r.delete(n),P(()=>{p.running=!0,N(n)},!1),p&&(p.running=!1)}))}}function ce(t){let r,i=0;for(r=0;r<t.length;r++){let e=t[r];e.user?t[i++]=e:N(e)}if(e.context){if(e.count){e.effects||=[],e.effects.push(...t.slice(0,i));return}n()}for(e.effects&&(e.done||!e.count)&&(t=[...e.effects,...t],i+=e.effects.length,delete e.effects),r=0;r<i;r++)N(t[r])}function F(e,t){let n=p&&p.running;n?e.tState=0:e.state=0;for(let r=0;r<e.sources.length;r+=1){let i=e.sources[r];if(i.sources){let e=n?i.tState:i.state;e===l?i!==t&&(!i.updatedAt||i.updatedAt<y)&&N(i):e===u&&F(i,t)}}}function I(e){let t=p&&p.running;for(let n=0;n<e.observers.length;n+=1){let r=e.observers[n];(t?!r.tState:!r.state)&&(t?r.tState=u:r.state=u,r.pure?_.push(r):v.push(r),r.observers&&I(r))}}function L(e){let t;if(e.sources)for(;e.sources.length;){let t=e.sources.pop(),n=e.sourceSlots.pop(),r=t.observers;if(r&&r.length){let e=r.pop(),i=t.observerSlots.pop();n<r.length&&(e.sourceSlots[i]=n,r[n]=e,t.observerSlots[n]=i)}}if(e.tOwned){for(t=e.tOwned.length-1;t>=0;t--)L(e.tOwned[t]);delete e.tOwned}if(p&&p.running&&e.pure)R(e,!0);else if(e.owned){for(t=e.owned.length-1;t>=0;t--)L(e.owned[t]);e.owned=null}if(e.cleanups){for(t=e.cleanups.length-1;t>=0;t--)e.cleanups[t]();e.cleanups=null}p&&p.running?e.tState=0:e.state=0}function R(e,t){if(t||(e.tState=0,p.disposed.add(e)),e.owned)for(let t=0;t<e.owned.length;t++)R(e.owned[t])}function le(e){return e instanceof Error?e:Error(typeof e==`string`?e:`Unknown error`,{cause:e})}function z(e,t,n){try{for(let n of t)n(e)}catch(e){B(e,n&&n.owner||null)}}function B(e,t=f){let n=s&&t&&t.context&&t.context[s],r=le(e);if(!n)throw r;v?v.push({fn(){z(r,n,t)},state:l}):z(r,n,t)}var ue=Symbol(`fallback`);function V(e){for(let t=0;t<e.length;t++)e[t]()}function de(e,t,n={}){let r=[],i=[],o=[],s=0,c=t.length>1?[]:null;return E(()=>V(o)),()=>{let l=e()||[],u=l.length,d,f;return l[a],T(()=>{let e,t,a,m,h,g,_,v,y;if(u===0)s!==0&&(V(o),o=[],r=[],i=[],s=0,c&&=[]),n.fallback&&(r=[ue],i[0]=b(e=>(o[0]=e,n.fallback())),s=1);else if(s===0){for(i=Array(u),f=0;f<u;f++)r[f]=l[f],i[f]=b(p);s=u}else{for(a=Array(u),m=Array(u),c&&(h=Array(u)),g=0,_=Math.min(s,u);g<_&&r[g]===l[g];g++);for(_=s-1,v=u-1;_>=g&&v>=g&&r[_]===l[v];_--,v--)a[v]=i[_],m[v]=o[_],c&&(h[v]=c[_]);for(e=new Map,t=Array(v+1),f=v;f>=g;f--)y=l[f],d=e.get(y),t[f]=d===void 0?-1:d,e.set(y,f);for(d=g;d<=_;d++)y=r[d],f=e.get(y),f!==void 0&&f!==-1?(a[f]=i[d],m[f]=o[d],c&&(h[f]=c[d]),f=t[f],e.set(y,f)):o[d]();for(f=g;f<u;f++)f in a?(i[f]=a[f],o[f]=m[f],c&&(c[f]=h[f],c[f](f))):i[f]=b(p);i=i.slice(0,s=u),r=l.slice(0)}return i});function p(e){if(o[f]=e,c){let[e,n]=x(f);return c[f]=n,t(l[f],e)}return t(l[f])}}}var fe=!1;function H(t,i){if(fe&&e.context){let a=e.context;n(r());let o=T(()=>t(i||{}));return n(a),o}return T(()=>t(i||{}))}var pe=e=>`Stale read from <${e}>.`;function me(e){let t=`fallback`in e&&{fallback:()=>e.fallback};return w(de(()=>e.each,e.children,t||void 0))}function U(e){let t=e.keyed,n=w(()=>e.when,void 0,void 0),r=t?n:w(n,void 0,{equals:(e,t)=>!e==!t});return w(()=>{let i=r();if(i){let a=e.children;return typeof a==`function`&&a.length>0?T(()=>a(t?i:()=>{if(!T(r))throw pe(`Show`);return n()})):a}return e.fallback},void 0,void 0)}var he=e=>w(()=>e());function ge(e,t,n){let r=n.length,i=t.length,a=r,o=0,s=0,c=t[i-1].nextSibling,l=null;for(;o<i||s<a;){if(t[o]===n[s]){o++,s++;continue}for(;t[i-1]===n[a-1];)i--,a--;if(i===o){let t=a<r?s?n[s-1].nextSibling:n[a-s]:c;for(;s<a;)e.insertBefore(n[s++],t)}else if(a===s)for(;o<i;)(!l||!l.has(t[o]))&&t[o].remove(),o++;else if(t[o]===n[a-1]&&n[s]===t[i-1]){let r=t[--i].nextSibling;e.insertBefore(n[s++],t[o++].nextSibling),e.insertBefore(n[--a],r),t[i]=n[a]}else{if(!l){l=new Map;let e=s;for(;e<a;)l.set(n[e],e++)}let r=l.get(t[o]);if(r!=null)if(s<r&&r<a){let c=o,u=1,d;for(;++c<i&&c<a&&!((d=l.get(t[c]))==null||d!==r+u);)u++;if(u>r-s){let i=t[o];for(;s<r;)e.insertBefore(n[s++],i)}else e.replaceChild(n[s++],t[o++])}else o++;else t[o++].remove()}}}var W=`_$DX_DELEGATE`;function _e(e,t,n,r={}){let i;return b(r=>{i=r,t===document?e():J(t,e(),t.firstChild?null:void 0,n)},r.owner),()=>{i(),t.textContent=``}}function G(e,t,n,r){let i,a=()=>{let t=r?document.createElementNS(`http://www.w3.org/1998/Math/MathML`,`template`):document.createElement(`template`);return t.innerHTML=e,n?t.content.firstChild.firstChild:r?t.firstChild:t.content.firstChild},o=t?()=>T(()=>document.importNode(i||=a(),!0)):()=>(i||=a()).cloneNode(!0);return o.cloneNode=o,o}function ve(e,t=window.document){let n=t[W]||(t[W]=new Set);for(let r=0,i=e.length;r<i;r++){let i=e[r];n.has(i)||(n.add(i),t.addEventListener(i,ye))}}function K(e,t,n){Y(e)||(n==null?e.removeAttribute(t):e.setAttribute(t,n))}function q(e,t){Y(e)||(t==null?e.removeAttribute(`class`):e.className=t)}function J(e,t,n,r){if(n!==void 0&&!r&&(r=[]),typeof t!=`function`)return X(e,t,r,n);S(r=>X(e,t(),r,n),r)}function Y(t){return!!e.context&&!e.done&&(!t||t.isConnected)}function ye(t){if(e.registry&&e.events&&e.events.find(([e,n])=>n===t))return;let n=t.target,r=`$$${t.type}`,i=t.target,a=t.currentTarget,o=e=>Object.defineProperty(t,"target",{configurable:!0,value:e}),s=()=>{let e=n[r];if(e&&!n.disabled){let i=n[`${r}Data`];if(i===void 0?e.call(n,t):e.call(n,i,t),t.cancelBubble)return}return n.host&&typeof n.host!=`string`&&!n.host._$host&&n.contains(t.target)&&o(n.host),!0},c=()=>{for(;s()&&(n=n._$host||n.parentNode||n.host););};if(Object.defineProperty(t,"currentTarget",{configurable:!0,get(){return n||document}}),e.registry&&!e.done&&(e.done=_$HY.done=!0),t.composedPath){let e=t.composedPath();o(e[0]);for(let t=0;t<e.length-2&&(n=e[t],s());t++){if(n._$host){n=n._$host,c();break}if(n.parentNode===a)break}}else c();o(i)}function X(e,t,n,r,i){let a=Y(e);if(a){!n&&(n=[...e.childNodes]);let t=[];for(let e=0;e<n.length;e++){let r=n[e];r.nodeType===8&&r.data.slice(0,2)===`!$`?r.remove():t.push(r)}n=t}for(;typeof n==`function`;)n=n();if(t===n)return n;let o=typeof t,s=r!==void 0;if(e=s&&n[0]&&n[0].parentNode||e,o===`string`||o===`number`){if(a||o===`number`&&(t=t.toString(),t===n))return n;if(s){let i=n[0];i&&i.nodeType===3?i.data!==t&&(i.data=t):i=document.createTextNode(t),n=Q(e,n,r,i)}else n=n!==``&&typeof n==`string`?e.firstChild.data=t:e.textContent=t}else if(t==null||o===`boolean`){if(a)return n;n=Q(e,n,r)}else if(o===`function`)return S(()=>{let i=t();for(;typeof i==`function`;)i=i();n=X(e,i,n,r)}),()=>n;else if(Array.isArray(t)){let o=[],c=n&&Array.isArray(n);if(Z(o,t,n,i))return S(()=>n=X(e,o,n,r,!0)),()=>n;if(a){if(!o.length)return n;if(r===void 0)return n=[...e.childNodes];let t=o[0];if(t.parentNode!==e)return n;let i=[t];for(;(t=t.nextSibling)!==r;)i.push(t);return n=i}if(o.length===0){if(n=Q(e,n,r),s)return n}else c?n.length===0?be(e,o,r):ge(e,n,o):(n&&Q(e),be(e,o));n=o}else if(t.nodeType){if(a&&t.parentNode)return n=s?[t]:t;if(Array.isArray(n)){if(s)return n=Q(e,n,r,t);Q(e,n,null,t)}else n==null||n===``||!e.firstChild?e.appendChild(t):e.replaceChild(t,e.firstChild);n=t}return n}function Z(e,t,n,r){let i=!1;for(let a=0,o=t.length;a<o;a++){let o=t[a],s=n&&n[e.length],c;if(!(o==null||o===!0||o===!1))if((c=typeof o)==`object`&&o.nodeType)e.push(o);else if(Array.isArray(o))i=Z(e,o,s)||i;else if(c===`function`)if(r){for(;typeof o==`function`;)o=o();i=Z(e,Array.isArray(o)?o:[o],Array.isArray(s)?s:[s])||i}else e.push(o),i=!0;else{let t=String(o);s&&s.nodeType===3&&s.data===t?e.push(s):e.push(document.createTextNode(t))}}return i}function be(e,t,n=null){for(let r=0,i=t.length;r<i;r++)e.insertBefore(t[r],n)}function Q(e,t,n,r){if(n===void 0)return e.textContent=``;let i=r||document.createTextNode(``);if(t.length){let r=!1;for(let a=t.length-1;a>=0;a--){let o=t[a];if(i!==o){let t=o.parentNode===e;!r&&!a?t?e.replaceChild(i,o):e.insertBefore(i,n):t&&o.remove()}else r=!0}}else e.insertBefore(i,n);return[i]}var xe=class{url;id=null;ws=null;opts;reconnectTimer=null;reconnecting=!1;constructor(e){this.opts=e,this.url=e.url||`ws://localhost:8866/agent-room`,this.id=e.id??null,this.connect()}connect(){this.ws||(this.ws=new WebSocket(this.url),this.ws.onopen=()=>{let e={type:`register`,clientType:`web`};this.id&&(e.id=this.id),this.ws.send(JSON.stringify(e))},this.ws.onmessage=e=>{let t=JSON.parse(e.data);if(t.type===`registered`){this.id=t.id,this.opts.onReady?.(this);return}if(t.type===`sessions-push`){let e=t.payload??[];this.opts.onSessionsPush?.(this,e);return}if(t.type===`error`){this.opts.onError?.(this,t.code||``,t.message||``);return}this.opts.onMessage?.(this,t)},this.ws.onclose=e=>{this.opts.onClose?.(this,e.code,e.reason),this.ws=null,this.tryReconnect()},this.ws.onerror=()=>{})}send(e,t,n){!this.ws||this.ws.readyState!==WebSocket.OPEN||this.ws.send(JSON.stringify({type:e,payload:t,to:n}))}reply(e,t){e.from&&this.send(e.type+`-result`,t,e.from)}disconnect(){this.clearReconnect(),this.reconnecting=!1,this.ws&&=(this.ws.close(1e3,`client disconnect`),null)}get connected(){return this.ws?.readyState===WebSocket.OPEN}clearReconnect(){this.reconnectTimer&&=(clearTimeout(this.reconnectTimer),null)}tryReconnect(){let e=this.opts.reconnectInterval??3e3;e<=0||this.reconnecting||(this.reconnecting=!0,this.reconnectTimer=setTimeout(()=>{this.reconnecting=!1,this.connect()},e))}},Se=G(`<div class=table-wrap><table class=sessions><thead><tr><th>Workspace</th><th>Name</th><th>Status</th><th>Created</th><th>Updated</th><th class=th-actions>Actions</th></tr></thead><tbody>`),Ce=G(`<div class=modal-backdrop><div class=modal role=dialog aria-modal=true aria-label="Confirm deletion"><div class=modal-body></div><div class=modal-actions><button type=button class="btn btn-cancel">Cancel</button><button type=button class="btn btn-confirm">`),we=G(`<div class=modal-backdrop><div class=modal role=dialog aria-modal=true aria-label="Session ID"><h3 class=modal-title>Session ID</h3><div class=modal-id></div><div class=modal-actions><button type=button class="btn btn-confirm">Close`),Te=G(`<div class=app-shell><header class=app-header><div><h1 class=app-title>DeepFish Sessions</h1><p class=app-subtitle></p></div><div class=status-pill><span></span></div></header><section class=panel><div class=panel-header><h2 class=panel-title>Active Sessions<span class=badge>`),Ee=G(`<div class=empty-state><div class=icon>◇</div><div>`),De=G(`<tr><td class="cell-mono cell-workspace"></td><td class=cell-name></td><td><span></span></td><td class=cell-time></td><td class=cell-time></td><td class=cell-actions><button type=button class="btn btn-id">Show ID</button><button type=button class="btn btn-delete">`),Oe={0:`Idle`,1:`Working`},ke={connecting:`is-connecting`,connected:`is-connected`,disconnected:`is-disconnected`,error:`is-error`,ssr:`is-disconnected`},Ae={ssr:`LOADING`,connecting:`CONNECTING`,connected:`CONNECTED`,disconnected:`DISCONNECTED`,error:`ERROR`};function je(e){if(!e)return`-`;let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString()}function Me(){let[e,t]=x([]),[n,r]=x(`ssr`),[i,a]=x(``),[o,s]=x(``),[c,l]=x(``),[u,d]=x(!1),[f,p]=x(``),[m,h]=x(``),g=null;ee(()=>{typeof window>`u`||(r(`connecting`),g=new xe({url:`ws://${window.location.host}/agent-room`,onReady:()=>{r(`connected`),a(``)},onSessionsPush:(e,n)=>{t(n??[]),s(``)},onError:(e,t,n)=>{r(`error`),a(n),s(``)},onClose:()=>{r(`disconnected`),s(``)}}))});let _=e=>{l(e),p(`Are you sure you want to delete session "${e}"? This action cannot be undone.`),d(!0)},v=()=>{let e=c();if(!g||!e){d(!1);return}s(e),d(!1),g.send(`delete-session`,{id:e})},y=()=>{l(``),d(!1)},b=e=>{h(e)},C=()=>{h(``)};return E(()=>g?.disconnect()),(()=>{var t=Te(),r=t.firstChild,a=r.firstChild.nextSibling,s=a.firstChild,l=r.nextSibling,d=l.firstChild.firstChild.firstChild.nextSibling;return J(a,()=>Ae[n()],null),J(d,()=>e().length),J(l,H(U,{get when(){return e().length>0},get fallback(){return(()=>{var e=Ee(),t=e.firstChild.nextSibling;return J(t,(()=>{var e=he(()=>n()===`connected`);return()=>e()?`No active sessions`:n()===`ssr`?`Hydrating…`:`Waiting for data…`})()),e})()},get children(){var t=Se(),n=t.firstChild.firstChild.nextSibling;return J(n,H(me,{get each(){return e()},children:e=>(()=>{var t=De(),n=t.firstChild,r=n.nextSibling,i=r.nextSibling,a=i.firstChild,s=i.nextSibling,c=s.nextSibling,l=c.nextSibling.firstChild,u=l.nextSibling;return J(n,()=>e.workspace),J(r,()=>e.name),J(a,()=>Oe[e.status??0]),J(s,()=>je(e.createdAt)),J(c,()=>je(e.updatedAt)),l.$$click=()=>b(e.id),u.$$click=()=>_(e.id),J(u,()=>o()===e.id?`Deleting...`:`Delete`),S(t=>{var r=e.workspace,i=`status-tag ${e.status===1?`is-online`:`is-offline`}`,s=o()===e.id;return r!==t.e&&K(n,`title`,t.e=r),i!==t.t&&q(a,t.t=i),s!==t.a&&(u.disabled=t.a=s),t},{e:void 0,t:void 0,a:void 0}),t})()})),t}}),null),J(t,H(U,{get when(){return u()},get children(){var e=Ce(),t=e.firstChild.firstChild,n=t.nextSibling.firstChild,r=n.nextSibling;return J(t,f),n.$$click=y,r.$$click=v,J(r,()=>o()===c()?`Deleting...`:`Confirm Delete`),S(()=>r.disabled=o()===c()),e}}),null),J(t,H(U,{get when(){return m()},get children(){var e=we(),t=e.firstChild.firstChild.nextSibling,n=t.nextSibling.firstChild;return J(t,m),n.$$click=C,e}}),null),S(e=>{var t=i(),r=`status-dot ${ke[n()]}`;return t!==e.e&&K(a,`title`,e.e=t),r!==e.t&&q(s,e.t=r),e},{e:void 0,t:void 0}),t})()}ve([`click`]);var $=document.getElementById(`app`);$&&($.innerHTML=``),_e(()=>H(Me,{}),$);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
|
-
<html lang="
|
|
2
|
+
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>DeepFish Sessions</title>
|
|
7
|
-
<!--
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
7
|
+
<!-- Global styles have been moved to src/serve/ui/App.less and imported in App.tsx. -->
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-Cr3CJSQU.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CXCKvQL3.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="app"></div>
|
package/dist/serve/pm2-server.js
CHANGED
|
@@ -8703,8 +8703,8 @@ var import_fs_extra17 = __toESM(require("fs-extra"));
|
|
|
8703
8703
|
var import_path12 = __toESM(require("path"));
|
|
8704
8704
|
|
|
8705
8705
|
// src/agent/AIAgent/index.ts
|
|
8706
|
-
var
|
|
8707
|
-
var
|
|
8706
|
+
var import_langchain17 = require("langchain");
|
|
8707
|
+
var import_deepagents2 = require("deepagents");
|
|
8708
8708
|
|
|
8709
8709
|
// src/agent/AIAgent/utils/langgraph-checkpoint-filesystem/filesystem-saver.ts
|
|
8710
8710
|
var import_runnables = require("@langchain/core/runnables");
|
|
@@ -23265,7 +23265,7 @@ function date4(params) {
|
|
|
23265
23265
|
config(en_default());
|
|
23266
23266
|
|
|
23267
23267
|
// src/agent/AIAgent/index.ts
|
|
23268
|
-
var
|
|
23268
|
+
var import_eventemitter_super2 = require("eventemitter-super");
|
|
23269
23269
|
|
|
23270
23270
|
// src/agent/AIAgent/middleware/eventEmitMiddleware.ts
|
|
23271
23271
|
var import_langchain = require("langchain");
|
|
@@ -23499,7 +23499,6 @@ var executeCommandTool = (0, import_langchain3.tool)(({ command, timeout }) => s
|
|
|
23499
23499
|
var import_langchain4 = require("langchain");
|
|
23500
23500
|
var import_path6 = __toESM(require("path"));
|
|
23501
23501
|
var import_fs_extra7 = __toESM(require("fs-extra"));
|
|
23502
|
-
var _require = require;
|
|
23503
23502
|
async function executeJSCode(code) {
|
|
23504
23503
|
logInfo("Executing JavaScript code: ");
|
|
23505
23504
|
logInfo(code);
|
|
@@ -23510,7 +23509,15 @@ async function executeJSCode(code) {
|
|
|
23510
23509
|
return result || "Code executed successfully, but __main() did not return anything."
|
|
23511
23510
|
})()`;
|
|
23512
23511
|
const fn = new Function("require", wrapped);
|
|
23513
|
-
const
|
|
23512
|
+
const _require = require;
|
|
23513
|
+
const newRequire = (modulePath) => {
|
|
23514
|
+
if (modulePath.startsWith("./")) {
|
|
23515
|
+
const resolvedPath = import_path6.default.resolve(process.cwd(), modulePath);
|
|
23516
|
+
return _require(resolvedPath);
|
|
23517
|
+
}
|
|
23518
|
+
return _require(modulePath);
|
|
23519
|
+
};
|
|
23520
|
+
const result = await fn(newRequire);
|
|
23514
23521
|
return result;
|
|
23515
23522
|
} catch (error51) {
|
|
23516
23523
|
logError(`Error executing code: ${error51.stack}`);
|
|
@@ -24163,6 +24170,11 @@ var builtinTools = [
|
|
|
24163
24170
|
var import_inquirer2 = __toESM(require("inquirer"));
|
|
24164
24171
|
var import_fs_extra16 = __toESM(require("fs-extra"));
|
|
24165
24172
|
|
|
24173
|
+
// src/agent/AIAgent/SubAIAgent.ts
|
|
24174
|
+
var import_langchain16 = require("langchain");
|
|
24175
|
+
var import_deepagents = require("deepagents");
|
|
24176
|
+
var import_eventemitter_super = require("eventemitter-super");
|
|
24177
|
+
|
|
24166
24178
|
// src/serve/service/agent-room/agent-client.ts
|
|
24167
24179
|
var import_ws = __toESM(require("ws"));
|
|
24168
24180
|
|
|
@@ -98,37 +98,42 @@ var AgentRoomWebClient = class {
|
|
|
98
98
|
//#region src/serve/ui/App.tsx
|
|
99
99
|
var _tmpl$ = [
|
|
100
100
|
"<div",
|
|
101
|
-
" class=\"table-wrap\"><table class=\"sessions\"><thead><tr><th>
|
|
101
|
+
" class=\"table-wrap\"><table class=\"sessions\"><thead><tr><th>Workspace</th><th>Name</th><th>Status</th><th>Created</th><th>Updated</th><th class=\"th-actions\">Actions</th></tr></thead><tbody>",
|
|
102
102
|
"</tbody></table></div>"
|
|
103
103
|
], _tmpl$2 = [
|
|
104
104
|
"<div",
|
|
105
|
-
" class=\"modal-backdrop\"><div class=\"modal\" role=\"dialog\" aria-modal=\"true\" aria-label=\"
|
|
106
|
-
"</div><div class=\"modal-actions\"><button type=\"button\" class=\"btn btn-cancel\"
|
|
105
|
+
" class=\"modal-backdrop\"><div class=\"modal\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Confirm deletion\"><div class=\"modal-body\">",
|
|
106
|
+
"</div><div class=\"modal-actions\"><button type=\"button\" class=\"btn btn-cancel\">Cancel</button><button type=\"button\" class=\"btn btn-confirm\"",
|
|
107
107
|
">",
|
|
108
108
|
"</button></div></div></div>"
|
|
109
109
|
], _tmpl$3 = [
|
|
110
110
|
"<div",
|
|
111
|
-
" class=\"
|
|
111
|
+
" class=\"modal-backdrop\"><div class=\"modal\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Session ID\"><h3 class=\"modal-title\">Session ID</h3><div class=\"modal-id\">",
|
|
112
|
+
"</div><div class=\"modal-actions\"><button type=\"button\" class=\"btn btn-confirm\">Close</button></div></div></div>"
|
|
113
|
+
], _tmpl$4 = [
|
|
114
|
+
"<div",
|
|
115
|
+
" class=\"app-shell\"><header class=\"app-header\"><div><h1 class=\"app-title\">DeepFish Sessions</h1><p class=\"app-subtitle\"></p></div><div class=\"status-pill\"",
|
|
112
116
|
"><span class=\"",
|
|
113
117
|
"\"></span><!--$-->",
|
|
114
118
|
"<!--/--></div></header><section class=\"panel\"><div class=\"panel-header\"><h2 class=\"panel-title\">Active Sessions<span class=\"badge\">",
|
|
115
119
|
"</span></h2></div><!--$-->",
|
|
116
120
|
"<!--/--></section><!--$-->",
|
|
121
|
+
"<!--/--><!--$-->",
|
|
117
122
|
"<!--/--></div>"
|
|
118
|
-
], _tmpl$
|
|
123
|
+
], _tmpl$5 = [
|
|
119
124
|
"<div",
|
|
120
125
|
" class=\"empty-state\"><div class=\"icon\">◇</div><div>",
|
|
121
126
|
"</div></div>"
|
|
122
|
-
], _tmpl$
|
|
127
|
+
], _tmpl$6 = [
|
|
123
128
|
"<tr",
|
|
124
|
-
"><td class=\"cell-mono\"
|
|
129
|
+
"><td class=\"cell-mono cell-workspace\"",
|
|
130
|
+
">",
|
|
125
131
|
"</td><td class=\"cell-name\">",
|
|
126
|
-
"</td><td class=\"cell-mono\">",
|
|
127
132
|
"</td><td><span class=\"",
|
|
128
133
|
"\">",
|
|
129
134
|
"</span></td><td class=\"cell-time\">",
|
|
130
135
|
"</td><td class=\"cell-time\">",
|
|
131
|
-
"</td><td class=\"cell-actions\"><button type=\"button\" class=\"btn-delete\"",
|
|
136
|
+
"</td><td class=\"cell-actions\"><button type=\"button\" class=\"btn btn-id\">Show ID</button><button type=\"button\" class=\"btn btn-delete\"",
|
|
132
137
|
">",
|
|
133
138
|
"</button></td></tr>"
|
|
134
139
|
];
|
|
@@ -150,7 +155,7 @@ var STATUS_PILL_TEXT = {
|
|
|
150
155
|
disconnected: "DISCONNECTED",
|
|
151
156
|
error: "ERROR"
|
|
152
157
|
};
|
|
153
|
-
/**
|
|
158
|
+
/** Format an ISO timestamp as a local string, while tolerating invalid values. */
|
|
154
159
|
function formatTime(value) {
|
|
155
160
|
if (!value) return "-";
|
|
156
161
|
const d = new Date(value);
|
|
@@ -165,6 +170,7 @@ function App() {
|
|
|
165
170
|
const [confirmingId, setConfirmingId] = createSignal("");
|
|
166
171
|
const [showConfirm, setShowConfirm] = createSignal(false);
|
|
167
172
|
const [confirmMessage, setConfirmMessage] = createSignal("");
|
|
173
|
+
const [visibleId, setVisibleId] = createSignal("");
|
|
168
174
|
let client = null;
|
|
169
175
|
onMount(() => {
|
|
170
176
|
if (typeof window === "undefined") return;
|
|
@@ -191,19 +197,19 @@ function App() {
|
|
|
191
197
|
});
|
|
192
198
|
});
|
|
193
199
|
onCleanup(() => client?.disconnect());
|
|
194
|
-
return ssr(_tmpl$
|
|
200
|
+
return ssr(_tmpl$4, ssrHydrationKey(), ssrAttribute("title", escape(errorMsg(), true), false), `status-dot ${escape(STATUS_DOT_CLASS[status()], true)}`, escape(STATUS_PILL_TEXT[status()]), escape(sessions().length), escape(createComponent(Show, {
|
|
195
201
|
get when() {
|
|
196
202
|
return sessions().length > 0;
|
|
197
203
|
},
|
|
198
204
|
get fallback() {
|
|
199
|
-
return ssr(_tmpl$
|
|
205
|
+
return ssr(_tmpl$5, ssrHydrationKey(), status() === "connected" ? "No active sessions" : status() === "ssr" ? "Hydrating…" : "Waiting for data…");
|
|
200
206
|
},
|
|
201
207
|
get children() {
|
|
202
208
|
return ssr(_tmpl$, ssrHydrationKey(), escape(createComponent(For, {
|
|
203
209
|
get each() {
|
|
204
210
|
return sessions();
|
|
205
211
|
},
|
|
206
|
-
children: (s) => ssr(_tmpl$
|
|
212
|
+
children: (s) => ssr(_tmpl$6, ssrHydrationKey(), ssrAttribute("title", escape(s.workspace, true), false), escape(s.workspace), escape(s.name), `status-tag ${s.status === 1 ? "is-online" : "is-offline"}`, escape(STATUS_LABEL[s.status ?? 0]), escape(formatTime(s.createdAt)), escape(formatTime(s.updatedAt)), ssrAttribute("disabled", deletingId() === s.id, true), deletingId() === s.id ? "Deleting..." : "Delete")
|
|
207
213
|
})));
|
|
208
214
|
}
|
|
209
215
|
})), escape(createComponent(Show, {
|
|
@@ -211,7 +217,14 @@ function App() {
|
|
|
211
217
|
return showConfirm();
|
|
212
218
|
},
|
|
213
219
|
get children() {
|
|
214
|
-
return ssr(_tmpl$2, ssrHydrationKey(), escape(confirmMessage()), ssrAttribute("disabled", deletingId() === confirmingId(), true), deletingId() === confirmingId() ? "Deleting..." : "
|
|
220
|
+
return ssr(_tmpl$2, ssrHydrationKey(), escape(confirmMessage()), ssrAttribute("disabled", deletingId() === confirmingId(), true), deletingId() === confirmingId() ? "Deleting..." : "Confirm Delete");
|
|
221
|
+
}
|
|
222
|
+
})), escape(createComponent(Show, {
|
|
223
|
+
get when() {
|
|
224
|
+
return visibleId();
|
|
225
|
+
},
|
|
226
|
+
get children() {
|
|
227
|
+
return ssr(_tmpl$3, ssrHydrationKey(), escape(visibleId()));
|
|
215
228
|
}
|
|
216
229
|
})));
|
|
217
230
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deepfish-ai",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.6",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "An efficient AI-driven command-line tool designed to bridge the gap between natural language and operating system commands, file operations, and more. It enables non-developers to quickly generate executable instructions through simple natural language descriptions, significantly improving terminal operation efficiency.",
|
|
6
6
|
"repository": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e={context:void 0,registry:void 0,effects:void 0,done:!1,getContextId(){return t(this.context.count)},getNextContextId(){return t(this.context.count++)}};function t(t){let n=String(t),r=n.length-1;return e.context.id+(r?String.fromCharCode(96+r):``)+n}function n(t){e.context=t}function r(){return{...e.context,id:e.getNextContextId(),count:0}}var i=(e,t)=>e===t,a=Symbol(`solid-track`),o={equals:i},s=null,c=oe,l=1,u=2,d={owned:null,cleanups:null,context:null,owner:null},f=null,p=null,m=null,h=null,g=null,_=null,v=null,y=0;function b(e,t){let n=g,r=f,i=e.length===0,a=t===void 0?r:t,o=i?d:{owned:null,cleanups:null,context:a?a.context:null,owner:a},s=i?e:()=>e(()=>w(()=>L(o)));f=o,g=null;try{return P(s,!0)}finally{g=n,f=r}}function x(e,t){t=t?Object.assign({},o,t):o;let n={value:e,observers:null,observerSlots:null,comparator:t.equals||void 0};return[O.bind(n),e=>(typeof e==`function`&&(e=p&&p.running&&p.sources.has(n)?e(n.tValue):e(n.value)),k(n,e))]}function S(e,t,n){let r=M(e,t,!1,l);m&&p&&p.running?_.push(r):A(r)}function ee(e,t,n){c=ce;let r=M(e,t,!1,l),i=D&&ie(D);i&&(r.suspense=i),(!n||!n.render)&&(r.user=!0),v?v.push(r):A(r)}function C(e,t,n){n=n?Object.assign({},o,n):o;let r=M(e,t,!0,0);return r.observers=null,r.observerSlots=null,r.comparator=n.equals||void 0,m&&p&&p.running?(r.tState=l,_.push(r)):A(r),O.bind(r)}function w(e){if(!h&&g===null)return e();let t=g;g=null;try{return h?h.untrack(e):e()}finally{g=t}}function te(e){ee(()=>w(e))}function T(e){return f===null||(f.cleanups===null?f.cleanups=[e]:f.cleanups.push(e)),e}function ne(e){if(p&&p.running)return e(),p.done;let t=g,n=f;return Promise.resolve().then(()=>{g=t,f=n;let r;return(m||D)&&(r=p||={sources:new Set,effects:[],promises:new Set,disposed:new Set,queue:new Set,running:!0},r.done||=new Promise(e=>r.resolve=e),r.running=!0),P(e,!1),g=f=null,r?r.done:void 0})}var[re,E]=x(!1);function ie(e){let t;return f&&f.context&&(t=f.context[e.id])!==void 0?t:e.defaultValue}var D;function O(){let e=p&&p.running;if(this.sources&&(e?this.tState:this.state))if((e?this.tState:this.state)===l)A(this);else{let e=_;_=null,P(()=>F(this),!1),_=e}if(g){let e=this.observers;if(!e||e[e.length-1]!==g){let t=e?e.length:0;g.sources?(g.sources.push(this),g.sourceSlots.push(t)):(g.sources=[this],g.sourceSlots=[t]),e?(e.push(g),this.observerSlots.push(g.sources.length-1)):(this.observers=[g],this.observerSlots=[g.sources.length-1])}}return e&&p.sources.has(this)?this.tValue:this.value}function k(e,t,n){let r=p&&p.running&&p.sources.has(e)?e.tValue:e.value;if(!e.comparator||!e.comparator(r,t)){if(p){let r=p.running;(r||!n&&p.sources.has(e))&&(p.sources.add(e),e.tValue=t),r||(e.value=t)}else e.value=t;e.observers&&e.observers.length&&P(()=>{for(let t=0;t<e.observers.length;t+=1){let n=e.observers[t],r=p&&p.running;r&&p.disposed.has(n)||((r?!n.tState:!n.state)&&(n.pure?_.push(n):v.push(n),n.observers&&I(n)),r?n.tState=l:n.state=l)}if(_.length>1e6)throw _=[],Error()},!1)}return t}function A(e){if(!e.fn)return;L(e);let t=y;j(e,p&&p.running&&p.sources.has(e)?e.tValue:e.value,t),p&&!p.running&&p.sources.has(e)&&queueMicrotask(()=>{P(()=>{p&&(p.running=!0),g=f=e,j(e,e.tValue,t),g=f=null},!1)})}function j(e,t,n){let r,i=f,a=g;g=f=e;try{r=e.fn(t)}catch(t){return e.pure&&(p&&p.running?(e.tState=l,e.tOwned&&e.tOwned.forEach(L),e.tOwned=void 0):(e.state=l,e.owned&&e.owned.forEach(L),e.owned=null)),e.updatedAt=n+1,B(t)}finally{g=a,f=i}(!e.updatedAt||e.updatedAt<=n)&&(e.updatedAt!=null&&`observers`in e?k(e,r,!0):p&&p.running&&e.pure?(p.sources.has(e)||(e.value=r),p.sources.add(e),e.tValue=r):e.value=r,e.updatedAt=n)}function M(e,t,n,r=l,i){let a={fn:e,state:r,updatedAt:null,owned:null,sources:null,sourceSlots:null,cleanups:null,value:t,owner:f,context:f?f.context:null,pure:n};if(p&&p.running&&(a.state=0,a.tState=r),f===null||f!==d&&(p&&p.running&&f.pure?f.tOwned?f.tOwned.push(a):f.tOwned=[a]:f.owned?f.owned.push(a):f.owned=[a]),h&&a.fn){let e=a.fn,[t,n]=x(void 0,{equals:!1}),r=h.factory(e,n);T(()=>r.dispose());let i,o=()=>ne(n).then(()=>{i&&=(i.dispose(),void 0)});a.fn=n=>(t(),p&&p.running?(i||=h.factory(e,o),i.track(n)):r.track(n))}return a}function N(e){let t=p&&p.running;if((t?e.tState:e.state)===0)return;if((t?e.tState:e.state)===u)return F(e);if(e.suspense&&w(e.suspense.inFallback))return e.suspense.effects.push(e);let n=[e];for(;(e=e.owner)&&(!e.updatedAt||e.updatedAt<y);){if(t&&p.disposed.has(e))return;(t?e.tState:e.state)&&n.push(e)}for(let r=n.length-1;r>=0;r--){if(e=n[r],t){let t=e,i=n[r+1];for(;(t=t.owner)&&t!==i;)if(p.disposed.has(t))return}if((t?e.tState:e.state)===l)A(e);else if((t?e.tState:e.state)===u){let t=_;_=null,P(()=>F(e,n[0]),!1),_=t}}}function P(e,t){if(_)return e();let n=!1;t||(_=[]),v?n=!0:v=[],y++;try{let t=e();return ae(n),t}catch(e){n||(v=null),_=null,B(e)}}function ae(e){if(_&&=(m&&p&&p.running?se(_):oe(_),null),e)return;let t;if(p){if(!p.promises.size&&!p.queue.size){let e=p.sources,n=p.disposed;v.push.apply(v,p.effects),t=p.resolve;for(let e of v)`tState`in e&&(e.state=e.tState),delete e.tState;p=null,P(()=>{for(let e of n)L(e);for(let t of e){if(t.value=t.tValue,t.owned)for(let e=0,n=t.owned.length;e<n;e++)L(t.owned[e]);t.tOwned&&(t.owned=t.tOwned),delete t.tValue,delete t.tOwned,t.tState=0}E(!1)},!1)}else if(p.running){p.running=!1,p.effects.push.apply(p.effects,v),v=null,E(!0);return}}let n=v;v=null,n.length&&P(()=>c(n),!1),t&&t()}function oe(e){for(let t=0;t<e.length;t++)N(e[t])}function se(e){for(let t=0;t<e.length;t++){let n=e[t],r=p.queue;r.has(n)||(r.add(n),m(()=>{r.delete(n),P(()=>{p.running=!0,N(n)},!1),p&&(p.running=!1)}))}}function ce(t){let r,i=0;for(r=0;r<t.length;r++){let e=t[r];e.user?t[i++]=e:N(e)}if(e.context){if(e.count){e.effects||=[],e.effects.push(...t.slice(0,i));return}n()}for(e.effects&&(e.done||!e.count)&&(t=[...e.effects,...t],i+=e.effects.length,delete e.effects),r=0;r<i;r++)N(t[r])}function F(e,t){let n=p&&p.running;n?e.tState=0:e.state=0;for(let r=0;r<e.sources.length;r+=1){let i=e.sources[r];if(i.sources){let e=n?i.tState:i.state;e===l?i!==t&&(!i.updatedAt||i.updatedAt<y)&&N(i):e===u&&F(i,t)}}}function I(e){let t=p&&p.running;for(let n=0;n<e.observers.length;n+=1){let r=e.observers[n];(t?!r.tState:!r.state)&&(t?r.tState=u:r.state=u,r.pure?_.push(r):v.push(r),r.observers&&I(r))}}function L(e){let t;if(e.sources)for(;e.sources.length;){let t=e.sources.pop(),n=e.sourceSlots.pop(),r=t.observers;if(r&&r.length){let e=r.pop(),i=t.observerSlots.pop();n<r.length&&(e.sourceSlots[i]=n,r[n]=e,t.observerSlots[n]=i)}}if(e.tOwned){for(t=e.tOwned.length-1;t>=0;t--)L(e.tOwned[t]);delete e.tOwned}if(p&&p.running&&e.pure)R(e,!0);else if(e.owned){for(t=e.owned.length-1;t>=0;t--)L(e.owned[t]);e.owned=null}if(e.cleanups){for(t=e.cleanups.length-1;t>=0;t--)e.cleanups[t]();e.cleanups=null}p&&p.running?e.tState=0:e.state=0}function R(e,t){if(t||(e.tState=0,p.disposed.add(e)),e.owned)for(let t=0;t<e.owned.length;t++)R(e.owned[t])}function le(e){return e instanceof Error?e:Error(typeof e==`string`?e:`Unknown error`,{cause:e})}function z(e,t,n){try{for(let n of t)n(e)}catch(e){B(e,n&&n.owner||null)}}function B(e,t=f){let n=s&&t&&t.context&&t.context[s],r=le(e);if(!n)throw r;v?v.push({fn(){z(r,n,t)},state:l}):z(r,n,t)}var ue=Symbol(`fallback`);function V(e){for(let t=0;t<e.length;t++)e[t]()}function de(e,t,n={}){let r=[],i=[],o=[],s=0,c=t.length>1?[]:null;return T(()=>V(o)),()=>{let l=e()||[],u=l.length,d,f;return l[a],w(()=>{let e,t,a,m,h,g,_,v,y;if(u===0)s!==0&&(V(o),o=[],r=[],i=[],s=0,c&&=[]),n.fallback&&(r=[ue],i[0]=b(e=>(o[0]=e,n.fallback())),s=1);else if(s===0){for(i=Array(u),f=0;f<u;f++)r[f]=l[f],i[f]=b(p);s=u}else{for(a=Array(u),m=Array(u),c&&(h=Array(u)),g=0,_=Math.min(s,u);g<_&&r[g]===l[g];g++);for(_=s-1,v=u-1;_>=g&&v>=g&&r[_]===l[v];_--,v--)a[v]=i[_],m[v]=o[_],c&&(h[v]=c[_]);for(e=new Map,t=Array(v+1),f=v;f>=g;f--)y=l[f],d=e.get(y),t[f]=d===void 0?-1:d,e.set(y,f);for(d=g;d<=_;d++)y=r[d],f=e.get(y),f!==void 0&&f!==-1?(a[f]=i[d],m[f]=o[d],c&&(h[f]=c[d]),f=t[f],e.set(y,f)):o[d]();for(f=g;f<u;f++)f in a?(i[f]=a[f],o[f]=m[f],c&&(c[f]=h[f],c[f](f))):i[f]=b(p);i=i.slice(0,s=u),r=l.slice(0)}return i});function p(e){if(o[f]=e,c){let[e,n]=x(f);return c[f]=n,t(l[f],e)}return t(l[f])}}}var fe=!1;function H(t,i){if(fe&&e.context){let a=e.context;n(r());let o=w(()=>t(i||{}));return n(a),o}return w(()=>t(i||{}))}var pe=e=>`Stale read from <${e}>.`;function me(e){let t=`fallback`in e&&{fallback:()=>e.fallback};return C(de(()=>e.each,e.children,t||void 0))}function U(e){let t=e.keyed,n=C(()=>e.when,void 0,void 0),r=t?n:C(n,void 0,{equals:(e,t)=>!e==!t});return C(()=>{let i=r();if(i){let a=e.children;return typeof a==`function`&&a.length>0?w(()=>a(t?i:()=>{if(!w(r))throw pe(`Show`);return n()})):a}return e.fallback},void 0,void 0)}var he=e=>C(()=>e());function ge(e,t,n){let r=n.length,i=t.length,a=r,o=0,s=0,c=t[i-1].nextSibling,l=null;for(;o<i||s<a;){if(t[o]===n[s]){o++,s++;continue}for(;t[i-1]===n[a-1];)i--,a--;if(i===o){let t=a<r?s?n[s-1].nextSibling:n[a-s]:c;for(;s<a;)e.insertBefore(n[s++],t)}else if(a===s)for(;o<i;)(!l||!l.has(t[o]))&&t[o].remove(),o++;else if(t[o]===n[a-1]&&n[s]===t[i-1]){let r=t[--i].nextSibling;e.insertBefore(n[s++],t[o++].nextSibling),e.insertBefore(n[--a],r),t[i]=n[a]}else{if(!l){l=new Map;let e=s;for(;e<a;)l.set(n[e],e++)}let r=l.get(t[o]);if(r!=null)if(s<r&&r<a){let c=o,u=1,d;for(;++c<i&&c<a&&!((d=l.get(t[c]))==null||d!==r+u);)u++;if(u>r-s){let i=t[o];for(;s<r;)e.insertBefore(n[s++],i)}else e.replaceChild(n[s++],t[o++])}else o++;else t[o++].remove()}}}var W=`_$DX_DELEGATE`;function _e(e,t,n,r={}){let i;return b(r=>{i=r,t===document?e():q(t,e(),t.firstChild?null:void 0,n)},r.owner),()=>{i(),t.textContent=``}}function G(e,t,n,r){let i,a=()=>{let t=r?document.createElementNS(`http://www.w3.org/1998/Math/MathML`,`template`):document.createElement(`template`);return t.innerHTML=e,n?t.content.firstChild.firstChild:r?t.firstChild:t.content.firstChild},o=t?()=>w(()=>document.importNode(i||=a(),!0)):()=>(i||=a()).cloneNode(!0);return o.cloneNode=o,o}function ve(e,t=window.document){let n=t[W]||(t[W]=new Set);for(let r=0,i=e.length;r<i;r++){let i=e[r];n.has(i)||(n.add(i),t.addEventListener(i,be))}}function ye(e,t,n){J(e)||(n==null?e.removeAttribute(t):e.setAttribute(t,n))}function K(e,t){J(e)||(t==null?e.removeAttribute(`class`):e.className=t)}function q(e,t,n,r){if(n!==void 0&&!r&&(r=[]),typeof t!=`function`)return Y(e,t,r,n);S(r=>Y(e,t(),r,n),r)}function J(t){return!!e.context&&!e.done&&(!t||t.isConnected)}function be(t){if(e.registry&&e.events&&e.events.find(([e,n])=>n===t))return;let n=t.target,r=`$$${t.type}`,i=t.target,a=t.currentTarget,o=e=>Object.defineProperty(t,"target",{configurable:!0,value:e}),s=()=>{let e=n[r];if(e&&!n.disabled){let i=n[`${r}Data`];if(i===void 0?e.call(n,t):e.call(n,i,t),t.cancelBubble)return}return n.host&&typeof n.host!=`string`&&!n.host._$host&&n.contains(t.target)&&o(n.host),!0},c=()=>{for(;s()&&(n=n._$host||n.parentNode||n.host););};if(Object.defineProperty(t,"currentTarget",{configurable:!0,get(){return n||document}}),e.registry&&!e.done&&(e.done=_$HY.done=!0),t.composedPath){let e=t.composedPath();o(e[0]);for(let t=0;t<e.length-2&&(n=e[t],s());t++){if(n._$host){n=n._$host,c();break}if(n.parentNode===a)break}}else c();o(i)}function Y(e,t,n,r,i){let a=J(e);if(a){!n&&(n=[...e.childNodes]);let t=[];for(let e=0;e<n.length;e++){let r=n[e];r.nodeType===8&&r.data.slice(0,2)===`!$`?r.remove():t.push(r)}n=t}for(;typeof n==`function`;)n=n();if(t===n)return n;let o=typeof t,s=r!==void 0;if(e=s&&n[0]&&n[0].parentNode||e,o===`string`||o===`number`){if(a||o===`number`&&(t=t.toString(),t===n))return n;if(s){let i=n[0];i&&i.nodeType===3?i.data!==t&&(i.data=t):i=document.createTextNode(t),n=Z(e,n,r,i)}else n=n!==``&&typeof n==`string`?e.firstChild.data=t:e.textContent=t}else if(t==null||o===`boolean`){if(a)return n;n=Z(e,n,r)}else if(o===`function`)return S(()=>{let i=t();for(;typeof i==`function`;)i=i();n=Y(e,i,n,r)}),()=>n;else if(Array.isArray(t)){let o=[],c=n&&Array.isArray(n);if(X(o,t,n,i))return S(()=>n=Y(e,o,n,r,!0)),()=>n;if(a){if(!o.length)return n;if(r===void 0)return n=[...e.childNodes];let t=o[0];if(t.parentNode!==e)return n;let i=[t];for(;(t=t.nextSibling)!==r;)i.push(t);return n=i}if(o.length===0){if(n=Z(e,n,r),s)return n}else c?n.length===0?xe(e,o,r):ge(e,n,o):(n&&Z(e),xe(e,o));n=o}else if(t.nodeType){if(a&&t.parentNode)return n=s?[t]:t;if(Array.isArray(n)){if(s)return n=Z(e,n,r,t);Z(e,n,null,t)}else n==null||n===``||!e.firstChild?e.appendChild(t):e.replaceChild(t,e.firstChild);n=t}return n}function X(e,t,n,r){let i=!1;for(let a=0,o=t.length;a<o;a++){let o=t[a],s=n&&n[e.length],c;if(!(o==null||o===!0||o===!1))if((c=typeof o)==`object`&&o.nodeType)e.push(o);else if(Array.isArray(o))i=X(e,o,s)||i;else if(c===`function`)if(r){for(;typeof o==`function`;)o=o();i=X(e,Array.isArray(o)?o:[o],Array.isArray(s)?s:[s])||i}else e.push(o),i=!0;else{let t=String(o);s&&s.nodeType===3&&s.data===t?e.push(s):e.push(document.createTextNode(t))}}return i}function xe(e,t,n=null){for(let r=0,i=t.length;r<i;r++)e.insertBefore(t[r],n)}function Z(e,t,n,r){if(n===void 0)return e.textContent=``;let i=r||document.createTextNode(``);if(t.length){let r=!1;for(let a=t.length-1;a>=0;a--){let o=t[a];if(i!==o){let t=o.parentNode===e;!r&&!a?t?e.replaceChild(i,o):e.insertBefore(i,n):t&&o.remove()}else r=!0}}else e.insertBefore(i,n);return[i]}var Se=class{url;id=null;ws=null;opts;reconnectTimer=null;reconnecting=!1;constructor(e){this.opts=e,this.url=e.url||`ws://localhost:8866/agent-room`,this.id=e.id??null,this.connect()}connect(){this.ws||(this.ws=new WebSocket(this.url),this.ws.onopen=()=>{let e={type:`register`,clientType:`web`};this.id&&(e.id=this.id),this.ws.send(JSON.stringify(e))},this.ws.onmessage=e=>{let t=JSON.parse(e.data);if(t.type===`registered`){this.id=t.id,this.opts.onReady?.(this);return}if(t.type===`sessions-push`){let e=t.payload??[];this.opts.onSessionsPush?.(this,e);return}if(t.type===`error`){this.opts.onError?.(this,t.code||``,t.message||``);return}this.opts.onMessage?.(this,t)},this.ws.onclose=e=>{this.opts.onClose?.(this,e.code,e.reason),this.ws=null,this.tryReconnect()},this.ws.onerror=()=>{})}send(e,t,n){!this.ws||this.ws.readyState!==WebSocket.OPEN||this.ws.send(JSON.stringify({type:e,payload:t,to:n}))}reply(e,t){e.from&&this.send(e.type+`-result`,t,e.from)}disconnect(){this.clearReconnect(),this.reconnecting=!1,this.ws&&=(this.ws.close(1e3,`client disconnect`),null)}get connected(){return this.ws?.readyState===WebSocket.OPEN}clearReconnect(){this.reconnectTimer&&=(clearTimeout(this.reconnectTimer),null)}tryReconnect(){let e=this.opts.reconnectInterval??3e3;e<=0||this.reconnecting||(this.reconnecting=!0,this.reconnectTimer=setTimeout(()=>{this.reconnecting=!1,this.connect()},e))}},Ce=G(`<div class=table-wrap><table class=sessions><thead><tr><th>ID</th><th>Name</th><th>Workspace</th><th>Status</th><th>Created</th><th>Updated</th><th class=th-actions>Actions</th></tr></thead><tbody>`),we=G(`<div class=modal-backdrop><div class=modal role=dialog aria-modal=true aria-label=确认删除><div class=modal-body></div><div class=modal-actions><button type=button class="btn btn-cancel">取消</button><button type=button class="btn btn-confirm">`),Te=G(`<div class=app-shell><header class=app-header><div><h1 class=app-title>DeepFish Sessions</h1><p class=app-subtitle>// agent-room · realtime</p></div><div class=status-pill><span></span></div></header><section class=panel><div class=panel-header><h2 class=panel-title>Active Sessions<span class=badge>`),Ee=G(`<div class=empty-state><div class=icon>◇</div><div>`),De=G(`<tr><td class=cell-mono></td><td class=cell-name></td><td class=cell-mono></td><td><span></span></td><td class=cell-time></td><td class=cell-time></td><td class=cell-actions><button type=button class=btn-delete>`),Oe={0:`Idle`,1:`Working`},ke={connecting:`is-connecting`,connected:`is-connected`,disconnected:`is-disconnected`,error:`is-error`,ssr:`is-disconnected`},Ae={ssr:`LOADING`,connecting:`CONNECTING`,connected:`CONNECTED`,disconnected:`DISCONNECTED`,error:`ERROR`};function Q(e){if(!e)return`-`;let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString()}function je(){let[e,t]=x([]),[n,r]=x(`ssr`),[i,a]=x(``),[o,s]=x(``),[c,l]=x(``),[u,d]=x(!1),[f,p]=x(``),m=null;te(()=>{typeof window>`u`||(r(`connecting`),m=new Se({url:`ws://${window.location.host}/agent-room`,onReady:()=>{r(`connected`),a(``)},onSessionsPush:(e,n)=>{t(n??[]),s(``)},onError:(e,t,n)=>{r(`error`),a(n),s(``)},onClose:()=>{r(`disconnected`),s(``)}}))});let h=e=>{l(e),p(`Are you sure you want to delete session "${e}"? This action cannot be undone.`),d(!0)},g=()=>{let e=c();if(!m||!e){d(!1);return}s(e),d(!1),m.send(`delete-session`,{id:e})},_=()=>{l(``),d(!1)};return T(()=>m?.disconnect()),(()=>{var t=Te(),r=t.firstChild,a=r.firstChild.nextSibling,s=a.firstChild,l=r.nextSibling,d=l.firstChild.firstChild.firstChild.nextSibling;return q(a,()=>Ae[n()],null),q(d,()=>e().length),q(l,H(U,{get when(){return e().length>0},get fallback(){return(()=>{var e=Ee(),t=e.firstChild.nextSibling;return q(t,(()=>{var e=he(()=>n()===`connected`);return()=>e()?`No active sessions`:n()===`ssr`?`Hydrating…`:`Waiting for data…`})()),e})()},get children(){var t=Ce(),n=t.firstChild.firstChild.nextSibling;return q(n,H(me,{get each(){return e()},children:e=>(()=>{var t=De(),n=t.firstChild,r=n.nextSibling,i=r.nextSibling,a=i.nextSibling,s=a.firstChild,c=a.nextSibling,l=c.nextSibling,u=l.nextSibling.firstChild;return q(n,()=>e.id),q(r,()=>e.name),q(i,()=>e.workspace),q(s,()=>Oe[e.status??0]),q(c,()=>Q(e.createdAt)),q(l,()=>Q(e.updatedAt)),u.$$click=()=>h(e.id),q(u,()=>o()===e.id?`Deleting...`:`Delete`),S(t=>{var n=`status-tag ${e.status===1?`is-online`:`is-offline`}`,r=o()===e.id;return n!==t.e&&K(s,t.e=n),r!==t.t&&(u.disabled=t.t=r),t},{e:void 0,t:void 0}),t})()})),t}}),null),q(t,H(U,{get when(){return u()},get children(){var e=we(),t=e.firstChild.firstChild,n=t.nextSibling.firstChild,r=n.nextSibling;return q(t,f),n.$$click=_,r.$$click=g,q(r,()=>o()===c()?`Deleting...`:`确认删除`),S(()=>r.disabled=o()===c()),e}}),null),S(e=>{var t=i(),r=`status-dot ${ke[n()]}`;return t!==e.e&&ye(a,`title`,e.e=t),r!==e.t&&K(s,e.t=r),e},{e:void 0,t:void 0}),t})()}ve([`click`]);var $=document.getElementById(`app`);$&&($.innerHTML=``),_e(()=>H(je,{}),$);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
*,:before,:after{box-sizing:border-box}html,body{min-height:100%;margin:0;padding:0}body{color:#2c3e50;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;letter-spacing:.01em;background:#f5f7fa;min-height:100vh;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,Hiragino Sans GB,Microsoft YaHei,sans-serif}.app-shell{max-width:1400px;margin:0 auto;padding:28px 20px 40px}.app-header{border-bottom:1px solid #ffffff0f;justify-content:space-between;align-items:flex-end;gap:24px;margin-bottom:24px;padding-bottom:18px;display:flex}.app-title{letter-spacing:.02em;color:#2c3e50;margin:0;font-size:1.4rem;font-weight:600}.app-subtitle{color:#6b7280;letter-spacing:.06em;margin:6px 0 0;font-family:SF Mono,JetBrains Mono,Consolas,monospace;font-size:.82rem}.status-pill{color:#6b7280;background:#f3f6fb;border:1px solid #e6e6e6;border-radius:999px;align-items:center;gap:8px;padding:6px 12px;font-family:SF Mono,JetBrains Mono,Consolas,monospace;font-size:.78rem;display:inline-flex}.status-dot{background:#94a3b8;border-radius:50%;width:8px;height:8px}.status-dot.is-connected{background:#38bdf8}.status-dot.is-connecting{background:#f59e0b}.status-dot.is-disconnected{background:#cbd5e1}.status-dot.is-error{background:#ef4444}@keyframes pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.55;transform:scale(.85)}}.panel{background:#fff;border:1px solid #e6e6e6;border-radius:10px;position:relative;overflow:hidden;box-shadow:0 6px 18px #1e293b0f}.panel:before{display:none}.panel-header{border-bottom:1px solid #f0f2f5;justify-content:space-between;align-items:center;padding:14px 18px;display:flex}.panel-title{color:#2c3e50;letter-spacing:.02em;align-items:center;gap:10px;margin:0;font-size:.95rem;font-weight:600;display:flex}.panel-title .badge{color:#3b82f6;background:#eef2ff;border:1px solid #3b82f61f;border-radius:6px;padding:2px 8px;font-family:SF Mono,JetBrains Mono,Consolas,monospace;font-size:.72rem;font-weight:500}.table-wrap{width:100%;overflow-x:visible}table.sessions{border-collapse:separate;border-spacing:0;width:100%;font-size:.88rem}table.sessions thead th{text-align:center;color:#6b7280;background:0 0;border-bottom:1px solid #f0f2f5;padding:12px 18px;font-size:.8rem;font-weight:600}table.sessions tbody td{color:#2c3e50;vertical-align:middle;white-space:normal;border-bottom:1px solid #f0f2f5;padding:14px 18px}table.sessions tbody tr{transition:background .16s}table.sessions tbody tr:hover{background:#fbfbfd}table.sessions tbody tr:last-child td{border-bottom:none}table.sessions .th-actions,table.sessions .cell-actions{text-align:center;white-space:nowrap}.btn-delete{color:#ef4444;letter-spacing:.02em;cursor:pointer;background:0 0;border:1px solid #ef44441f;border-radius:6px;align-items:center;gap:6px;padding:8px 14px;font-family:SF Mono,JetBrains Mono,Consolas,monospace;font-size:.86rem;font-weight:600;transition:all .16s;display:inline-flex}.btn-delete:hover{box-shadow:none;background:#ef44440f}.btn-delete:active{transform:translateY(1px)}.btn-delete:disabled{opacity:.4;cursor:not-allowed}.cell-mono{color:#64748b;font-family:SF Mono,JetBrains Mono,Consolas,monospace;font-size:.86rem}.cell-name{color:#2c3e50;font-weight:600}.cell-time{color:#64748b;font-family:SF Mono,JetBrains Mono,Consolas,monospace;font-size:.86rem}.status-tag{letter-spacing:.04em;border-radius:999px;align-items:center;gap:6px;padding:3px 10px;font-family:SF Mono,JetBrains Mono,Consolas,monospace;font-size:.74rem;font-weight:500;display:inline-flex}.status-tag:before{content:"";background:currentColor;border-radius:50%;width:6px;height:6px;box-shadow:0 0 6px}.status-tag.is-online{color:#4ade80;background:#4ade8014;border:1px solid #4ade8040}.status-tag.is-offline{color:#94a3b8;background:#94a3b80f;border:1px solid #94a3b82e}.empty-state{color:#6b7280;flex-direction:column;justify-content:center;align-items:center;gap:10px;padding:60px 20px;font-size:.98rem;display:flex}.empty-state .icon{opacity:.6;font-size:1.6rem}@media (width<=720px){.app-shell{padding:24px 14px 40px}.app-header{flex-direction:column;align-items:flex-start}table.sessions thead th,table.sessions tbody td{padding:10px 12px}}.modal-backdrop{z-index:1200;background:#10182814;justify-content:center;align-items:center;padding:20px;display:flex;position:fixed;inset:0}.modal{background:#fff;border:1px solid #e6e6e6;border-radius:8px;width:100%;max-width:520px;padding:18px;box-shadow:0 8px 30px #1018280f}.modal-body{color:#2c3e50;margin-bottom:18px;font-size:.98rem}.modal-actions{justify-content:flex-end;gap:12px;display:flex}.btn{cursor:pointer;border:none;border-radius:8px;padding:8px 14px;font-weight:600}.btn:disabled{opacity:.6;cursor:not-allowed}.btn-cancel{color:#6b7280;background:0 0;border:1px solid #f0f2f5}.btn-confirm{color:#fff;background:linear-gradient(90deg,#3b82f6,#60a5fa);border:1px solid #3b82f60f;box-shadow:0 6px 18px #3b82f61f}
|