cli-claw-kit 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +245 -0
- package/config/default-groups.json +1 -0
- package/config/global-agents-md.template.md +37 -0
- package/config/mount-allowlist.json +11 -0
- package/container/Dockerfile +160 -0
- package/container/agent-runner/dist/.tsbuildinfo +1 -0
- package/container/agent-runner/dist/agent-definitions.js +22 -0
- package/container/agent-runner/dist/channel-prefixes.js +16 -0
- package/container/agent-runner/dist/codex-config.js +29 -0
- package/container/agent-runner/dist/image-detector.js +96 -0
- package/container/agent-runner/dist/index.js +2587 -0
- package/container/agent-runner/dist/mcp-tools.js +1076 -0
- package/container/agent-runner/dist/stream-event.types.js +5 -0
- package/container/agent-runner/dist/stream-processor.js +867 -0
- package/container/agent-runner/dist/types.js +6 -0
- package/container/agent-runner/dist/utils.js +115 -0
- package/container/agent-runner/package.json +36 -0
- package/container/agent-runner/prompts/security-rules.md +31 -0
- package/container/agent-runner/src/agent-definitions.ts +27 -0
- package/container/agent-runner/src/channel-prefixes.ts +16 -0
- package/container/agent-runner/src/codex-config.ts +40 -0
- package/container/agent-runner/src/image-detector.ts +116 -0
- package/container/agent-runner/src/index.ts +3107 -0
- package/container/agent-runner/src/mcp-tools.ts +1295 -0
- package/container/agent-runner/src/stream-event.types.ts +10 -0
- package/container/agent-runner/src/stream-processor.ts +932 -0
- package/container/agent-runner/src/types.ts +75 -0
- package/container/agent-runner/src/utils.ts +114 -0
- package/container/agent-runner/tsconfig.json +17 -0
- package/container/build.sh +28 -0
- package/container/entrypoint.sh +64 -0
- package/container/skills/agent-browser/SKILL.md +159 -0
- package/container/skills/install-skill/SKILL.md +64 -0
- package/container/skills/post-test-cleanup/SKILL.md +121 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/agent-output-parser.js +459 -0
- package/dist/app-root.js +52 -0
- package/dist/assistant-meta-footer.js +1 -0
- package/dist/auth.js +91 -0
- package/dist/billing.js +694 -0
- package/dist/channel-prefixes.js +16 -0
- package/dist/cli.js +86 -0
- package/dist/commands.js +79 -0
- package/dist/config.js +120 -0
- package/dist/container-runner.js +981 -0
- package/dist/daily-summary.js +210 -0
- package/dist/db.js +3683 -0
- package/dist/dingtalk.js +1347 -0
- package/dist/feishu-markdown-style.js +97 -0
- package/dist/feishu-streaming-card.js +1875 -0
- package/dist/feishu.js +1628 -0
- package/dist/file-manager.js +270 -0
- package/dist/group-queue.js +1070 -0
- package/dist/group-runtime.js +35 -0
- package/dist/host-workspace-cwd.js +85 -0
- package/dist/im-channel.js +384 -0
- package/dist/im-command-utils.js +142 -0
- package/dist/im-downloader.js +45 -0
- package/dist/im-manager.js +527 -0
- package/dist/im-utils.js +53 -0
- package/dist/image-detector.js +96 -0
- package/dist/index.js +5828 -0
- package/dist/logger.js +22 -0
- package/dist/mcp-utils.js +66 -0
- package/dist/message-attachments.js +69 -0
- package/dist/message-notifier.js +36 -0
- package/dist/middleware/auth.js +85 -0
- package/dist/mount-security.js +315 -0
- package/dist/permissions.js +67 -0
- package/dist/project-memory.js +6 -0
- package/dist/provider-pool.js +189 -0
- package/dist/qq.js +826 -0
- package/dist/reset-admin.js +42 -0
- package/dist/routes/admin.js +543 -0
- package/dist/routes/agent-definitions.js +241 -0
- package/dist/routes/agents.js +533 -0
- package/dist/routes/auth.js +675 -0
- package/dist/routes/billing.js +490 -0
- package/dist/routes/browse.js +210 -0
- package/dist/routes/bug-report.js +387 -0
- package/dist/routes/config.js +1868 -0
- package/dist/routes/files.js +671 -0
- package/dist/routes/groups.js +1367 -0
- package/dist/routes/mcp-servers.js +320 -0
- package/dist/routes/memory.js +523 -0
- package/dist/routes/monitor.js +307 -0
- package/dist/routes/skills.js +777 -0
- package/dist/routes/tasks.js +509 -0
- package/dist/routes/usage.js +64 -0
- package/dist/routes/workspace-config.js +458 -0
- package/dist/runtime-build.js +112 -0
- package/dist/runtime-command-handler.js +189 -0
- package/dist/runtime-command-registry.js +1 -0
- package/dist/runtime-config.js +1777 -0
- package/dist/runtime-identity.js +52 -0
- package/dist/schemas.js +590 -0
- package/dist/script-runner.js +64 -0
- package/dist/sdk-query.js +82 -0
- package/dist/skill-utils.js +145 -0
- package/dist/sqlite-compat.js +19 -0
- package/dist/stream-event.types.js +5 -0
- package/dist/streaming-runtime-meta.js +29 -0
- package/dist/task-scheduler.js +695 -0
- package/dist/task-utils.js +13 -0
- package/dist/telegram-pairing.js +59 -0
- package/dist/telegram.js +897 -0
- package/dist/terminal-manager.js +307 -0
- package/dist/tool-step-display.js +1 -0
- package/dist/types.js +1 -0
- package/dist/utils.js +85 -0
- package/dist/web-context.js +161 -0
- package/dist/web.js +1377 -0
- package/dist/wechat-crypto.js +182 -0
- package/dist/wechat.js +589 -0
- package/dist/workspace-runtime-reset.js +35 -0
- package/package.json +107 -0
- package/shared/assistant-meta-footer.ts +127 -0
- package/shared/channel-prefixes.ts +16 -0
- package/shared/dist/assistant-meta-footer.d.ts +29 -0
- package/shared/dist/assistant-meta-footer.js +85 -0
- package/shared/dist/channel-prefixes.d.ts +4 -0
- package/shared/dist/channel-prefixes.js +16 -0
- package/shared/dist/image-detector.d.ts +20 -0
- package/shared/dist/image-detector.js +96 -0
- package/shared/dist/runtime-command-registry.d.ts +38 -0
- package/shared/dist/runtime-command-registry.js +185 -0
- package/shared/dist/stream-event.d.ts +65 -0
- package/shared/dist/stream-event.js +8 -0
- package/shared/dist/tool-step-display.d.ts +4 -0
- package/shared/dist/tool-step-display.js +11 -0
- package/shared/image-detector.ts +116 -0
- package/shared/runtime-command-registry.ts +252 -0
- package/shared/stream-event.ts +67 -0
- package/shared/tool-step-display.ts +21 -0
- package/shared/tsconfig.json +24 -0
- package/web/dist/assets/BillingPage-B1wBR_o-.js +52 -0
- package/web/dist/assets/ChatPage-6GBZ9nXN.css +32 -0
- package/web/dist/assets/ChatPage-BOJcXtaj.js +161 -0
- package/web/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/web/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/web/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/web/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/web/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/web/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/web/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/web/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/web/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/web/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/web/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/web/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/web/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/web/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/web/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/web/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/web/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/web/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/web/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/web/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/web/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/web/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/web/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/web/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/web/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/web/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/web/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/web/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/web/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/web/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/web/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/web/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/web/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/web/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/web/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/web/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/web/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/web/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/web/dist/assets/SettingsPage-DoY7FoZ_.js +153 -0
- package/web/dist/assets/ShareImageDialog-C1ga8b7l.js +22 -0
- package/web/dist/assets/TasksPage-CRivnNsx.js +14 -0
- package/web/dist/assets/_basePickBy-Bf-bSoS9.js +1 -0
- package/web/dist/assets/_baseUniq-zAOaCuKw.js +1 -0
- package/web/dist/assets/arc-Dm9mVQ9U.js +1 -0
- package/web/dist/assets/architectureDiagram-2XIMDMQ5-BLmzX1wr.js +36 -0
- package/web/dist/assets/band-CquvqAHh.js +1 -0
- package/web/dist/assets/blockDiagram-WCTKOSBZ-B9pcqm3j.js +132 -0
- package/web/dist/assets/c4Diagram-IC4MRINW-Cytx1q3b.js +10 -0
- package/web/dist/assets/channel-BOVj73LR.js +1 -0
- package/web/dist/assets/channel-meta-CQD0Pei-.js +41 -0
- package/web/dist/assets/chunk-4BX2VUAB-0ToDr6RE.js +1 -0
- package/web/dist/assets/chunk-55IACEB6-DQDjnXfS.js +1 -0
- package/web/dist/assets/chunk-FMBD7UC4-Di8ABm6c.js +15 -0
- package/web/dist/assets/chunk-JSJVCQXG-BZQN6rnX.js +1 -0
- package/web/dist/assets/chunk-KX2RTZJC-zBbcpaN_.js +1 -0
- package/web/dist/assets/chunk-NQ4KR5QH-BCrLoU88.js +220 -0
- package/web/dist/assets/chunk-QZHKN3VN-Bqk8juan.js +1 -0
- package/web/dist/assets/chunk-WL4C6EOR-D2YX-MHY.js +189 -0
- package/web/dist/assets/classDiagram-VBA2DB6C-DUUoMyaK.js +1 -0
- package/web/dist/assets/classDiagram-v2-RAHNMMFH-DUUoMyaK.js +1 -0
- package/web/dist/assets/clone-BmaCesfa.js +1 -0
- package/web/dist/assets/cose-bilkent-S5V4N54A-CTsv6qQA.js +1 -0
- package/web/dist/assets/cytoscape.esm-BQaXIfA_.js +331 -0
- package/web/dist/assets/dagre-KLK3FWXG-Ci4Jh9nu.js +4 -0
- package/web/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/web/dist/assets/diagram-E7M64L7V-BFRnfTI2.js +24 -0
- package/web/dist/assets/diagram-IFDJBPK2-B7Zhnp0b.js +43 -0
- package/web/dist/assets/diagram-P4PSJMXO-BVyP7nwq.js +24 -0
- package/web/dist/assets/erDiagram-INFDFZHY-NorKdTOF.js +70 -0
- package/web/dist/assets/error-CGD5mp5f.js +1 -0
- package/web/dist/assets/flowDiagram-PKNHOUZH-Ch97nABF.js +162 -0
- package/web/dist/assets/ganttDiagram-A5KZAMGK-BQ2pLWsy.js +292 -0
- package/web/dist/assets/gitGraphDiagram-K3NZZRJ6-bcvnBsD2.js +65 -0
- package/web/dist/assets/graph-CeAEckur.js +1 -0
- package/web/dist/assets/index-CPnL1_qC.js +768 -0
- package/web/dist/assets/index-DVevCbcO.css +10 -0
- package/web/dist/assets/infoDiagram-LFFYTUFH-CcsrFdj-.js +2 -0
- package/web/dist/assets/init-Dmth1JHB.js +1 -0
- package/web/dist/assets/ishikawaDiagram-PHBUUO56-1upyMfHN.js +70 -0
- package/web/dist/assets/journeyDiagram-4ABVD52K-CKUi-V0c.js +139 -0
- package/web/dist/assets/kanban-definition-K7BYSVSG-DOnQwXfL.js +89 -0
- package/web/dist/assets/layout-BmMMqTnJ.js +1 -0
- package/web/dist/assets/linear-DiaJloY5.js +1 -0
- package/web/dist/assets/mermaid.core-BWLV1B2v.js +254 -0
- package/web/dist/assets/mindmap-definition-YRQLILUH-BeAKHVWP.js +68 -0
- package/web/dist/assets/ordinal-DILIJJjt.js +1 -0
- package/web/dist/assets/pieDiagram-SKSYHLDU-DfiMSfWo.js +30 -0
- package/web/dist/assets/quadrantDiagram-337W2JSQ-wZxZOJxd.js +7 -0
- package/web/dist/assets/requirementDiagram-Z7DCOOCP-BK4HHm17.js +73 -0
- package/web/dist/assets/sankeyDiagram-WA2Y5GQK-BX6t2avX.js +10 -0
- package/web/dist/assets/sequenceDiagram-2WXFIKYE-BPQlkbAa.js +145 -0
- package/web/dist/assets/sheet-rI0FfB1g.js +6 -0
- package/web/dist/assets/sliders-horizontal-CuijWFNK.js +6 -0
- package/web/dist/assets/sparkles-BsMYXJoT.js +11 -0
- package/web/dist/assets/square-0CqMX1Q3.js +11 -0
- package/web/dist/assets/stateDiagram-RAJIS63D-DxkV0Vwd.js +1 -0
- package/web/dist/assets/stateDiagram-v2-FVOUBMTO-qLYoiOPe.js +1 -0
- package/web/dist/assets/step-D51IIHGA.js +1 -0
- package/web/dist/assets/tasks-D8JjBTwx.js +1 -0
- package/web/dist/assets/time-O8zIGux3.js +1 -0
- package/web/dist/assets/timeline-definition-YZTLITO2-kNp1DyFc.js +61 -0
- package/web/dist/assets/treemap-KZPCXAKY-CkrClVhk.js +162 -0
- package/web/dist/assets/utils-KGAn0XTg.js +11 -0
- package/web/dist/assets/vennDiagram-LZ73GAT5-CgdzEZz4.js +34 -0
- package/web/dist/assets/xychartDiagram-JWTSCODW-DfYGPfNB.js +7 -0
- package/web/dist/assets/zap-_hKJYy7J.js +6 -0
- package/web/dist/favicon.svg +332 -0
- package/web/dist/fonts/AlibabaPuHuiTi-3-55-Regular.woff2 +0 -0
- package/web/dist/fonts/AlibabaPuHuiTi-3-65-Medium.woff2 +0 -0
- package/web/dist/fonts/AlibabaPuHuiTi-3-75-SemiBold.woff2 +0 -0
- package/web/dist/fonts/DMSans-latin-ext.woff2 +0 -0
- package/web/dist/fonts/DMSans-latin.woff2 +0 -0
- package/web/dist/icons/README.md +20 -0
- package/web/dist/icons/apple-touch-icon-180.png +0 -0
- package/web/dist/icons/icon-128.png +0 -0
- package/web/dist/icons/icon-144.png +0 -0
- package/web/dist/icons/icon-152.png +0 -0
- package/web/dist/icons/icon-192.png +0 -0
- package/web/dist/icons/icon-192.svg +332 -0
- package/web/dist/icons/icon-384.png +0 -0
- package/web/dist/icons/icon-48.png +0 -0
- package/web/dist/icons/icon-512-maskable.png +0 -0
- package/web/dist/icons/icon-512.png +0 -0
- package/web/dist/icons/icon-512.svg +332 -0
- package/web/dist/icons/icon-72.png +0 -0
- package/web/dist/icons/icon-96.png +0 -0
- package/web/dist/icons/loading-logo.svg +332 -0
- package/web/dist/icons/logo-1024.png +0 -0
- package/web/dist/icons/logo-icon.svg +332 -0
- package/web/dist/icons/logo-text.svg +332 -0
- package/web/dist/index.html +30 -0
- package/web/dist/manifest.webmanifest +1 -0
- package/web/dist/registerSW.js +1 -0
- package/web/dist/sw.js +1 -0
- package/web/dist/workbox-08d6266a.js +1 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { exec } from 'child_process';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { GROUPS_DIR } from './config.js';
|
|
4
|
+
import { logger } from './logger.js';
|
|
5
|
+
import { getSystemSettings } from './runtime-config.js';
|
|
6
|
+
let activeScriptCount = 0;
|
|
7
|
+
export function getActiveScriptCount() {
|
|
8
|
+
return activeScriptCount;
|
|
9
|
+
}
|
|
10
|
+
export function hasScriptCapacity() {
|
|
11
|
+
const { maxConcurrentScripts } = getSystemSettings();
|
|
12
|
+
return activeScriptCount < maxConcurrentScripts;
|
|
13
|
+
}
|
|
14
|
+
const MAX_BUFFER = 1024 * 1024; // 1MB
|
|
15
|
+
export async function runScript(command, groupFolder, cwdOverride) {
|
|
16
|
+
const { scriptTimeout } = getSystemSettings();
|
|
17
|
+
const cwd = cwdOverride || path.join(GROUPS_DIR, groupFolder);
|
|
18
|
+
const startTime = Date.now();
|
|
19
|
+
activeScriptCount++;
|
|
20
|
+
try {
|
|
21
|
+
return await new Promise((resolve) => {
|
|
22
|
+
const child = exec(command, {
|
|
23
|
+
cwd,
|
|
24
|
+
timeout: scriptTimeout,
|
|
25
|
+
maxBuffer: MAX_BUFFER,
|
|
26
|
+
env: {
|
|
27
|
+
PATH: process.env.PATH,
|
|
28
|
+
LANG: process.env.LANG || 'en_US.UTF-8',
|
|
29
|
+
TZ: process.env.TZ ||
|
|
30
|
+
Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
31
|
+
GROUP_FOLDER: groupFolder,
|
|
32
|
+
HOME: cwd,
|
|
33
|
+
},
|
|
34
|
+
shell: '/bin/sh',
|
|
35
|
+
}, (error, stdout, stderr) => {
|
|
36
|
+
activeScriptCount--;
|
|
37
|
+
const durationMs = Date.now() - startTime;
|
|
38
|
+
const timedOut = error?.killed === true;
|
|
39
|
+
if (timedOut) {
|
|
40
|
+
logger.warn({ command: command.slice(0, 100), groupFolder, durationMs }, 'Script timed out');
|
|
41
|
+
}
|
|
42
|
+
resolve({
|
|
43
|
+
stdout: stdout.slice(0, MAX_BUFFER),
|
|
44
|
+
stderr: stderr.slice(0, MAX_BUFFER),
|
|
45
|
+
exitCode: timedOut ? null : (child.exitCode ?? (error ? 1 : 0)),
|
|
46
|
+
timedOut,
|
|
47
|
+
durationMs,
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
activeScriptCount--;
|
|
54
|
+
const durationMs = Date.now() - startTime;
|
|
55
|
+
logger.error({ command: command.slice(0, 100), groupFolder, err }, 'Script exec() threw synchronously');
|
|
56
|
+
return {
|
|
57
|
+
stdout: '',
|
|
58
|
+
stderr: err instanceof Error ? err.message : String(err),
|
|
59
|
+
exitCode: 1,
|
|
60
|
+
timedOut: false,
|
|
61
|
+
durationMs,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight Claude Agent SDK wrapper for simple text-in → text-out queries.
|
|
3
|
+
* Replaces all `claude --print` CLI calls so authentication uses the
|
|
4
|
+
* provider configured in the settings page (ANTHROPIC_API_KEY / OAuth / Base URL).
|
|
5
|
+
*/
|
|
6
|
+
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
7
|
+
import { buildClaudeEnvLines, getClaudeProviderConfig, } from './runtime-config.js';
|
|
8
|
+
import { logger } from './logger.js';
|
|
9
|
+
// Mutex: process.env mutation is not re-entrant. Serialize concurrent calls
|
|
10
|
+
// to prevent overlapping env writes from corrupting each other.
|
|
11
|
+
let envLock = Promise.resolve();
|
|
12
|
+
/**
|
|
13
|
+
* Send a prompt to Claude and return the plain-text response.
|
|
14
|
+
* Uses the provider configured in the web settings (not a separate CLI install).
|
|
15
|
+
*
|
|
16
|
+
* @param prompt The user prompt text
|
|
17
|
+
* @param opts.model Override model (defaults to provider config)
|
|
18
|
+
* @param opts.timeout Timeout in ms (default 60 000)
|
|
19
|
+
* @returns The assistant's text response, or null on failure
|
|
20
|
+
*/
|
|
21
|
+
export async function sdkQuery(prompt, opts) {
|
|
22
|
+
// Chain on the lock so only one sdkQuery touches process.env at a time
|
|
23
|
+
let release;
|
|
24
|
+
const acquired = new Promise((r) => (release = r));
|
|
25
|
+
const prevLock = envLock;
|
|
26
|
+
envLock = acquired;
|
|
27
|
+
await prevLock;
|
|
28
|
+
const timeout = opts?.timeout ?? 60_000;
|
|
29
|
+
// Inject provider credentials into process.env for the SDK
|
|
30
|
+
const config = getClaudeProviderConfig();
|
|
31
|
+
const envLines = buildClaudeEnvLines(config);
|
|
32
|
+
const savedEnv = {};
|
|
33
|
+
for (const line of envLines) {
|
|
34
|
+
const eq = line.indexOf('=');
|
|
35
|
+
if (eq <= 0)
|
|
36
|
+
continue;
|
|
37
|
+
const key = line.slice(0, eq);
|
|
38
|
+
const value = line.slice(eq + 1);
|
|
39
|
+
savedEnv[key] = process.env[key];
|
|
40
|
+
process.env[key] = value;
|
|
41
|
+
}
|
|
42
|
+
const abortController = new AbortController();
|
|
43
|
+
const timer = setTimeout(() => abortController.abort(), timeout);
|
|
44
|
+
try {
|
|
45
|
+
const model = opts?.model || config.anthropicModel || undefined;
|
|
46
|
+
let result = '';
|
|
47
|
+
const conversation = query({
|
|
48
|
+
prompt,
|
|
49
|
+
options: {
|
|
50
|
+
...(model && { model }),
|
|
51
|
+
maxTurns: 1,
|
|
52
|
+
allowedTools: [],
|
|
53
|
+
permissionMode: 'bypassPermissions',
|
|
54
|
+
allowDangerouslySkipPermissions: true,
|
|
55
|
+
abortController,
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
for await (const event of conversation) {
|
|
59
|
+
if (event.type === 'result' && event.subtype === 'success') {
|
|
60
|
+
result = event.result;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return result.trim() || null;
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
logger.warn({ err: err.message?.slice(0, 200) }, 'sdkQuery failed');
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
clearTimeout(timer);
|
|
71
|
+
// Restore original env
|
|
72
|
+
for (const [key, original] of Object.entries(savedEnv)) {
|
|
73
|
+
if (original === undefined) {
|
|
74
|
+
delete process.env[key];
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
process.env[key] = original;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
release();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared skill utility functions.
|
|
3
|
+
* Used by both src/routes/skills.ts (user-level) and src/routes/workspace-config.ts (workspace-level).
|
|
4
|
+
*/
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
// --- Functions ---
|
|
8
|
+
export function validateSkillId(id) {
|
|
9
|
+
return /^[\w\-]+$/.test(id);
|
|
10
|
+
}
|
|
11
|
+
export function validateSkillPath(skillsRoot, skillDir) {
|
|
12
|
+
try {
|
|
13
|
+
const realSkillsRoot = fs.realpathSync(skillsRoot);
|
|
14
|
+
const realSkillDir = fs.realpathSync(skillDir);
|
|
15
|
+
const relative = path.relative(realSkillsRoot, realSkillDir);
|
|
16
|
+
return !relative.startsWith('..') && !path.isAbsolute(relative);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function parseFrontmatter(content) {
|
|
23
|
+
const lines = content.split('\n');
|
|
24
|
+
if (lines[0]?.trim() !== '---')
|
|
25
|
+
return {};
|
|
26
|
+
const endIndex = lines.slice(1).findIndex((line) => line.trim() === '---');
|
|
27
|
+
if (endIndex === -1)
|
|
28
|
+
return {};
|
|
29
|
+
const frontmatterLines = lines.slice(1, endIndex + 1);
|
|
30
|
+
const result = {};
|
|
31
|
+
let currentKey = null;
|
|
32
|
+
let currentValue = [];
|
|
33
|
+
let multilineMode = null;
|
|
34
|
+
for (const line of frontmatterLines) {
|
|
35
|
+
const keyMatch = line.match(/^([\w\-]+):\s*(.*)$/);
|
|
36
|
+
if (keyMatch) {
|
|
37
|
+
// Save previous key if exists
|
|
38
|
+
if (currentKey) {
|
|
39
|
+
result[currentKey] = currentValue.join(multilineMode === 'literal' ? '\n' : ' ');
|
|
40
|
+
}
|
|
41
|
+
currentKey = keyMatch[1];
|
|
42
|
+
const value = keyMatch[2].trim();
|
|
43
|
+
if (value === '>') {
|
|
44
|
+
multilineMode = 'folded';
|
|
45
|
+
currentValue = [];
|
|
46
|
+
}
|
|
47
|
+
else if (value === '|') {
|
|
48
|
+
multilineMode = 'literal';
|
|
49
|
+
currentValue = [];
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
result[currentKey] = value;
|
|
53
|
+
currentKey = null;
|
|
54
|
+
currentValue = [];
|
|
55
|
+
multilineMode = null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else if (currentKey && multilineMode) {
|
|
59
|
+
const trimmedLine = line.trimStart();
|
|
60
|
+
if (trimmedLine) {
|
|
61
|
+
currentValue.push(trimmedLine);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Save last key
|
|
66
|
+
if (currentKey) {
|
|
67
|
+
result[currentKey] = currentValue.join(multilineMode === 'literal' ? '\n' : ' ');
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
export function listFiles(dir) {
|
|
72
|
+
try {
|
|
73
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
74
|
+
return entries
|
|
75
|
+
.filter((entry) => !entry.name.startsWith('.'))
|
|
76
|
+
.map((entry) => {
|
|
77
|
+
const fullPath = path.join(dir, entry.name);
|
|
78
|
+
const stats = fs.statSync(fullPath);
|
|
79
|
+
return {
|
|
80
|
+
name: entry.name,
|
|
81
|
+
type: entry.isDirectory() ? 'directory' : 'file',
|
|
82
|
+
size: entry.isDirectory() ? 0 : stats.size,
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
export function scanSkillDirectory(rootDir, source) {
|
|
91
|
+
const skills = [];
|
|
92
|
+
if (!fs.existsSync(rootDir))
|
|
93
|
+
return skills;
|
|
94
|
+
try {
|
|
95
|
+
const entries = fs.readdirSync(rootDir, { withFileTypes: true });
|
|
96
|
+
for (const entry of entries) {
|
|
97
|
+
if (!entry.isDirectory())
|
|
98
|
+
continue;
|
|
99
|
+
const skillDir = path.join(rootDir, entry.name);
|
|
100
|
+
const skillMdPath = path.join(skillDir, 'SKILL.md');
|
|
101
|
+
const skillMdDisabledPath = path.join(skillDir, 'SKILL.md.disabled');
|
|
102
|
+
let enabled = false;
|
|
103
|
+
let skillFilePath = null;
|
|
104
|
+
if (fs.existsSync(skillMdPath)) {
|
|
105
|
+
enabled = true;
|
|
106
|
+
skillFilePath = skillMdPath;
|
|
107
|
+
}
|
|
108
|
+
else if (fs.existsSync(skillMdDisabledPath)) {
|
|
109
|
+
enabled = false;
|
|
110
|
+
skillFilePath = skillMdDisabledPath;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
const content = fs.readFileSync(skillFilePath, 'utf-8');
|
|
117
|
+
const frontmatter = parseFrontmatter(content);
|
|
118
|
+
const stats = fs.statSync(skillDir);
|
|
119
|
+
skills.push({
|
|
120
|
+
id: entry.name,
|
|
121
|
+
name: frontmatter.name || entry.name,
|
|
122
|
+
description: frontmatter.description || '',
|
|
123
|
+
source,
|
|
124
|
+
enabled,
|
|
125
|
+
userInvocable: frontmatter['user-invocable'] === undefined
|
|
126
|
+
? true
|
|
127
|
+
: frontmatter['user-invocable'] !== 'false',
|
|
128
|
+
allowedTools: frontmatter['allowed-tools']
|
|
129
|
+
? frontmatter['allowed-tools'].split(',').map((t) => t.trim())
|
|
130
|
+
: [],
|
|
131
|
+
argumentHint: frontmatter['argument-hint'] || null,
|
|
132
|
+
updatedAt: stats.mtime.toISOString(),
|
|
133
|
+
files: listFiles(skillDir),
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
// Skip malformed skills
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
// Skip if directory is not readable
|
|
143
|
+
}
|
|
144
|
+
return skills;
|
|
145
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite 兼容层:Bun 用 bun:sqlite,Node.js 用 better-sqlite3
|
|
3
|
+
*
|
|
4
|
+
* 两者 API 几乎一致(prepare/run/get/all/exec/transaction),
|
|
5
|
+
* 唯一差异是 import 路径和 pragma() 方法(Bun 无此方法,用 exec 替代)。
|
|
6
|
+
*/
|
|
7
|
+
const isBun = typeof globalThis.Bun !== 'undefined';
|
|
8
|
+
let DatabaseConstructor;
|
|
9
|
+
if (isBun) {
|
|
10
|
+
// 动态字符串阻止 tsc 尝试解析 bun:sqlite 模块
|
|
11
|
+
const modName = 'bun:sqlite';
|
|
12
|
+
const mod = await import(modName);
|
|
13
|
+
DatabaseConstructor = mod.Database;
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
const mod = await import('better-sqlite3');
|
|
17
|
+
DatabaseConstructor = mod.default;
|
|
18
|
+
}
|
|
19
|
+
export default DatabaseConstructor;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export function normalizeStreamingStatusText(statusText) {
|
|
2
|
+
if (typeof statusText !== 'string')
|
|
3
|
+
return null;
|
|
4
|
+
const trimmed = statusText.trim();
|
|
5
|
+
if (!trimmed)
|
|
6
|
+
return null;
|
|
7
|
+
if (trimmed === 'usage_updated')
|
|
8
|
+
return null;
|
|
9
|
+
return trimmed;
|
|
10
|
+
}
|
|
11
|
+
export function buildProvisionalTokenUsage(startedAtMs) {
|
|
12
|
+
const durationMs = Math.max(0, Date.now() - startedAtMs);
|
|
13
|
+
return {
|
|
14
|
+
inputTokens: 0,
|
|
15
|
+
outputTokens: 0,
|
|
16
|
+
cacheReadInputTokens: 0,
|
|
17
|
+
cacheCreationInputTokens: 0,
|
|
18
|
+
costUSD: 0,
|
|
19
|
+
durationMs,
|
|
20
|
+
numTurns: 1,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export function serializeAssistantTokenUsage(tokenUsage) {
|
|
24
|
+
if (!tokenUsage)
|
|
25
|
+
return undefined;
|
|
26
|
+
return typeof tokenUsage === 'string'
|
|
27
|
+
? tokenUsage
|
|
28
|
+
: JSON.stringify(tokenUsage);
|
|
29
|
+
}
|