ccpanel 0.1.4 → 0.1.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/dist/{chunk-HRPQYUJV.js → chunk-LZFMCC5M.js} +4 -0
- package/dist/cli.js +138 -50
- package/dist/server/app.js +1 -1
- package/package.json +1 -1
- package/web/dist/assets/index-B5vT_l-U.css +1 -0
- package/web/dist/assets/{index-DtOjAT6i.js → index-XKaR9SwA.js} +27 -30
- package/web/dist/index.html +3 -3
- package/web/dist/assets/index-D8o1BXhX.css +0 -1
|
@@ -371,6 +371,10 @@ import { z as z4 } from "zod";
|
|
|
371
371
|
function projectRoutes(deps) {
|
|
372
372
|
const app = new Hono4();
|
|
373
373
|
app.get("/", async (c) => c.json({ projects: await deps.projects.list() }));
|
|
374
|
+
app.get(
|
|
375
|
+
"/known",
|
|
376
|
+
async (c) => c.json({ projects: await deps.projects.known() })
|
|
377
|
+
);
|
|
374
378
|
app.post("/", async (c) => {
|
|
375
379
|
const { path } = z4.object({ path: z4.string().min(1) }).parse(await c.req.json());
|
|
376
380
|
return c.json({ projects: await deps.projects.add(path) });
|
package/dist/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
assertNoConflict,
|
|
9
9
|
createApp,
|
|
10
10
|
currentMtime
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-LZFMCC5M.js";
|
|
12
12
|
|
|
13
13
|
// src/cli.ts
|
|
14
14
|
import { homedir, networkInterfaces } from "os";
|
|
@@ -447,19 +447,37 @@ var SkillService = class {
|
|
|
447
447
|
};
|
|
448
448
|
|
|
449
449
|
// src/core/project-service.ts
|
|
450
|
+
import { stat as stat2 } from "fs/promises";
|
|
450
451
|
var ProjectService = class {
|
|
451
|
-
constructor(store, registryFile) {
|
|
452
|
+
constructor(store, registryFile, userClaudeJson) {
|
|
452
453
|
this.store = store;
|
|
453
454
|
this.registryFile = registryFile;
|
|
455
|
+
this.userClaudeJson = userClaudeJson;
|
|
454
456
|
}
|
|
455
457
|
store;
|
|
456
458
|
registryFile;
|
|
459
|
+
userClaudeJson;
|
|
457
460
|
async list() {
|
|
458
461
|
const data = await this.store.readJson(
|
|
459
462
|
this.registryFile
|
|
460
463
|
);
|
|
461
464
|
return data?.projects ?? [];
|
|
462
465
|
}
|
|
466
|
+
// Claude Code 在 ~/.claude.json 的 projects 键下记录所有打开过的项目路径,
|
|
467
|
+
// 作为「添加项目」的候选来源;剔除已注册与已删除的目录。
|
|
468
|
+
async known() {
|
|
469
|
+
const data = await this.store.readJson(this.userClaudeJson);
|
|
470
|
+
const registered = new Set(await this.list());
|
|
471
|
+
const out = [];
|
|
472
|
+
for (const p of Object.keys(data?.projects ?? {})) {
|
|
473
|
+
if (registered.has(p)) continue;
|
|
474
|
+
try {
|
|
475
|
+
if ((await stat2(p)).isDirectory()) out.push(p);
|
|
476
|
+
} catch {
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
return out.sort();
|
|
480
|
+
}
|
|
463
481
|
async add(path) {
|
|
464
482
|
const current = await this.list();
|
|
465
483
|
if (!current.includes(path)) current.push(path);
|
|
@@ -504,12 +522,12 @@ var MemoryService = class {
|
|
|
504
522
|
};
|
|
505
523
|
|
|
506
524
|
// src/core/memory-files-service.ts
|
|
507
|
-
import { readdir as readdir3, readFile as readFile5, stat as
|
|
525
|
+
import { readdir as readdir3, readFile as readFile5, stat as stat4 } from "fs/promises";
|
|
508
526
|
import { join as join5 } from "path";
|
|
509
527
|
import matter2 from "gray-matter";
|
|
510
528
|
|
|
511
529
|
// src/core/session-service.ts
|
|
512
|
-
import { readdir as readdir2, readFile as readFile4, stat as
|
|
530
|
+
import { readdir as readdir2, readFile as readFile4, stat as stat3 } from "fs/promises";
|
|
513
531
|
import { join as join4 } from "path";
|
|
514
532
|
var MAX_BLOCK = 1e4;
|
|
515
533
|
var NOISE_PREFIXES = ["<local-command", "<command-", "<system-reminder", "Caveat:"];
|
|
@@ -608,7 +626,7 @@ var SessionService = class {
|
|
|
608
626
|
const out = [];
|
|
609
627
|
for (const name of names) {
|
|
610
628
|
const full = join4(dir, name);
|
|
611
|
-
const st = await
|
|
629
|
+
const st = await stat3(full);
|
|
612
630
|
const { firstPrompt, messageCount } = await this.summarize(full);
|
|
613
631
|
out.push({
|
|
614
632
|
id: name.replace(/\.jsonl$/, ""),
|
|
@@ -720,7 +738,7 @@ var MemoryFilesService = class {
|
|
|
720
738
|
index = await readFile5(full, "utf8");
|
|
721
739
|
continue;
|
|
722
740
|
}
|
|
723
|
-
const st = await
|
|
741
|
+
const st = await stat4(full);
|
|
724
742
|
const fm = await this.parseFront(full, name);
|
|
725
743
|
files.push({ file: name, ...fm, size: st.size, mtime: st.mtimeMs });
|
|
726
744
|
}
|
|
@@ -750,7 +768,7 @@ var MemoryFilesService = class {
|
|
|
750
768
|
};
|
|
751
769
|
|
|
752
770
|
// src/core/plugin-service.ts
|
|
753
|
-
import { readFile as readFile6, readdir as readdir4, stat as
|
|
771
|
+
import { readFile as readFile6, readdir as readdir4, stat as stat5 } from "fs/promises";
|
|
754
772
|
import { isAbsolute as isAbsolute2, join as join6, relative as relative2, resolve as resolve3 } from "path";
|
|
755
773
|
import matter3 from "gray-matter";
|
|
756
774
|
var PluginService = class {
|
|
@@ -759,7 +777,7 @@ var PluginService = class {
|
|
|
759
777
|
}
|
|
760
778
|
store;
|
|
761
779
|
async pathExists(p) {
|
|
762
|
-
return
|
|
780
|
+
return stat5(p).then(() => true).catch(() => false);
|
|
763
781
|
}
|
|
764
782
|
// 插件元数据要尽量容错:单个文件损坏不应让整页报错(启停写入除外)。
|
|
765
783
|
async safeReadJson(file) {
|
|
@@ -1013,7 +1031,7 @@ var PluginService = class {
|
|
|
1013
1031
|
};
|
|
1014
1032
|
|
|
1015
1033
|
// src/core/codex-plugin-service.ts
|
|
1016
|
-
import { readFile as readFile7, readdir as readdir5, stat as
|
|
1034
|
+
import { readFile as readFile7, readdir as readdir5, stat as stat6 } from "fs/promises";
|
|
1017
1035
|
import { isAbsolute as isAbsolute3, join as join7, relative as relative3, resolve as resolve4 } from "path";
|
|
1018
1036
|
import matter4 from "gray-matter";
|
|
1019
1037
|
import { parse as parse2, stringify as stringify2 } from "smol-toml";
|
|
@@ -1028,7 +1046,7 @@ var CodexPluginService = class {
|
|
|
1028
1046
|
}
|
|
1029
1047
|
store;
|
|
1030
1048
|
async pathExists(p) {
|
|
1031
|
-
return
|
|
1049
|
+
return stat6(p).then(() => true).catch(() => false);
|
|
1032
1050
|
}
|
|
1033
1051
|
async readConfig(paths) {
|
|
1034
1052
|
let raw;
|
|
@@ -1260,7 +1278,7 @@ var CodexPluginService = class {
|
|
|
1260
1278
|
}
|
|
1261
1279
|
async setEnabled(paths, id, enabled, baseMtime) {
|
|
1262
1280
|
if (baseMtime !== void 0) {
|
|
1263
|
-
const st = await
|
|
1281
|
+
const st = await stat6(paths.codexConfigToml);
|
|
1264
1282
|
if (Math.abs(st.mtimeMs - baseMtime) > 1) {
|
|
1265
1283
|
throw new Error("\u914D\u7F6E\u6587\u4EF6\u5DF2\u88AB\u5176\u4ED6\u8FDB\u7A0B\u4FEE\u6539\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5");
|
|
1266
1284
|
}
|
|
@@ -1274,7 +1292,7 @@ var CodexPluginService = class {
|
|
|
1274
1292
|
|
|
1275
1293
|
// src/core/codex-memory-service.ts
|
|
1276
1294
|
import Database from "better-sqlite3";
|
|
1277
|
-
import { readFile as readFile8, readdir as readdir6, stat as
|
|
1295
|
+
import { readFile as readFile8, readdir as readdir6, stat as stat7 } from "fs/promises";
|
|
1278
1296
|
import { basename, extname, isAbsolute as isAbsolute4, join as join8, relative as relative4, resolve as resolve5 } from "path";
|
|
1279
1297
|
var CodexDataCompatibilityError = class extends Error {
|
|
1280
1298
|
constructor(message = "Codex \u8BB0\u5FC6\u6570\u636E\u5E93\u683C\u5F0F\u6682\u4E0D\u652F\u6301") {
|
|
@@ -1409,7 +1427,7 @@ var CodexMemoryService = class {
|
|
|
1409
1427
|
for (const entry of entries) {
|
|
1410
1428
|
if (!entry.isFile() || !FILE_EXTENSIONS.has(extname(entry.name))) continue;
|
|
1411
1429
|
const file = join8(paths.codexMemoriesDir, entry.name);
|
|
1412
|
-
const st = await
|
|
1430
|
+
const st = await stat7(file);
|
|
1413
1431
|
out.push({
|
|
1414
1432
|
id: `file:${entry.name}`,
|
|
1415
1433
|
name: entry.name,
|
|
@@ -1435,7 +1453,7 @@ var CodexMemoryService = class {
|
|
|
1435
1453
|
return content.replace(/\s+/g, " ").trim().slice(0, 120);
|
|
1436
1454
|
}
|
|
1437
1455
|
async exists(file) {
|
|
1438
|
-
return
|
|
1456
|
+
return stat7(file).then(() => true).catch((err) => {
|
|
1439
1457
|
if (err.code === "ENOENT") return false;
|
|
1440
1458
|
throw err;
|
|
1441
1459
|
});
|
|
@@ -1443,7 +1461,7 @@ var CodexMemoryService = class {
|
|
|
1443
1461
|
};
|
|
1444
1462
|
|
|
1445
1463
|
// src/core/codex-session-service.ts
|
|
1446
|
-
import { readdir as readdir7, readFile as readFile9, stat as
|
|
1464
|
+
import { readdir as readdir7, readFile as readFile9, stat as stat8 } from "fs/promises";
|
|
1447
1465
|
import { join as join9, resolve as resolve6 } from "path";
|
|
1448
1466
|
var MAX_BLOCK2 = 1e4;
|
|
1449
1467
|
function truncate2(s) {
|
|
@@ -1490,6 +1508,18 @@ function blocksFromContent(content) {
|
|
|
1490
1508
|
}
|
|
1491
1509
|
return out;
|
|
1492
1510
|
}
|
|
1511
|
+
function outputText(output) {
|
|
1512
|
+
if (typeof output === "string") return output;
|
|
1513
|
+
return textFromContent(output);
|
|
1514
|
+
}
|
|
1515
|
+
function summaryText(summary) {
|
|
1516
|
+
if (!Array.isArray(summary)) return "";
|
|
1517
|
+
return summary.map((raw) => {
|
|
1518
|
+
if (!raw || typeof raw !== "object") return "";
|
|
1519
|
+
const s = raw;
|
|
1520
|
+
return typeof s.text === "string" ? s.text : "";
|
|
1521
|
+
}).filter(Boolean).join("\n");
|
|
1522
|
+
}
|
|
1493
1523
|
function parseFunctionArguments(args) {
|
|
1494
1524
|
if (typeof args !== "string") return JSON.stringify(args ?? {}, null, 2);
|
|
1495
1525
|
try {
|
|
@@ -1505,7 +1535,9 @@ var CodexSessionService = class {
|
|
|
1505
1535
|
this.readIndex(paths)
|
|
1506
1536
|
]);
|
|
1507
1537
|
const project = normalizeProjectPath(projectPath);
|
|
1508
|
-
return rollouts.filter(
|
|
1538
|
+
return rollouts.filter(
|
|
1539
|
+
(r) => normalizeProjectPath(r.cwd) === project && r.threadSource !== "subagent"
|
|
1540
|
+
).map((r) => {
|
|
1509
1541
|
const idx = index.get(r.id);
|
|
1510
1542
|
const mtime = idx?.updatedAt ? Date.parse(idx.updatedAt) : r.mtime;
|
|
1511
1543
|
return {
|
|
@@ -1520,12 +1552,38 @@ var CodexSessionService = class {
|
|
|
1520
1552
|
async read(paths, projectPath, id) {
|
|
1521
1553
|
assertSafeId2(id);
|
|
1522
1554
|
const project = normalizeProjectPath(projectPath);
|
|
1523
|
-
const
|
|
1555
|
+
const rollouts = await this.scanRollouts(paths);
|
|
1556
|
+
const found = rollouts.find(
|
|
1524
1557
|
(r) => r.id === id && normalizeProjectPath(r.cwd) === project
|
|
1525
1558
|
);
|
|
1526
1559
|
if (!found) throw new Error(`\u672A\u627E\u5230\u4F1A\u8BDD\uFF1A${id}`);
|
|
1527
1560
|
const parsed = this.parseDetail(await readFile9(found.file, "utf8"));
|
|
1528
|
-
|
|
1561
|
+
const subagents = await this.readSubagents(rollouts, parsed.subagentRefs);
|
|
1562
|
+
return { messages: parsed.messages, subagents, skippedRecords: parsed.skipped };
|
|
1563
|
+
}
|
|
1564
|
+
// 按 sub_agent_activity(started) 引用加载子会话;文件缺失或解析失败均跳过,
|
|
1565
|
+
// 不影响主会话展示。只嵌套一层:子会话内部的 subagentRefs 不再展开。
|
|
1566
|
+
async readSubagents(rollouts, refs) {
|
|
1567
|
+
const out = [];
|
|
1568
|
+
for (const ref of refs) {
|
|
1569
|
+
const rollout = rollouts.find((r) => r.id === ref.threadId);
|
|
1570
|
+
if (!rollout) continue;
|
|
1571
|
+
let parsed;
|
|
1572
|
+
try {
|
|
1573
|
+
parsed = this.parseDetail(await readFile9(rollout.file, "utf8"));
|
|
1574
|
+
} catch {
|
|
1575
|
+
continue;
|
|
1576
|
+
}
|
|
1577
|
+
const firstUser = parsed.messages.find((m) => m.type === "user");
|
|
1578
|
+
out.push({
|
|
1579
|
+
toolUseId: ref.toolUseId,
|
|
1580
|
+
agentId: ref.threadId,
|
|
1581
|
+
agentType: ref.agentPath.split("/").filter(Boolean).pop() ?? "subagent",
|
|
1582
|
+
description: (firstUser?.blocks[0]?.text ?? "").replace(/\s+/g, " ").trim().slice(0, 200),
|
|
1583
|
+
messages: parsed.messages
|
|
1584
|
+
});
|
|
1585
|
+
}
|
|
1586
|
+
return out;
|
|
1529
1587
|
}
|
|
1530
1588
|
async scanRollouts(paths) {
|
|
1531
1589
|
const files = await this.rolloutFiles(paths.codexSessionsDir);
|
|
@@ -1556,12 +1614,13 @@ var CodexSessionService = class {
|
|
|
1556
1614
|
return out;
|
|
1557
1615
|
}
|
|
1558
1616
|
async summarizeRollout(file) {
|
|
1559
|
-
const st = await
|
|
1617
|
+
const st = await stat8(file);
|
|
1560
1618
|
const raw = await readFile9(file, "utf8");
|
|
1561
1619
|
let id = "";
|
|
1562
1620
|
let cwd = "";
|
|
1563
1621
|
let firstPrompt = "";
|
|
1564
1622
|
let messageCount = 0;
|
|
1623
|
+
let threadSource;
|
|
1565
1624
|
for (const line of raw.split("\n")) {
|
|
1566
1625
|
if (!line.trim()) continue;
|
|
1567
1626
|
let obj;
|
|
@@ -1574,6 +1633,7 @@ var CodexSessionService = class {
|
|
|
1574
1633
|
if (obj.type === "session_meta" || payload.type === "session_meta") {
|
|
1575
1634
|
id = String(payload.id ?? id);
|
|
1576
1635
|
cwd = String(payload.cwd ?? cwd);
|
|
1636
|
+
if (payload.thread_source) threadSource = String(payload.thread_source);
|
|
1577
1637
|
continue;
|
|
1578
1638
|
}
|
|
1579
1639
|
if (payload.type === "message") {
|
|
@@ -1589,7 +1649,16 @@ var CodexSessionService = class {
|
|
|
1589
1649
|
id = m?.[1] ?? "";
|
|
1590
1650
|
}
|
|
1591
1651
|
if (!id || !cwd) return void 0;
|
|
1592
|
-
return {
|
|
1652
|
+
return {
|
|
1653
|
+
id,
|
|
1654
|
+
file,
|
|
1655
|
+
cwd,
|
|
1656
|
+
mtime: st.mtimeMs,
|
|
1657
|
+
size: st.size,
|
|
1658
|
+
firstPrompt,
|
|
1659
|
+
messageCount,
|
|
1660
|
+
threadSource
|
|
1661
|
+
};
|
|
1593
1662
|
}
|
|
1594
1663
|
async readIndex(paths) {
|
|
1595
1664
|
const out = /* @__PURE__ */ new Map();
|
|
@@ -1619,8 +1688,22 @@ var CodexSessionService = class {
|
|
|
1619
1688
|
}
|
|
1620
1689
|
parseDetail(raw) {
|
|
1621
1690
|
const messages = [];
|
|
1691
|
+
const subagentRefs = [];
|
|
1622
1692
|
let skipped = 0;
|
|
1623
1693
|
let currentAssistant;
|
|
1694
|
+
let pendingReasoning = "";
|
|
1695
|
+
const ensureAssistant = (timestamp) => {
|
|
1696
|
+
if (!currentAssistant) {
|
|
1697
|
+
currentAssistant = {
|
|
1698
|
+
type: "assistant",
|
|
1699
|
+
role: "assistant",
|
|
1700
|
+
timestamp: timestamp ? String(timestamp) : void 0,
|
|
1701
|
+
blocks: []
|
|
1702
|
+
};
|
|
1703
|
+
messages.push(currentAssistant);
|
|
1704
|
+
}
|
|
1705
|
+
return currentAssistant;
|
|
1706
|
+
};
|
|
1624
1707
|
for (const line of raw.split("\n")) {
|
|
1625
1708
|
if (!line.trim()) continue;
|
|
1626
1709
|
let obj;
|
|
@@ -1631,6 +1714,30 @@ var CodexSessionService = class {
|
|
|
1631
1714
|
continue;
|
|
1632
1715
|
}
|
|
1633
1716
|
const payload = payloadOf(obj);
|
|
1717
|
+
if (payload.type === "agent_reasoning") {
|
|
1718
|
+
const text = String(payload.text ?? "").trim();
|
|
1719
|
+
if (text) pendingReasoning = text;
|
|
1720
|
+
continue;
|
|
1721
|
+
}
|
|
1722
|
+
if (payload.type === "reasoning") {
|
|
1723
|
+
const text = pendingReasoning || summaryText(payload.summary);
|
|
1724
|
+
pendingReasoning = "";
|
|
1725
|
+
ensureAssistant(obj.timestamp).blocks.push({
|
|
1726
|
+
kind: "thinking",
|
|
1727
|
+
text: truncate2(text)
|
|
1728
|
+
});
|
|
1729
|
+
continue;
|
|
1730
|
+
}
|
|
1731
|
+
if (payload.type === "sub_agent_activity") {
|
|
1732
|
+
if (payload.kind === "started" && payload.event_id && payload.agent_thread_id) {
|
|
1733
|
+
subagentRefs.push({
|
|
1734
|
+
toolUseId: String(payload.event_id),
|
|
1735
|
+
threadId: String(payload.agent_thread_id),
|
|
1736
|
+
agentPath: String(payload.agent_path ?? "")
|
|
1737
|
+
});
|
|
1738
|
+
}
|
|
1739
|
+
continue;
|
|
1740
|
+
}
|
|
1634
1741
|
if (payload.type === "message") {
|
|
1635
1742
|
const role = String(payload.role ?? "");
|
|
1636
1743
|
if (role !== "user" && role !== "assistant") continue;
|
|
@@ -1645,45 +1752,26 @@ var CodexSessionService = class {
|
|
|
1645
1752
|
currentAssistant = role === "assistant" ? msg : void 0;
|
|
1646
1753
|
continue;
|
|
1647
1754
|
}
|
|
1648
|
-
if (payload.type === "function_call") {
|
|
1649
|
-
const
|
|
1650
|
-
|
|
1651
|
-
role: "assistant",
|
|
1652
|
-
timestamp: obj.timestamp ? String(obj.timestamp) : void 0,
|
|
1653
|
-
blocks: []
|
|
1654
|
-
};
|
|
1655
|
-
if (!currentAssistant) {
|
|
1656
|
-
messages.push(target);
|
|
1657
|
-
currentAssistant = target;
|
|
1658
|
-
}
|
|
1659
|
-
target.blocks.push({
|
|
1755
|
+
if (payload.type === "function_call" || payload.type === "custom_tool_call") {
|
|
1756
|
+
const args = payload.type === "custom_tool_call" ? payload.input : payload.arguments;
|
|
1757
|
+
ensureAssistant(obj.timestamp).blocks.push({
|
|
1660
1758
|
kind: "tool_use",
|
|
1661
1759
|
name: String(payload.name ?? "tool"),
|
|
1662
|
-
text: truncate2(parseFunctionArguments(
|
|
1760
|
+
text: truncate2(parseFunctionArguments(args)),
|
|
1663
1761
|
toolUseId: payload.call_id ? String(payload.call_id) : void 0
|
|
1664
1762
|
});
|
|
1665
1763
|
continue;
|
|
1666
1764
|
}
|
|
1667
|
-
if (payload.type === "function_call_output") {
|
|
1668
|
-
|
|
1669
|
-
type: "assistant",
|
|
1670
|
-
role: "assistant",
|
|
1671
|
-
timestamp: obj.timestamp ? String(obj.timestamp) : void 0,
|
|
1672
|
-
blocks: []
|
|
1673
|
-
};
|
|
1674
|
-
if (!currentAssistant) {
|
|
1675
|
-
messages.push(target);
|
|
1676
|
-
currentAssistant = target;
|
|
1677
|
-
}
|
|
1678
|
-
target.blocks.push({
|
|
1765
|
+
if (payload.type === "function_call_output" || payload.type === "custom_tool_call_output") {
|
|
1766
|
+
ensureAssistant(obj.timestamp).blocks.push({
|
|
1679
1767
|
kind: "tool_result",
|
|
1680
|
-
text: truncate2(
|
|
1768
|
+
text: truncate2(outputText(payload.output)),
|
|
1681
1769
|
isError: payload.is_error === true,
|
|
1682
1770
|
toolUseId: payload.call_id ? String(payload.call_id) : void 0
|
|
1683
1771
|
});
|
|
1684
1772
|
}
|
|
1685
1773
|
}
|
|
1686
|
-
return { messages, skipped };
|
|
1774
|
+
return { messages, skipped, subagentRefs };
|
|
1687
1775
|
}
|
|
1688
1776
|
};
|
|
1689
1777
|
|
|
@@ -1825,7 +1913,7 @@ var AgentCommandService = class {
|
|
|
1825
1913
|
};
|
|
1826
1914
|
|
|
1827
1915
|
// src/core/sync-service.ts
|
|
1828
|
-
import { cp as cp2, lstat, mkdir as mkdir5, readlink as readlink2, rm as rm3, rmdir, stat as
|
|
1916
|
+
import { cp as cp2, lstat, mkdir as mkdir5, readlink as readlink2, rm as rm3, rmdir, stat as stat9, symlink, unlink } from "fs/promises";
|
|
1829
1917
|
import { dirname as dirname5, join as join11, resolve as resolve7 } from "path";
|
|
1830
1918
|
var SyncService = class {
|
|
1831
1919
|
agentsSkillsDir;
|
|
@@ -1879,7 +1967,7 @@ var SyncService = class {
|
|
|
1879
1967
|
assertSafeName(name);
|
|
1880
1968
|
const src = join11(this.agentsSkillsDir, name);
|
|
1881
1969
|
try {
|
|
1882
|
-
if (!(await
|
|
1970
|
+
if (!(await stat9(src)).isDirectory()) throw new Error();
|
|
1883
1971
|
} catch {
|
|
1884
1972
|
throw new Error(`\u672A\u627E\u5230\u516C\u5171 skill\u300C${name}\u300D`);
|
|
1885
1973
|
}
|
|
@@ -1961,7 +2049,7 @@ async function main() {
|
|
|
1961
2049
|
store,
|
|
1962
2050
|
mcp: new McpService(store),
|
|
1963
2051
|
skills: new SkillService(),
|
|
1964
|
-
projects: new ProjectService(store, registryFile),
|
|
2052
|
+
projects: new ProjectService(store, registryFile, join12(home, ".claude.json")),
|
|
1965
2053
|
memory: new MemoryService(),
|
|
1966
2054
|
memoryFiles: new MemoryFilesService(),
|
|
1967
2055
|
sessions: new SessionService(),
|
package/dist/server/app.js
CHANGED
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.inset-0{top:0;right:0;bottom:0;left:0}.right-0{right:0}.top-0{top:0}.z-40{z-index:40}.mx-1{margin-left:.25rem;margin-right:.25rem}.mb-1{margin-bottom:.25rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-auto{margin-left:auto}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.h-40{height:10rem}.h-5{height:1.25rem}.h-full{height:100%}.min-h-0{min-height:0px}.min-h-\[2\.5rem\]{min-height:2.5rem}.min-h-screen{min-height:100vh}.w-2\/5{width:40%}.w-56{width:14rem}.w-full{width:100%}.w-px{width:1px}.min-w-0{min-width:0px}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-5xl{max-width:64rem}.max-w-6xl{max-width:72rem}.max-w-\[10rem\]{max-width:10rem}.max-w-\[14rem\]{max-width:14rem}.max-w-lg{max-width:32rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.cursor-pointer{cursor:pointer}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-end{justify-content:flex-end}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-amber-600{--tw-border-opacity: 1;border-color:rgb(217 119 6 / var(--tw-border-opacity, 1))}.border-blue-200{--tw-border-opacity: 1;border-color:rgb(191 219 254 / var(--tw-border-opacity, 1))}.border-emerald-200{--tw-border-opacity: 1;border-color:rgb(167 243 208 / var(--tw-border-opacity, 1))}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.border-violet-200{--tw-border-opacity: 1;border-color:rgb(221 214 254 / var(--tw-border-opacity, 1))}.bg-amber-100{--tw-bg-opacity: 1;background-color:rgb(254 243 199 / var(--tw-bg-opacity, 1))}.bg-amber-50{--tw-bg-opacity: 1;background-color:rgb(255 251 235 / var(--tw-bg-opacity, 1))}.bg-amber-600{--tw-bg-opacity: 1;background-color:rgb(217 119 6 / var(--tw-bg-opacity, 1))}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity, 1))}.bg-black\/30{background-color:#0000004d}.bg-blue-100{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.bg-blue-50{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.bg-blue-600{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.bg-emerald-100{--tw-bg-opacity: 1;background-color:rgb(209 250 229 / var(--tw-bg-opacity, 1))}.bg-emerald-50{--tw-bg-opacity: 1;background-color:rgb(236 253 245 / var(--tw-bg-opacity, 1))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.bg-gray-200{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.bg-gray-300{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity, 1))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.bg-green-100{--tw-bg-opacity: 1;background-color:rgb(220 252 231 / var(--tw-bg-opacity, 1))}.bg-red-100{--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1))}.bg-red-50{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.bg-slate-100{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.bg-violet-100{--tw-bg-opacity: 1;background-color:rgb(237 233 254 / var(--tw-bg-opacity, 1))}.bg-violet-50{--tw-bg-opacity: 1;background-color:rgb(245 243 255 / var(--tw-bg-opacity, 1))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.pl-3{padding-left:.75rem}.pr-2{padding-right:.5rem}.pt-4{padding-top:1rem}.text-left{text-align:left}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.normal-case{text-transform:none}.italic{font-style:italic}.text-amber-700{--tw-text-opacity: 1;color:rgb(180 83 9 / var(--tw-text-opacity, 1))}.text-amber-800{--tw-text-opacity: 1;color:rgb(146 64 14 / var(--tw-text-opacity, 1))}.text-blue-600{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.text-emerald-700{--tw-text-opacity: 1;color:rgb(4 120 87 / var(--tw-text-opacity, 1))}.text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.text-gray-800{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.text-green-600{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity, 1))}.text-green-700{--tw-text-opacity: 1;color:rgb(21 128 61 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.text-slate-700{--tw-text-opacity: 1;color:rgb(51 65 85 / var(--tw-text-opacity, 1))}.text-violet-400{--tw-text-opacity: 1;color:rgb(167 139 250 / var(--tw-text-opacity, 1))}.text-violet-500{--tw-text-opacity: 1;color:rgb(139 92 246 / var(--tw-text-opacity, 1))}.text-violet-700{--tw-text-opacity: 1;color:rgb(109 40 217 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.underline{text-decoration-line:underline}.line-through{text-decoration-line:line-through}.opacity-70{opacity:.7}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.hover\:bg-gray-200:hover{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.hover\:text-red-600:hover{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.hover\:text-white:hover{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.hover\:shadow:hover{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.disabled\:opacity-50:disabled{opacity:.5}@media (min-width: 640px){.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width: 1024px){.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-\[18rem_minmax\(0\,1fr\)\]{grid-template-columns:18rem minmax(0,1fr)}}
|