siclaw 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (270) hide show
  1. package/README.md +75 -114
  2. package/dist/agentbox/gateway-client.d.ts +2 -1
  3. package/dist/agentbox/gateway-client.js +6 -2
  4. package/dist/agentbox/gateway-client.js.map +1 -1
  5. package/dist/agentbox/http-server.js +184 -19
  6. package/dist/agentbox/http-server.js.map +1 -1
  7. package/dist/agentbox/resource-handlers.d.ts +1 -0
  8. package/dist/agentbox/resource-handlers.js +23 -23
  9. package/dist/agentbox/resource-handlers.js.map +1 -1
  10. package/dist/agentbox/session.js +85 -5
  11. package/dist/agentbox/session.js.map +1 -1
  12. package/dist/agentbox-main.d.ts +2 -1
  13. package/dist/agentbox-main.js +65 -18
  14. package/dist/agentbox-main.js.map +1 -1
  15. package/dist/cli-credentials.d.ts +1 -0
  16. package/dist/cli-credentials.js +109 -0
  17. package/dist/cli-credentials.js.map +1 -0
  18. package/dist/cli-first-run.d.ts +11 -0
  19. package/dist/cli-first-run.js +99 -0
  20. package/dist/cli-first-run.js.map +1 -0
  21. package/dist/cli-main.js +33 -11
  22. package/dist/cli-main.js.map +1 -1
  23. package/dist/cli-setup.d.ts +5 -11
  24. package/dist/cli-setup.js +12 -225
  25. package/dist/cli-setup.js.map +1 -1
  26. package/dist/core/agent-factory.d.ts +4 -0
  27. package/dist/core/agent-factory.js +102 -151
  28. package/dist/core/agent-factory.js.map +1 -1
  29. package/dist/core/config.d.ts +10 -3
  30. package/dist/core/config.js +11 -95
  31. package/dist/core/config.js.map +1 -1
  32. package/dist/core/extensions/deep-investigation.d.ts +2 -1
  33. package/dist/core/extensions/deep-investigation.js +144 -24
  34. package/dist/core/extensions/deep-investigation.js.map +1 -1
  35. package/dist/core/extensions/setup.d.ts +8 -0
  36. package/dist/core/extensions/setup.js +669 -0
  37. package/dist/core/extensions/setup.js.map +1 -0
  38. package/dist/core/llm-proxy.js +7 -3
  39. package/dist/core/llm-proxy.js.map +1 -1
  40. package/dist/core/mcp-client.d.ts +0 -10
  41. package/dist/core/mcp-client.js +0 -65
  42. package/dist/core/mcp-client.js.map +1 -1
  43. package/dist/core/prompt.d.ts +1 -1
  44. package/dist/core/prompt.js +42 -5
  45. package/dist/core/prompt.js.map +1 -1
  46. package/dist/core/provider-presets.d.ts +14 -0
  47. package/dist/core/provider-presets.js +81 -0
  48. package/dist/core/provider-presets.js.map +1 -0
  49. package/dist/cron/cron-coordinator.d.ts +2 -0
  50. package/dist/cron/cron-coordinator.js +46 -14
  51. package/dist/cron/cron-coordinator.js.map +1 -1
  52. package/dist/cron/cron-executor.js +33 -8
  53. package/dist/cron/cron-executor.js.map +1 -1
  54. package/dist/cron/cron-scheduler.d.ts +1 -1
  55. package/dist/cron/gateway-client.d.ts +5 -0
  56. package/dist/cron/gateway-client.js +43 -8
  57. package/dist/cron/gateway-client.js.map +1 -1
  58. package/dist/cron-main.js +39 -9
  59. package/dist/cron-main.js.map +1 -1
  60. package/dist/gateway/agentbox/client.d.ts +11 -0
  61. package/dist/gateway/agentbox/client.js +18 -0
  62. package/dist/gateway/agentbox/client.js.map +1 -1
  63. package/dist/gateway/agentbox/k8s-spawner.d.ts +11 -2
  64. package/dist/gateway/agentbox/k8s-spawner.js +95 -52
  65. package/dist/gateway/agentbox/k8s-spawner.js.map +1 -1
  66. package/dist/gateway/agentbox/local-spawner.d.ts +1 -1
  67. package/dist/gateway/agentbox/local-spawner.js +4 -2
  68. package/dist/gateway/agentbox/local-spawner.js.map +1 -1
  69. package/dist/gateway/agentbox/manager.d.ts +0 -10
  70. package/dist/gateway/agentbox/manager.js +11 -30
  71. package/dist/gateway/agentbox/manager.js.map +1 -1
  72. package/dist/gateway/agentbox/types.d.ts +6 -4
  73. package/dist/gateway/cron/cron-service.d.ts +49 -0
  74. package/dist/gateway/cron/cron-service.js +259 -0
  75. package/dist/gateway/cron/cron-service.js.map +1 -0
  76. package/dist/gateway/db/init-schema.js +44 -0
  77. package/dist/gateway/db/init-schema.js.map +1 -1
  78. package/dist/gateway/db/migrate-sqlite.js +73 -4
  79. package/dist/gateway/db/migrate-sqlite.js.map +1 -1
  80. package/dist/gateway/db/repositories/chat-repo.d.ts +56 -2
  81. package/dist/gateway/db/repositories/chat-repo.js +132 -2
  82. package/dist/gateway/db/repositories/chat-repo.js.map +1 -1
  83. package/dist/gateway/db/repositories/config-repo.d.ts +31 -2
  84. package/dist/gateway/db/repositories/config-repo.js +57 -7
  85. package/dist/gateway/db/repositories/config-repo.js.map +1 -1
  86. package/dist/gateway/db/repositories/env-repo.d.ts +14 -0
  87. package/dist/gateway/db/repositories/env-repo.js +15 -2
  88. package/dist/gateway/db/repositories/env-repo.js.map +1 -1
  89. package/dist/gateway/db/repositories/model-config-repo.d.ts +1 -1
  90. package/dist/gateway/db/repositories/model-config-repo.js +26 -12
  91. package/dist/gateway/db/repositories/model-config-repo.js.map +1 -1
  92. package/dist/gateway/db/repositories/skill-repo.d.ts +0 -5
  93. package/dist/gateway/db/repositories/skill-review-repo.d.ts +1 -0
  94. package/dist/gateway/db/repositories/skill-review-repo.js +4 -1
  95. package/dist/gateway/db/repositories/skill-review-repo.js.map +1 -1
  96. package/dist/gateway/db/repositories/skill-version-repo.js +0 -1
  97. package/dist/gateway/db/repositories/skill-version-repo.js.map +1 -1
  98. package/dist/gateway/db/repositories/system-config-repo.d.ts +1 -1
  99. package/dist/gateway/db/repositories/system-config-repo.js +2 -1
  100. package/dist/gateway/db/repositories/system-config-repo.js.map +1 -1
  101. package/dist/gateway/db/repositories/user-env-config-repo.d.ts +13 -0
  102. package/dist/gateway/db/repositories/user-env-config-repo.js +11 -0
  103. package/dist/gateway/db/repositories/user-env-config-repo.js.map +1 -1
  104. package/dist/gateway/db/repositories/workspace-repo.d.ts +3 -2
  105. package/dist/gateway/db/repositories/workspace-repo.js +6 -2
  106. package/dist/gateway/db/repositories/workspace-repo.js.map +1 -1
  107. package/dist/gateway/db/schema-mysql.d.ts +473 -51
  108. package/dist/gateway/db/schema-mysql.js +35 -4
  109. package/dist/gateway/db/schema-mysql.js.map +1 -1
  110. package/dist/gateway/db/schema-sqlite.d.ts +522 -57
  111. package/dist/gateway/db/schema-sqlite.js +38 -6
  112. package/dist/gateway/db/schema-sqlite.js.map +1 -1
  113. package/dist/gateway/db/schema.d.ts +471 -51
  114. package/dist/gateway/db/schema.js +1 -1
  115. package/dist/gateway/db/schema.js.map +1 -1
  116. package/dist/gateway/metrics-aggregator.d.ts +65 -0
  117. package/dist/gateway/metrics-aggregator.js +244 -0
  118. package/dist/gateway/metrics-aggregator.js.map +1 -0
  119. package/dist/gateway/plugins/channel-bridge.d.ts +4 -1
  120. package/dist/gateway/plugins/channel-bridge.js +78 -86
  121. package/dist/gateway/plugins/channel-bridge.js.map +1 -1
  122. package/dist/gateway/rpc-methods.d.ts +4 -2
  123. package/dist/gateway/rpc-methods.js +962 -163
  124. package/dist/gateway/rpc-methods.js.map +1 -1
  125. package/dist/gateway/security/cert-manager.d.ts +2 -2
  126. package/dist/gateway/security/cert-manager.js +4 -2
  127. package/dist/gateway/security/cert-manager.js.map +1 -1
  128. package/dist/gateway/server.d.ts +4 -8
  129. package/dist/gateway/server.js +297 -261
  130. package/dist/gateway/server.js.map +1 -1
  131. package/dist/gateway/skills/file-writer.js +17 -11
  132. package/dist/gateway/skills/file-writer.js.map +1 -1
  133. package/dist/gateway/skills/script-evaluator.js +12 -9
  134. package/dist/gateway/skills/script-evaluator.js.map +1 -1
  135. package/dist/gateway/web/dist/assets/index-0p17ZeTP.js +740 -0
  136. package/dist/gateway/web/dist/assets/index-9eP6nPUq.js +741 -0
  137. package/dist/gateway/web/dist/assets/index-9eP6nPUq.js.map +1 -0
  138. package/dist/gateway/web/dist/assets/index-CAmSY91d.js +675 -0
  139. package/dist/gateway/web/dist/assets/index-DMFEh8Pp.css +1 -0
  140. package/dist/gateway/web/dist/assets/index-DyowBCEj.css +1 -0
  141. package/dist/gateway/web/dist/assets/index-PDK5JJDO.css +1 -0
  142. package/dist/gateway/web/dist/index.html +2 -2
  143. package/dist/gateway-main.js +27 -10
  144. package/dist/gateway-main.js.map +1 -1
  145. package/dist/memory/embeddings.js +5 -4
  146. package/dist/memory/embeddings.js.map +1 -1
  147. package/dist/memory/indexer.d.ts +23 -3
  148. package/dist/memory/indexer.js +235 -23
  149. package/dist/memory/indexer.js.map +1 -1
  150. package/dist/memory/schema.js +15 -1
  151. package/dist/memory/schema.js.map +1 -1
  152. package/dist/memory/types.d.ts +18 -0
  153. package/dist/memory/types.js +6 -1
  154. package/dist/memory/types.js.map +1 -1
  155. package/dist/shared/detect-language.d.ts +12 -0
  156. package/dist/shared/detect-language.js +78 -0
  157. package/dist/shared/detect-language.js.map +1 -0
  158. package/dist/shared/diagnostic-events.d.ts +70 -0
  159. package/dist/shared/diagnostic-events.js +38 -0
  160. package/dist/shared/diagnostic-events.js.map +1 -0
  161. package/dist/shared/local-collector.d.ts +56 -0
  162. package/dist/shared/local-collector.js +284 -0
  163. package/dist/shared/local-collector.js.map +1 -0
  164. package/dist/shared/metrics-types.d.ts +64 -0
  165. package/dist/shared/metrics-types.js +25 -0
  166. package/dist/shared/metrics-types.js.map +1 -0
  167. package/dist/shared/metrics.d.ts +19 -0
  168. package/dist/shared/metrics.js +185 -0
  169. package/dist/shared/metrics.js.map +1 -0
  170. package/dist/shared/path-utils.d.ts +15 -0
  171. package/dist/shared/path-utils.js +23 -0
  172. package/dist/shared/path-utils.js.map +1 -0
  173. package/dist/shared/retry.d.ts +35 -0
  174. package/dist/shared/retry.js +61 -0
  175. package/dist/shared/retry.js.map +1 -0
  176. package/dist/tools/command-sets.d.ts +18 -2
  177. package/dist/tools/command-sets.js +207 -32
  178. package/dist/tools/command-sets.js.map +1 -1
  179. package/dist/tools/command-validator.d.ts +56 -0
  180. package/dist/tools/command-validator.js +357 -0
  181. package/dist/tools/command-validator.js.map +1 -0
  182. package/dist/tools/create-skill.js +26 -1
  183. package/dist/tools/create-skill.js.map +1 -1
  184. package/dist/tools/credential-list.js +1 -23
  185. package/dist/tools/credential-list.js.map +1 -1
  186. package/dist/tools/credential-manager.d.ts +98 -0
  187. package/dist/tools/credential-manager.js +313 -0
  188. package/dist/tools/credential-manager.js.map +1 -0
  189. package/dist/tools/deep-search/engine.js +184 -127
  190. package/dist/tools/deep-search/engine.js.map +1 -1
  191. package/dist/tools/deep-search/prompts.d.ts +10 -2
  192. package/dist/tools/deep-search/prompts.js +37 -36
  193. package/dist/tools/deep-search/prompts.js.map +1 -1
  194. package/dist/tools/deep-search/schemas.d.ts +87 -0
  195. package/dist/tools/deep-search/schemas.js +85 -0
  196. package/dist/tools/deep-search/schemas.js.map +1 -0
  197. package/dist/tools/deep-search/sub-agent.d.ts +21 -0
  198. package/dist/tools/deep-search/sub-agent.js +153 -4
  199. package/dist/tools/deep-search/sub-agent.js.map +1 -1
  200. package/dist/tools/deep-search/tool.js +1 -0
  201. package/dist/tools/deep-search/tool.js.map +1 -1
  202. package/dist/tools/deep-search/types.d.ts +2 -0
  203. package/dist/tools/deep-search/types.js.map +1 -1
  204. package/dist/tools/dp-tools.js +29 -5
  205. package/dist/tools/dp-tools.js.map +1 -1
  206. package/dist/tools/exec-utils.d.ts +85 -0
  207. package/dist/tools/exec-utils.js +294 -0
  208. package/dist/tools/exec-utils.js.map +1 -0
  209. package/dist/tools/fork-skill.js +14 -2
  210. package/dist/tools/fork-skill.js.map +1 -1
  211. package/dist/tools/investigation-feedback.d.ts +3 -0
  212. package/dist/tools/investigation-feedback.js +71 -0
  213. package/dist/tools/investigation-feedback.js.map +1 -0
  214. package/dist/tools/manage-schedule.js +16 -6
  215. package/dist/tools/manage-schedule.js.map +1 -1
  216. package/dist/tools/netns-script.js +27 -281
  217. package/dist/tools/netns-script.js.map +1 -1
  218. package/dist/tools/node-exec.d.ts +2 -14
  219. package/dist/tools/node-exec.js +18 -225
  220. package/dist/tools/node-exec.js.map +1 -1
  221. package/dist/tools/node-script.js +14 -168
  222. package/dist/tools/node-script.js.map +1 -1
  223. package/dist/tools/pod-exec.d.ts +1 -1
  224. package/dist/tools/pod-exec.js +10 -26
  225. package/dist/tools/pod-exec.js.map +1 -1
  226. package/dist/tools/pod-nsenter-exec.js +21 -225
  227. package/dist/tools/pod-nsenter-exec.js.map +1 -1
  228. package/dist/tools/pod-script.js +10 -19
  229. package/dist/tools/pod-script.js.map +1 -1
  230. package/dist/tools/restricted-bash.d.ts +1 -17
  231. package/dist/tools/restricted-bash.js +38 -252
  232. package/dist/tools/restricted-bash.js.map +1 -1
  233. package/dist/tools/run-skill.d.ts +3 -1
  234. package/dist/tools/run-skill.js +21 -1
  235. package/dist/tools/run-skill.js.map +1 -1
  236. package/dist/tools/script-resolver.d.ts +3 -1
  237. package/dist/tools/script-resolver.js +74 -30
  238. package/dist/tools/script-resolver.js.map +1 -1
  239. package/dist/tools/update-skill.js +17 -6
  240. package/dist/tools/update-skill.js.map +1 -1
  241. package/package.json +8 -6
  242. package/siclaw.mjs +10 -1
  243. package/skills/core/cluster-events/SKILL.md +1 -1
  244. package/skills/core/deep-investigation/SKILL.md +11 -0
  245. package/skills/core/deployment-rollout-debug/SKILL.md +1 -1
  246. package/skills/core/dns-debug/SKILL.md +1 -0
  247. package/skills/core/meta.json +12 -1
  248. package/skills/core/networkpolicy-debug/SKILL.md +332 -0
  249. package/skills/core/node-logs/scripts/get-node-logs.sh +19 -9
  250. package/skills/core/pod-pending-debug/SKILL.md +1 -0
  251. package/skills/core/quota-debug/SKILL.md +203 -0
  252. package/skills/core/service-debug/SKILL.md +1 -0
  253. package/skills/core/statefulset-debug/SKILL.md +280 -0
  254. package/skills/core/volcano-diagnose-pod/SKILL.md +196 -0
  255. package/skills/core/volcano-diagnose-pod/scripts/diagnose-pod.sh +175 -0
  256. package/skills/core/volcano-gang-scheduling/SKILL.md +299 -0
  257. package/skills/core/volcano-job-diagnose/SKILL.md +319 -0
  258. package/skills/core/volcano-job-diagnose/scripts/diagnose-job.sh +253 -0
  259. package/skills/core/volcano-node-resources/SKILL.md +334 -0
  260. package/skills/core/volcano-node-resources/scripts/get-node-resources.sh +281 -0
  261. package/skills/core/volcano-queue-diagnose/SKILL.md +294 -0
  262. package/skills/core/volcano-queue-diagnose/scripts/diagnose-queue.sh +283 -0
  263. package/skills/core/volcano-resource-insufficient/SKILL.md +315 -0
  264. package/skills/core/volcano-scheduler-config/SKILL.md +371 -0
  265. package/skills/core/volcano-scheduler-config/scripts/get-scheduler-config.sh +297 -0
  266. package/skills/core/volcano-scheduler-logs/SKILL.md +241 -0
  267. package/skills/core/volcano-scheduler-logs/scripts/get-scheduler-logs.sh +159 -0
  268. package/skills/platform/create-skill/SKILL.md +35 -3
  269. package/skills/platform/manage-skill/SKILL.md +9 -2
  270. package/skills/platform/update-skill/SKILL.md +17 -6
package/README.md CHANGED
@@ -4,31 +4,37 @@
4
4
 
5
5
  # Siclaw
6
6
 
7
- **AI Agent platform for SRE — the collaborative AI foundation for your team**
7
+ **Read-only investigation copilot for SRE teams**
8
8
 
9
+ [![npm](https://img.shields.io/npm/v/siclaw?logo=npm)](https://www.npmjs.com/package/siclaw)
9
10
  [![CI](https://github.com/scitix/siclaw/actions/workflows/ci.yml/badge.svg)](https://github.com/scitix/siclaw/actions/workflows/ci.yml)
10
11
  [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D22-339933?logo=node.js&logoColor=white)](https://nodejs.org/)
11
12
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.9-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
12
13
  [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
14
+ [![Slack](https://img.shields.io/badge/Slack-Join%20Community-4A154B?logo=slack&logoColor=white)](https://join.slack.com/t/siclaw-scitix/shared_invite/zt-3rrsoc2ic-JIfbfvT1_04sqgQorSRfmw)
13
15
 
16
+ [Website](https://www.siclaw.ai) | [Documentation](https://docs.siclaw.ai) | [Slack](https://join.slack.com/t/siclaw-scitix/shared_invite/zt-3rrsoc2ic-JIfbfvT1_04sqgQorSRfmw)
14
17
 
15
18
  </div>
16
19
 
17
20
  ---
18
21
 
19
- Siclaw is an AI Agent platform for DevOps / SRE, inspired by [OpenClaw](https://github.com/openclaw) and designed to be the collaborative AI foundation for engineering teams. Unlike general-purpose coding agents, Siclaw is built for **read-only infrastructure diagnostics** the agent observes, analyzes, and reports, but never mutates your environment directly. When remediation is needed, Siclaw integrates with your existing change management systems to execute changes through established, auditable workflows. Describe a problem in plain language and the agent runs kubectl, reads logs, traces network paths, and delivers a root-cause analysis — from a terminal, a web UI, or your team's IM workspace.
22
+ Siclaw is an open-source AI agent for DevOps and SRE teams. It is built for **read-only infrastructure diagnostics**: gather evidence, form hypotheses, validate them, and return a clear root-cause analysis without changing your environment directly. Describe a problem in plain language and Siclaw investigates it from the terminal, the web UI, or your team's chat channels.
23
+
24
+ <div align="center">
25
+ <img src="docs/assets/demo.gif" alt="Siclaw Demo" width="800" />
26
+ <p><em>Deep investigation: diagnosing a CrashLoopBackOff in seconds</em></p>
27
+ </div>
20
28
 
21
29
  ## Features
22
30
 
23
- - **Deep Investigation** — Hypothesis-driven 4-phase diagnostic engine (context gathering hypothesis generation parallel validation → root-cause conclusion), bringing Deep Research to SRE with cross-system, multi-dimensional fault analysis
24
- - **Investigation Memory** — Accumulates structured knowledge from every deep investigation into a local hybrid store (vector + full-text); surfaces relevant past experience during hypothesis generation so the agent gets smarter with every incident resolved
25
- - **Security Governance** — Strict permission layer between agent and infrastructure: read-only by default, command whitelist, write operations require per-item approval, credentials isolated by workspace — zero accidental mutations in production
26
- - **Team Collaboration** — Multi-workspace, multi-user management (SSO/OAuth2), isolated AgentBox sandboxes per user, designed for multi-team, multi-environment enterprise scenarios
27
- - **Alert-Driven Operations** — Webhook triggers connect to your existing monitoring stack (Prometheus, PagerDuty, custom), automatically launching agent investigations when alerts fire
28
- - **Scheduled Tasks** — Cron-based recurring jobs for routine health checks, periodic diagnostics, or any agent task — manageable via Web UI or natural language
29
- - **Skill System** — AI-generated diagnostic skills with automated risk-level review, supporting creation, forking, and hot-reload via Web UI or natural language — organize across core / team / personal tiers to codify your team's operational expertise into reusable, shareable runbooks
30
- - **Extensible** — [MCP](https://modelcontextprotocol.io) tool servers for custom data source integrations
31
- - **Multi-Channel Access** — Terminal TUI, Web UI, or IM bots (Slack, Discord, Telegram, Lark)
31
+ - **Deep Investigation** — A 4-phase workflow for evidence gathering, hypothesis testing, and root-cause analysis
32
+ - **Investigation Memory** — Learns from past incidents to improve future investigations
33
+ - **Read-Only by Default** — Investigates and recommends next steps without changing your environment directly
34
+ - **Team Workflows** — Shared web UI, credentials, channels, triggers, and scheduled patrols
35
+ - **Reusable Skills** — Turn repeated diagnostic playbooks into reviewable runbooks
36
+ - **Extensible** — Connect external tools and data sources through [MCP](https://modelcontextprotocol.io)
37
+ - **Multi-Channel Access** — Use Siclaw from the terminal, web UI, or chat channels
32
38
 
33
39
  ## Architecture
34
40
 
@@ -43,28 +49,33 @@ Siclaw is an AI Agent platform for DevOps / SRE, inspired by [OpenClaw](https://
43
49
 
44
50
  - **Node.js >= 22.12.0** — [Download](https://nodejs.org/)
45
51
  - **npm** — Comes with Node.js
46
- - **kubectl** + **kubeconfig** Required for Kubernetes diagnostics only ([Install guide](https://kubernetes.io/docs/tasks/tools/)); not needed for TUI or Local Server mode without K8s access
52
+ - **kubectl** — Optional, only needed if you want Siclaw to investigate Kubernetes clusters
47
53
 
48
54
  ## Quick Start
49
55
 
50
- Siclaw supports three deployment profiles. Pick the one that fits your use case.
56
+ Siclaw supports three deployment profiles. For local usage, start from a dedicated working directory because Siclaw stores most runtime data in `.siclaw/` relative to where you launch it.
57
+
58
+ ```bash
59
+ mkdir -p ~/siclaw-work
60
+ cd ~/siclaw-work
61
+ ```
51
62
 
52
63
  ### 1. TUI Mode — Personal, local, lowest barrier
53
64
 
54
65
  Run the agent directly in your terminal. No server, no database. All operations are read-only by default — safe to run on your workstation.
55
66
 
56
67
  ```bash
57
- # Install
58
- npm install siclaw
68
+ # Install globally
69
+ npm install -g siclaw
59
70
 
60
71
  # Run (interactive — prompts for LLM provider on first launch)
61
- npx siclaw
72
+ siclaw
62
73
 
63
74
  # Single-shot
64
- npx siclaw --prompt "Why is pod nginx-abc in CrashLoopBackOff?"
75
+ siclaw --prompt "Why is pod nginx-abc in CrashLoopBackOff?"
65
76
 
66
77
  # Continue last session
67
- npx siclaw --continue
78
+ siclaw --continue
68
79
  ```
69
80
 
70
81
  <details>
@@ -72,7 +83,7 @@ npx siclaw --continue
72
83
 
73
84
  ```bash
74
85
  git clone https://github.com/scitix/siclaw.git && cd siclaw
75
- npm ci && npm run build
86
+ npm ci && npm run build:web && npm run build
76
87
  npm link # register `siclaw` command globally
77
88
 
78
89
  siclaw # TUI mode
@@ -87,17 +98,18 @@ siclaw --prompt "..." # single-shot mode
87
98
 
88
99
  ### 2. Local Server — VM or laptop, recommended for daily use
89
100
 
90
- A lightweight web UI backed by SQLite. No MySQL, no Docker required — just start the server and configure everything in the browser. Siclaw enforces strict read-only access by default (command whitelist, no write operations without approval), so you can safely deploy it on your own workstation without worrying about unintended changes to your clusters.
101
+ A lightweight web UI backed by SQLite. No MySQL, no Docker required.
91
102
 
92
103
  ```bash
93
- npm install siclaw
104
+ npm install -g siclaw
94
105
 
95
- # Start the server (SQLite database is created automatically)
96
- npx siclaw local
106
+ # Start the server
107
+ siclaw local
97
108
 
98
109
  # Open http://localhost:3000
99
110
  # Login: admin / admin (default credentials)
100
- # Go to Settings to configure your LLM provider
111
+ # Configure providers in Models
112
+ # Import kubeconfigs in Credentials
101
113
  ```
102
114
 
103
115
  <details>
@@ -105,7 +117,7 @@ npx siclaw local
105
117
 
106
118
  ```bash
107
119
  git clone https://github.com/scitix/siclaw.git && cd siclaw
108
- npm ci && npm run build && npm run build:web
120
+ npm ci && npm run build:web && npm run build
109
121
  npm link # register `siclaw` command globally
110
122
 
111
123
  siclaw local # start local server
@@ -115,43 +127,47 @@ siclaw local # start local server
115
127
 
116
128
  </details>
117
129
 
118
- The server uses SQLite by default and auto-generates a JWT secret on first run. All configuration — LLM providers, models, credentials is done through the **Settings** page in the web UI.
130
+ On first startup, Siclaw creates a local admin account:
131
+
132
+ - Username: `admin`
133
+ - Password: `admin`
134
+
135
+ Set `SICLAW_ADMIN_PASSWORD` before first launch if you want a different bootstrap password.
119
136
 
120
137
  ### 3. Kubernetes — Team / enterprise
121
138
 
122
- Full multi-user deployment with isolated AgentBox pods, SSO, and IM channels. Just prepare a MySQL database and deploy with Helm:
139
+ Production deployment uses Helm plus three container images: `gateway`, `agentbox`, and `cron`.
140
+
141
+ Build and push images if you are using your own registry:
123
142
 
124
143
  ```bash
125
- helm upgrade --install siclaw ./helm/siclaw \
126
- --namespace siclaw --create-namespace \
127
- --set database.url="mysql://user:pass@host:3306/siclaw"
144
+ make docker REGISTRY=registry.example.com/myteam TAG=latest
145
+ make push REGISTRY=registry.example.com/myteam TAG=latest
128
146
  ```
129
147
 
130
- <details>
131
- <summary><b>Using a custom image registry</b></summary>
132
-
133
- If you need to build and push images to your own registry:
148
+ Then deploy the chart with a MySQL URL:
134
149
 
135
150
  ```bash
136
- # Build and push images
137
- make docker push REGISTRY=registry.example.com/myteam
138
-
139
- # Deploy with custom registry
140
151
  helm upgrade --install siclaw ./helm/siclaw \
141
- --namespace siclaw --create-namespace \
142
- --set image.registry="registry.example.com/myteam" \
152
+ --namespace siclaw \
153
+ --create-namespace \
154
+ --set image.registry=registry.example.com/myteam \
155
+ --set image.tag=latest \
143
156
  --set database.url="mysql://user:pass@host:3306/siclaw"
144
157
  ```
145
158
 
146
- </details>
147
-
148
- See [`helm/siclaw/`](helm/siclaw/) for values reference, and [`k8s/README.md`](k8s/README.md) for the full deployment guide.
159
+ The default chart exposes the Gateway Service on service port `80` and NodePort `31000`.
149
160
 
150
161
  ## Configuration
151
162
 
152
- ### settings.json (TUI mode)
163
+ ### TUI / CLI
164
+
165
+ - TUI reads `.siclaw/config/settings.json`
166
+ - The first-run wizard can generate this file for you
167
+ - Kubernetes credentials should be imported through `/setup`
168
+ - Investigation reports are written to `~/.siclaw/reports/`
153
169
 
154
- Minimal example — copy `settings.example.json` to `.siclaw/config/settings.json`:
170
+ Minimal example:
155
171
 
156
172
  ```json
157
173
  {
@@ -159,82 +175,28 @@ Minimal example — copy `settings.example.json` to `.siclaw/config/settings.jso
159
175
  "default": {
160
176
  "baseUrl": "https://api.openai.com/v1",
161
177
  "apiKey": "sk-YOUR-KEY",
178
+ "api": "openai-completions",
162
179
  "models": [{ "id": "gpt-4o", "name": "GPT-4o" }]
163
180
  }
164
181
  }
165
182
  }
166
183
  ```
167
184
 
168
- <details>
169
- <summary><b>Full settings.json reference</b></summary>
170
-
171
- ```json
172
- {
173
- "providers": {
174
- "provider-name": {
175
- "baseUrl": "https://api.example.com/v1",
176
- "apiKey": "your-key",
177
- "api": "openai-completions",
178
- "authHeader": true,
179
- "models": [
180
- {
181
- "id": "model-id",
182
- "name": "Display Name",
183
- "reasoning": false,
184
- "contextWindow": 128000,
185
- "maxTokens": 16384,
186
- "cost": { "input": 2.5, "output": 10.0, "cacheRead": 0.5, "cacheWrite": 3.0 }
187
- }
188
- ]
189
- }
190
- },
191
- "default": { "provider": "provider-name", "modelId": "model-id" },
192
- "embedding": {
193
- "baseUrl": "https://api.example.com/v1",
194
- "apiKey": "your-key",
195
- "model": "BAAI/bge-m3",
196
- "dimensions": 1024
197
- },
198
- "mcpServers": {
199
- "server-name": {
200
- "command": "npx",
201
- "args": ["-y", "@some/mcp-server"]
202
- }
203
- },
204
- "debugImage": "busybox:latest",
205
- "debug": false
206
- }
207
- ```
208
-
209
- </details>
210
-
211
- <details>
212
- <summary><b>IM Channels — Slack / Discord / Telegram / Lark</b></summary>
213
-
214
- ### Slack
215
-
216
- Configure a Slack bot in **Settings > Channels**. You'll need:
217
- - Bot token and signing secret from the [Slack API](https://api.slack.com/apps)
218
-
219
- ### Discord
185
+ ### Local Server / Kubernetes
220
186
 
221
- Configure a Discord bot in **Settings > Channels**. You'll need:
222
- - Bot token from the [Discord Developer Portal](https://discord.com/developers/applications)
223
- - Scopes: `bot`, `messages.read`
187
+ - Configure providers in the **Models** page
188
+ - Import kubeconfigs, API tokens, and SSH credentials in **Credentials**
189
+ - Configure Slack, Lark, Discord, and Telegram in **Channels**
190
+ - Create inbound webhook endpoints in **Triggers**
191
+ - Configure MCP servers in **MCP Servers**
224
192
 
225
- ### Telegram
193
+ ## Documentation
226
194
 
227
- Configure a Telegram bot in **Settings > Channels**. You'll need:
228
- - Bot token from [@BotFather](https://t.me/BotFather)
229
-
230
- ### Lark
231
-
232
- Configure a Lark bot in **Settings > Channels** of the web UI. You'll need:
233
- - App ID and App Secret from the [Lark Open Platform](https://open.larksuite.com/)
234
- - Event subscription URL: `https://your-domain/api/channels/feishu/event`
235
- - Scopes: `im:message`, `im:message.group_at_msg`, `im:resource`
236
-
237
- </details>
195
+ - [Getting Started](https://docs.siclaw.ai/start/getting-started)
196
+ - [CLI & Local Server](https://docs.siclaw.ai/install/cli)
197
+ - [Kubernetes Deployment](https://docs.siclaw.ai/install/kubernetes)
198
+ - [LLM Providers](https://docs.siclaw.ai/configuration/providers)
199
+ - [MCP Servers](https://docs.siclaw.ai/configuration/mcp)
238
200
 
239
201
  ## Tech Stack
240
202
 
@@ -252,11 +214,10 @@ Configure a Lark bot in **Settings > Channels** of the web UI. You'll need:
252
214
 
253
215
  ## Community
254
216
 
217
+ - [Slack](https://join.slack.com/t/siclaw-scitix/shared_invite/zt-3rrsoc2ic-JIfbfvT1_04sqgQorSRfmw) — Chat with the team and other users
255
218
  - [GitHub Issues](https://github.com/scitix/siclaw/issues) — Bug reports and feature requests
256
219
  - [GitHub Discussions](https://github.com/scitix/siclaw/discussions) — Questions, ideas, and general discussion
257
220
 
258
- <!-- TODO: Add Discord invite link once server is created -->
259
-
260
221
  ## Contributing
261
222
 
262
223
  See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, architecture overview, and pull request guidelines.
@@ -16,6 +16,7 @@ export interface CronJob {
16
16
  description?: string | null;
17
17
  lastRunAt?: string | null;
18
18
  lastResult?: string | null;
19
+ workspaceId?: string | null;
19
20
  }
20
21
  export declare class GatewayClient {
21
22
  private gatewayUrl;
@@ -28,7 +29,7 @@ export declare class GatewayClient {
28
29
  /**
29
30
  * List cron jobs for a user
30
31
  */
31
- listCronJobs(userId: string): Promise<CronJob[]>;
32
+ listCronJobs(userId: string, workspaceId?: string): Promise<CronJob[]>;
32
33
  /**
33
34
  * Return a GatewayClientLike adapter for use with resource handlers.
34
35
  * Keeps `request()` private while exposing a minimal interface.
@@ -40,8 +40,12 @@ export class GatewayClient {
40
40
  /**
41
41
  * List cron jobs for a user
42
42
  */
43
- async listCronJobs(userId) {
44
- const data = await this.request(`/api/internal/cron-list?userId=${encodeURIComponent(userId)}`, "GET");
43
+ async listCronJobs(userId, workspaceId) {
44
+ let url = `/api/internal/cron-list?userId=${encodeURIComponent(userId)}`;
45
+ if (workspaceId) {
46
+ url += `&workspaceId=${encodeURIComponent(workspaceId)}`;
47
+ }
48
+ const data = await this.request(url, "GET");
45
49
  return data.jobs || [];
46
50
  }
47
51
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"gateway-client.js","sourceRoot":"","sources":["../../src/agentbox/gateway-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gateway-client.js","sourceRoot":"","sources":["../../src/agentbox/gateway-client.ts"],"names":[],"mappings":"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"}
@@ -11,17 +11,44 @@ import { hasOpenAIProvider, ensureProxy } from "../core/llm-proxy.js";
11
11
  import { deepSearchEvents } from "../tools/deep-search/events.js";
12
12
  import { createChecklist, buildActivationMessage } from "../tools/dp-tools.js";
13
13
  import { loadConfig } from "../core/config.js";
14
+ import { emitDiagnostic } from "../shared/diagnostic-events.js";
15
+ import { checkMetricsAuth } from "../shared/metrics.js"; // also registers metrics subscriber (side-effect)
14
16
  import { GatewayClient } from "./gateway-client.js";
15
17
  import { getResourceHandler } from "./resource-handlers.js";
16
18
  import { RESOURCE_DESCRIPTORS } from "../shared/resource-sync.js";
19
+ import { detectLanguage } from "../shared/detect-language.js";
20
+ import { resolveUnderDir } from "../shared/path-utils.js";
17
21
  /**
18
22
  * Parse JSON body
19
23
  */
24
+ const MAX_BODY_SIZE = 10 * 1024 * 1024; // 10MB
25
+ const BODY_TIMEOUT_MS = 30_000; // 30s
20
26
  async function parseJsonBody(req) {
21
27
  return new Promise((resolve, reject) => {
22
28
  let body = "";
23
- req.on("data", (chunk) => (body += chunk));
29
+ let size = 0;
30
+ let timedOut = false;
31
+ const timer = setTimeout(() => {
32
+ timedOut = true;
33
+ req.destroy();
34
+ reject(new Error("Body read timeout"));
35
+ }, BODY_TIMEOUT_MS);
36
+ req.on("data", (chunk) => {
37
+ if (timedOut)
38
+ return;
39
+ size += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
40
+ if (size > MAX_BODY_SIZE) {
41
+ clearTimeout(timer);
42
+ req.destroy();
43
+ reject(new Error(`Body exceeds ${MAX_BODY_SIZE} byte limit`));
44
+ return;
45
+ }
46
+ body += chunk;
47
+ });
24
48
  req.on("end", () => {
49
+ clearTimeout(timer);
50
+ if (timedOut)
51
+ return;
25
52
  try {
26
53
  resolve(body ? JSON.parse(body) : {});
27
54
  }
@@ -29,7 +56,10 @@ async function parseJsonBody(req) {
29
56
  reject(new Error("Invalid JSON"));
30
57
  }
31
58
  });
32
- req.on("error", reject);
59
+ req.on("error", (err) => {
60
+ clearTimeout(timer);
61
+ reject(err);
62
+ });
33
63
  });
34
64
  }
35
65
  /**
@@ -91,7 +121,56 @@ export function createHttpServer(sessionManager) {
91
121
  handler,
92
122
  });
93
123
  }
124
+ // ── Credential materialization helper (shared by prompt and reload-credentials) ──
125
+ // Writes new files with .new suffix first, then atomically renames them into place.
126
+ // This prevents data loss if the process crashes between delete and write.
127
+ function materializeCredentials(payload, kubeconfigRef) {
128
+ const credDir = path.resolve(process.cwd(), loadConfig().paths.credentialsDir);
129
+ fs.mkdirSync(credDir, { recursive: true });
130
+ // Phase 1: Write new files with .new suffix (staging)
131
+ const stagedFiles = [];
132
+ for (const file of payload.files) {
133
+ const resolved = resolveUnderDir(credDir, file.name);
134
+ const staged = resolved + ".new";
135
+ fs.writeFileSync(staged, file.content, file.mode ? { mode: file.mode } : undefined);
136
+ stagedFiles.push(file.name);
137
+ }
138
+ // Stage manifest
139
+ const manifestPath = path.join(credDir, "manifest.json");
140
+ fs.writeFileSync(manifestPath + ".new", JSON.stringify(payload.manifest, null, 2));
141
+ // Phase 2: Remove old files
142
+ for (const entry of fs.readdirSync(credDir)) {
143
+ if (entry.endsWith(".new"))
144
+ continue; // skip staged files
145
+ fs.rmSync(path.join(credDir, entry), { recursive: true });
146
+ }
147
+ // Phase 3: Rename staged files into place (atomic per-file on same filesystem)
148
+ for (const file of payload.files) {
149
+ const resolved = resolveUnderDir(credDir, file.name);
150
+ fs.renameSync(resolved + ".new", resolved);
151
+ }
152
+ fs.renameSync(manifestPath + ".new", manifestPath);
153
+ kubeconfigRef.credentialsDir = credDir;
154
+ return payload.files.length;
155
+ }
94
156
  // ==================== Routes ====================
157
+ /**
158
+ * GET /metrics - Prometheus metrics endpoint
159
+ */
160
+ addRoute("GET", "/metrics", async (req, res) => {
161
+ if (!checkMetricsAuth(req, res))
162
+ return;
163
+ const { metricsRegistry } = await import("../shared/metrics.js");
164
+ res.writeHead(200, { "Content-Type": metricsRegistry.contentType });
165
+ res.end(await metricsRegistry.metrics());
166
+ });
167
+ /**
168
+ * GET /api/internal/metrics-snapshot - export metrics snapshot for Gateway pull (K8s mode)
169
+ */
170
+ addRoute("GET", "/api/internal/metrics-snapshot", async (_req, res) => {
171
+ const { localCollector } = await import("../shared/local-collector.js");
172
+ sendJson(res, 200, localCollector.exportSnapshot());
173
+ });
95
174
  /**
96
175
  * GET /health - health check
97
176
  */
@@ -128,22 +207,21 @@ export function createHttpServer(sessionManager) {
128
207
  return;
129
208
  }
130
209
  const managed = await sessionManager.getOrCreate(body.sessionId, body.mode, body.brainType);
131
- // Materialize credential files from payload (sent by gateway in prompt body)
132
- if (body.credentials?.files?.length) {
133
- const credDir = path.resolve(process.cwd(), loadConfig().paths.credentialsDir);
134
- fs.mkdirSync(credDir, { recursive: true });
135
- // Clear existing files
136
- for (const entry of fs.readdirSync(credDir)) {
137
- fs.rmSync(path.join(credDir, entry), { recursive: true });
138
- }
139
- // Write credential files
140
- for (const file of body.credentials.files) {
141
- fs.writeFileSync(path.join(credDir, file.name), file.content, file.mode ? { mode: file.mode } : undefined);
142
- }
143
- // Write manifest
144
- fs.writeFileSync(path.join(credDir, "manifest.json"), JSON.stringify(body.credentials.manifest, null, 2));
145
- managed.kubeconfigRef.credentialsDir = credDir;
146
- console.log(`[agentbox-http] Materialized ${body.credentials.files.length} credential files to ${credDir}`);
210
+ // Materialize credential files from payload (sent by gateway in prompt body).
211
+ // Always call when credentials payload is present — even with empty files
212
+ // so stale credential files from prior sessions are cleaned up.
213
+ if (body.credentials) {
214
+ try {
215
+ const count = materializeCredentials(body.credentials, managed.kubeconfigRef);
216
+ if (count > 0) {
217
+ console.log(`[agentbox-http] Materialized ${count} credential files`);
218
+ }
219
+ }
220
+ catch (err) {
221
+ console.error(`[agentbox-http] Failed to materialize credentials for session ${managed.id}:`, err);
222
+ sendJson(res, 500, { error: "Failed to materialize credentials" });
223
+ return;
224
+ }
147
225
  }
148
226
  // Dynamically register provider config from gateway DB (before findModel)
149
227
  if (body.modelConfig && body.modelProvider && managed.brain.registerProvider) {
@@ -238,10 +316,52 @@ export function createHttpServer(sessionManager) {
238
316
  console.log(`[agentbox-http] DP exited for SDK brain, session ${managed.id}`);
239
317
  }
240
318
  }
319
+ // --- Language detection: inject explicit instruction so model doesn't guess ---
320
+ const detectedLang = detectLanguage(body.text);
321
+ if (detectedLang !== "English") {
322
+ promptText = `[System: respond in ${detectedLang}]\n${promptText}`;
323
+ }
324
+ // Programmatically update PROFILE.md Language field (code-level, not model-dependent).
325
+ // Only update on non-English detection to avoid flapping: English is the default,
326
+ // so we only persist when the user actively uses another language.
327
+ if (detectedLang !== "English") {
328
+ try {
329
+ const cfg = loadConfig();
330
+ const userDataDir = process.env.SICLAW_USER_DATA_DIR || cfg.paths.userDataDir;
331
+ const profilePath = path.resolve(userDataDir, "memory", "PROFILE.md");
332
+ if (fs.existsSync(profilePath)) {
333
+ const content = fs.readFileSync(profilePath, "utf-8");
334
+ const currentLangMatch = content.match(/\*\*Language\*\*:\s*(.+)/i);
335
+ const currentLang = currentLangMatch?.[1]?.trim();
336
+ if (currentLang !== detectedLang) {
337
+ const updated = content.replace(/(\*\*Language\*\*:\s*).+/i, `$1${detectedLang}`);
338
+ fs.writeFileSync(profilePath, updated);
339
+ }
340
+ }
341
+ }
342
+ catch { /* best-effort, don't block prompt */ }
343
+ }
241
344
  // Execute prompt asynchronously; notify SSE to close on completion
242
- console.log(`[agentbox-http] Starting prompt for session ${managed.id}`);
345
+ console.log(`[agentbox-http] Starting prompt for session ${managed.id} [lang=${detectedLang}]`);
346
+ // Metrics: snapshot stats before prompt for delta calculation
347
+ const prevStats = managed.brain.getSessionStats();
348
+ const promptStartTime = Date.now();
349
+ let promptOutcome = "completed";
243
350
  const actuallyFinish = () => {
244
351
  managed._promptDone = true;
352
+ // Emit prompt metrics via diagnostic event bus
353
+ const currStats = managed.brain.getSessionStats();
354
+ const model = managed.brain.getModel();
355
+ emitDiagnostic({
356
+ type: "prompt_complete",
357
+ sessionId: managed.id,
358
+ prev: prevStats,
359
+ curr: currStats,
360
+ model,
361
+ durationMs: Date.now() - promptStartTime,
362
+ outcome: promptOutcome,
363
+ userId: sessionManager.userId,
364
+ });
245
365
  // Stop buffering
246
366
  if (managed._bufferUnsub) {
247
367
  managed._bufferUnsub();
@@ -281,9 +401,11 @@ export function createHttpServer(sessionManager) {
281
401
  };
282
402
  managed.brain.prompt(promptText).then(() => {
283
403
  console.log(`[agentbox-http] Prompt completed for session ${managed.id}`);
404
+ promptOutcome = "completed";
284
405
  onPromptFinish();
285
406
  }).catch((err) => {
286
407
  console.error(`[agentbox-http] Prompt error for session ${managed.id}:`, err);
408
+ promptOutcome = "error";
287
409
  onPromptFinish();
288
410
  });
289
411
  sendJson(res, 200, { ok: true, sessionId: managed.id, brainType: managed.brainType });
@@ -528,6 +650,49 @@ export function createHttpServer(sessionManager) {
528
650
  }
529
651
  });
530
652
  }
653
+ /**
654
+ * POST /api/reload-credentials — push-based credential update from Gateway
655
+ *
656
+ * Accepts the same {manifest, files} payload as the prompt body's credentials
657
+ * field and re-materializes credential files on disk. This allows the Gateway
658
+ * to push credential changes (kubeconfig upload/delete, credential CRUD)
659
+ * without waiting for the next prompt.
660
+ */
661
+ addRoute("POST", "/api/reload-credentials", async (req, res) => {
662
+ const body = (await parseJsonBody(req));
663
+ if (!body.manifest) {
664
+ sendJson(res, 400, { error: "Missing 'manifest' field" });
665
+ return;
666
+ }
667
+ // Each AgentBox pod serves exactly one user (one-pod-per-workspace in K8s mode,
668
+ // one in-process instance per user in local mode). All sessions within this
669
+ // AgentBox belong to the same user, so updating any session's kubeconfigRef is correct.
670
+ const sessions = sessionManager.list();
671
+ const kubeconfigRef = sessions.length > 0
672
+ ? sessions[0].kubeconfigRef
673
+ : { credentialsDir: undefined };
674
+ const payload = { manifest: body.manifest, files: body.files ?? [] };
675
+ try {
676
+ // Use atomic materializeCredentials for both populate and clear paths
677
+ const count = materializeCredentials(payload, kubeconfigRef);
678
+ if (count > 0) {
679
+ console.log(`[agentbox-http] Credentials reloaded: ${count} files materialized`);
680
+ }
681
+ else {
682
+ console.log("[agentbox-http] Credentials cleared (empty payload)");
683
+ }
684
+ }
685
+ catch (err) {
686
+ console.error("[agentbox-http] Failed to reload credentials:", err);
687
+ sendJson(res, 500, { error: "Failed to materialize credentials" });
688
+ return;
689
+ }
690
+ // Update kubeconfigRef on all active sessions
691
+ for (const session of sessions) {
692
+ session.kubeconfigRef.credentialsDir = kubeconfigRef.credentialsDir;
693
+ }
694
+ sendJson(res, 200, { ok: true, count: payload.files.length });
695
+ });
531
696
  /**
532
697
  * GET /api/models - list available models (read from settings.json)
533
698
  */