corporateai 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.
Files changed (704) hide show
  1. package/.dockerignore +10 -0
  2. package/.env.example +3 -0
  3. package/.github/workflows/publish-cli.yml +49 -0
  4. package/.mailmap +1 -0
  5. package/AGENTS.md +148 -0
  6. package/CONTRIBUTING.md +75 -0
  7. package/Dockerfile +59 -0
  8. package/Dockerfile.onboard-smoke +42 -0
  9. package/LICENSE +21 -0
  10. package/README.md +93 -0
  11. package/cli/esbuild.config.mjs +11 -0
  12. package/cli/package.json +24 -0
  13. package/cli/scripts/build-cli.mjs +5 -0
  14. package/cli/src/index.ts +27 -0
  15. package/docker-compose.quickstart.yml +18 -0
  16. package/docker-compose.untrusted-review.yml +33 -0
  17. package/docker-compose.yml +38 -0
  18. package/package.json +56 -0
  19. package/patches/embedded-postgres@18.1.0-beta.16.patch +0 -0
  20. package/pnpm-workspace.yaml +4 -0
  21. package/releases/.gitkeep +0 -0
  22. package/releases/v0.0.1.md +36 -0
  23. package/releases/v0.2.7.md +15 -0
  24. package/releases/v0.3.0.md +54 -0
  25. package/releases/v0.3.1.md +55 -0
  26. package/releases/v2026.318.0.md +66 -0
  27. package/releases/v2026.325.0.md +78 -0
  28. package/report/2026-03-13-08-46-token-optimization-implementation.md +48 -0
  29. package/scripts/backup-db.sh +17 -0
  30. package/scripts/build-npm.sh +80 -0
  31. package/scripts/check-forbidden-tokens.mjs +115 -0
  32. package/scripts/clean-onboard-git.sh +14 -0
  33. package/scripts/clean-onboard-npm.sh +13 -0
  34. package/scripts/clean-onboard-ref.sh +86 -0
  35. package/scripts/create-github-release.sh +99 -0
  36. package/scripts/dev-runner-paths.mjs +38 -0
  37. package/scripts/dev-runner.mjs +606 -0
  38. package/scripts/docker-onboard-smoke.sh +306 -0
  39. package/scripts/ensure-plugin-build-deps.mjs +47 -0
  40. package/scripts/generate-company-assets.ts +365 -0
  41. package/scripts/generate-npm-package-json.mjs +113 -0
  42. package/scripts/generate-org-chart-images.ts +694 -0
  43. package/scripts/generate-org-chart-satori-comparison.ts +225 -0
  44. package/scripts/generate-ui-package-json.mjs +31 -0
  45. package/scripts/kill-dev.sh +71 -0
  46. package/scripts/migrate-inline-env-secrets.ts +126 -0
  47. package/scripts/prepare-server-ui-dist.sh +22 -0
  48. package/scripts/provision-worktree.sh +333 -0
  49. package/scripts/release-lib.sh +306 -0
  50. package/scripts/release-package-map.mjs +169 -0
  51. package/scripts/release.sh +312 -0
  52. package/scripts/rollback-latest.sh +111 -0
  53. package/scripts/smoke/openclaw-docker-ui.sh +329 -0
  54. package/scripts/smoke/openclaw-gateway-e2e.sh +954 -0
  55. package/scripts/smoke/openclaw-join.sh +295 -0
  56. package/scripts/smoke/openclaw-sse-standalone.sh +146 -0
  57. package/scripts/workspace-compat.mjs +60 -0
  58. package/server/CHANGELOG.md +130 -0
  59. package/server/package.json +96 -0
  60. package/server/scripts/copy-onboarding-assets.mjs +10 -0
  61. package/server/scripts/dev-watch.ts +33 -0
  62. package/server/src/__tests__/activity-routes.test.ts +70 -0
  63. package/server/src/__tests__/adapter-models.test.ts +105 -0
  64. package/server/src/__tests__/adapter-session-codecs.test.ts +194 -0
  65. package/server/src/__tests__/agent-auth-jwt.test.ts +79 -0
  66. package/server/src/__tests__/agent-instructions-routes.test.ts +318 -0
  67. package/server/src/__tests__/agent-instructions-service.test.ts +361 -0
  68. package/server/src/__tests__/agent-permissions-routes.test.ts +275 -0
  69. package/server/src/__tests__/agent-shortname-collision.test.ts +69 -0
  70. package/server/src/__tests__/agent-skill-contract.test.ts +50 -0
  71. package/server/src/__tests__/agent-skills-routes.test.ts +462 -0
  72. package/server/src/__tests__/app-hmr-port.test.ts +19 -0
  73. package/server/src/__tests__/approval-routes-idempotency.test.ts +110 -0
  74. package/server/src/__tests__/approvals-service.test.ts +107 -0
  75. package/server/src/__tests__/assets.test.ts +250 -0
  76. package/server/src/__tests__/attachment-types.test.ts +97 -0
  77. package/server/src/__tests__/board-mutation-guard.test.ts +105 -0
  78. package/server/src/__tests__/budgets-service.test.ts +311 -0
  79. package/server/src/__tests__/claude-local-adapter-environment.test.ts +92 -0
  80. package/server/src/__tests__/claude-local-adapter.test.ts +31 -0
  81. package/server/src/__tests__/claude-local-skill-sync.test.ts +111 -0
  82. package/server/src/__tests__/cli-auth-routes.test.ts +230 -0
  83. package/server/src/__tests__/codex-local-adapter-environment.test.ts +143 -0
  84. package/server/src/__tests__/codex-local-adapter.test.ts +253 -0
  85. package/server/src/__tests__/codex-local-execute.test.ts +391 -0
  86. package/server/src/__tests__/codex-local-skill-injection.test.ts +175 -0
  87. package/server/src/__tests__/codex-local-skill-sync.test.ts +123 -0
  88. package/server/src/__tests__/companies-route-path-guard.test.ts +56 -0
  89. package/server/src/__tests__/company-branding-route.test.ts +196 -0
  90. package/server/src/__tests__/company-portability-routes.test.ts +175 -0
  91. package/server/src/__tests__/company-portability.test.ts +2186 -0
  92. package/server/src/__tests__/company-skills-routes.test.ts +113 -0
  93. package/server/src/__tests__/company-skills.test.ts +229 -0
  94. package/server/src/__tests__/costs-service.test.ts +226 -0
  95. package/server/src/__tests__/cursor-local-adapter-environment.test.ts +196 -0
  96. package/server/src/__tests__/cursor-local-adapter.test.ts +406 -0
  97. package/server/src/__tests__/cursor-local-execute.test.ts +263 -0
  98. package/server/src/__tests__/cursor-local-skill-injection.test.ts +104 -0
  99. package/server/src/__tests__/cursor-local-skill-sync.test.ts +145 -0
  100. package/server/src/__tests__/dev-runner-paths.test.ts +25 -0
  101. package/server/src/__tests__/dev-server-status.test.ts +66 -0
  102. package/server/src/__tests__/dev-watch-ignore.test.ts +42 -0
  103. package/server/src/__tests__/documents.test.ts +29 -0
  104. package/server/src/__tests__/error-handler.test.ts +53 -0
  105. package/server/src/__tests__/execution-workspace-policy.test.ts +170 -0
  106. package/server/src/__tests__/forbidden-tokens.test.ts +77 -0
  107. package/server/src/__tests__/gemini-local-adapter-environment.test.ts +135 -0
  108. package/server/src/__tests__/gemini-local-adapter.test.ts +190 -0
  109. package/server/src/__tests__/gemini-local-execute.test.ts +172 -0
  110. package/server/src/__tests__/gemini-local-skill-sync.test.ts +90 -0
  111. package/server/src/__tests__/health.test.ts +16 -0
  112. package/server/src/__tests__/heartbeat-process-recovery.test.ts +256 -0
  113. package/server/src/__tests__/heartbeat-run-summary.test.ts +33 -0
  114. package/server/src/__tests__/heartbeat-workspace-session.test.ts +334 -0
  115. package/server/src/__tests__/helpers/embedded-postgres.ts +7 -0
  116. package/server/src/__tests__/hire-hook.test.ts +181 -0
  117. package/server/src/__tests__/instance-settings-routes.test.ts +156 -0
  118. package/server/src/__tests__/invite-accept-gateway-defaults.test.ts +119 -0
  119. package/server/src/__tests__/invite-accept-replay.test.ts +92 -0
  120. package/server/src/__tests__/invite-expiry.test.ts +10 -0
  121. package/server/src/__tests__/invite-join-grants.test.ts +57 -0
  122. package/server/src/__tests__/invite-join-manager.test.ts +33 -0
  123. package/server/src/__tests__/invite-onboarding-text.test.ts +116 -0
  124. package/server/src/__tests__/issue-comment-reopen-routes.test.ts +146 -0
  125. package/server/src/__tests__/issue-goal-fallback.test.ts +99 -0
  126. package/server/src/__tests__/issues-checkout-wakeup.test.ts +48 -0
  127. package/server/src/__tests__/issues-goal-context-routes.test.ts +187 -0
  128. package/server/src/__tests__/issues-service.test.ts +317 -0
  129. package/server/src/__tests__/issues-user-context.test.ts +113 -0
  130. package/server/src/__tests__/log-redaction.test.ts +74 -0
  131. package/server/src/__tests__/monthly-spend-service.test.ts +90 -0
  132. package/server/src/__tests__/normalize-agent-mention-token.test.ts +41 -0
  133. package/server/src/__tests__/openclaw-gateway-adapter.test.ts +626 -0
  134. package/server/src/__tests__/openclaw-invite-prompt-route.test.ts +192 -0
  135. package/server/src/__tests__/opencode-local-adapter-environment.test.ts +97 -0
  136. package/server/src/__tests__/opencode-local-adapter.test.ts +226 -0
  137. package/server/src/__tests__/opencode-local-skill-sync.test.ts +91 -0
  138. package/server/src/__tests__/paperclip-env.test.ts +58 -0
  139. package/server/src/__tests__/paperclip-skill-utils.test.ts +63 -0
  140. package/server/src/__tests__/pi-local-adapter-environment.test.ts +102 -0
  141. package/server/src/__tests__/pi-local-skill-sync.test.ts +95 -0
  142. package/server/src/__tests__/plugin-dev-watcher.test.ts +68 -0
  143. package/server/src/__tests__/plugin-worker-manager.test.ts +43 -0
  144. package/server/src/__tests__/private-hostname-guard.test.ts +56 -0
  145. package/server/src/__tests__/project-shortname-resolution.test.ts +45 -0
  146. package/server/src/__tests__/quota-windows-service.test.ts +56 -0
  147. package/server/src/__tests__/quota-windows.test.ts +1109 -0
  148. package/server/src/__tests__/redaction.test.ts +66 -0
  149. package/server/src/__tests__/routines-e2e.test.ts +276 -0
  150. package/server/src/__tests__/routines-routes.test.ts +271 -0
  151. package/server/src/__tests__/routines-service.test.ts +424 -0
  152. package/server/src/__tests__/storage-local-provider.test.ts +78 -0
  153. package/server/src/__tests__/ui-branding.test.ts +82 -0
  154. package/server/src/__tests__/work-products.test.ts +95 -0
  155. package/server/src/__tests__/workspace-runtime.test.ts +1131 -0
  156. package/server/src/__tests__/worktree-config.test.ts +426 -0
  157. package/server/src/adapters/codex-models.ts +105 -0
  158. package/server/src/adapters/cursor-models.ts +171 -0
  159. package/server/src/adapters/http/execute.ts +42 -0
  160. package/server/src/adapters/http/index.ts +21 -0
  161. package/server/src/adapters/http/test.ts +116 -0
  162. package/server/src/adapters/index.ts +18 -0
  163. package/server/src/adapters/process/execute.ts +77 -0
  164. package/server/src/adapters/process/index.ts +24 -0
  165. package/server/src/adapters/process/test.ts +89 -0
  166. package/server/src/adapters/registry.ts +225 -0
  167. package/server/src/adapters/server-utils-compat.ts +57 -0
  168. package/server/src/adapters/types.ts +30 -0
  169. package/server/src/adapters/utils.ts +48 -0
  170. package/server/src/agent-auth-jwt.ts +141 -0
  171. package/server/src/app.ts +321 -0
  172. package/server/src/attachment-types.ts +74 -0
  173. package/server/src/auth/better-auth.ts +148 -0
  174. package/server/src/board-claim.ts +150 -0
  175. package/server/src/config-file.ts +17 -0
  176. package/server/src/config.ts +260 -0
  177. package/server/src/dev-server-status.ts +103 -0
  178. package/server/src/dev-watch-ignore.ts +36 -0
  179. package/server/src/errors.ts +34 -0
  180. package/server/src/home-paths.ts +95 -0
  181. package/server/src/index.ts +799 -0
  182. package/server/src/log-redaction.ts +146 -0
  183. package/server/src/middleware/auth.ts +178 -0
  184. package/server/src/middleware/board-mutation-guard.ts +66 -0
  185. package/server/src/middleware/error-handler.ts +71 -0
  186. package/server/src/middleware/index.ts +3 -0
  187. package/server/src/middleware/logger.ts +90 -0
  188. package/server/src/middleware/private-hostname-guard.ts +92 -0
  189. package/server/src/middleware/validate.ts +9 -0
  190. package/server/src/onboarding-assets/ceo/AGENTS.md +54 -0
  191. package/server/src/onboarding-assets/ceo/HEARTBEAT.md +72 -0
  192. package/server/src/onboarding-assets/ceo/SOUL.md +33 -0
  193. package/server/src/onboarding-assets/ceo/TOOLS.md +3 -0
  194. package/server/src/onboarding-assets/default/AGENTS.md +3 -0
  195. package/server/src/paths.ts +34 -0
  196. package/server/src/realtime/live-events-ws.ts +274 -0
  197. package/server/src/redaction.ts +59 -0
  198. package/server/src/routes/access.ts +2888 -0
  199. package/server/src/routes/activity.ts +89 -0
  200. package/server/src/routes/agents.ts +2313 -0
  201. package/server/src/routes/approvals.ts +346 -0
  202. package/server/src/routes/assets.ts +341 -0
  203. package/server/src/routes/authz.ts +52 -0
  204. package/server/src/routes/companies.ts +343 -0
  205. package/server/src/routes/company-skills.ts +300 -0
  206. package/server/src/routes/costs.ts +335 -0
  207. package/server/src/routes/dashboard.ts +19 -0
  208. package/server/src/routes/execution-workspaces.ts +182 -0
  209. package/server/src/routes/goals.ts +107 -0
  210. package/server/src/routes/health.ts +94 -0
  211. package/server/src/routes/index.ts +17 -0
  212. package/server/src/routes/instance-settings.ts +95 -0
  213. package/server/src/routes/issues-checkout-wakeup.ts +14 -0
  214. package/server/src/routes/issues.ts +1680 -0
  215. package/server/src/routes/llms.ts +86 -0
  216. package/server/src/routes/org-chart-svg.ts +777 -0
  217. package/server/src/routes/plugin-ui-static.ts +497 -0
  218. package/server/src/routes/plugins.ts +2220 -0
  219. package/server/src/routes/projects.ts +295 -0
  220. package/server/src/routes/routines.ts +300 -0
  221. package/server/src/routes/secrets.ts +166 -0
  222. package/server/src/routes/sidebar-badges.ts +52 -0
  223. package/server/src/secrets/external-stub-providers.ts +32 -0
  224. package/server/src/secrets/local-encrypted-provider.ts +135 -0
  225. package/server/src/secrets/provider-registry.ts +31 -0
  226. package/server/src/secrets/types.ts +23 -0
  227. package/server/src/services/access.ts +381 -0
  228. package/server/src/services/activity-log.ts +95 -0
  229. package/server/src/services/activity.ts +164 -0
  230. package/server/src/services/agent-instructions.ts +735 -0
  231. package/server/src/services/agent-permissions.ts +27 -0
  232. package/server/src/services/agents.ts +694 -0
  233. package/server/src/services/approvals.ts +273 -0
  234. package/server/src/services/assets.ts +23 -0
  235. package/server/src/services/board-auth.ts +355 -0
  236. package/server/src/services/budgets.ts +959 -0
  237. package/server/src/services/companies.ts +313 -0
  238. package/server/src/services/company-export-readme.ts +173 -0
  239. package/server/src/services/company-portability.ts +4263 -0
  240. package/server/src/services/company-skills.ts +2356 -0
  241. package/server/src/services/costs.ts +365 -0
  242. package/server/src/services/cron.ts +373 -0
  243. package/server/src/services/dashboard.ts +110 -0
  244. package/server/src/services/default-agent-instructions.ts +27 -0
  245. package/server/src/services/documents.ts +434 -0
  246. package/server/src/services/execution-workspace-policy.ts +210 -0
  247. package/server/src/services/execution-workspaces.ts +100 -0
  248. package/server/src/services/finance.ts +135 -0
  249. package/server/src/services/goals.ts +81 -0
  250. package/server/src/services/heartbeat-run-summary.ts +35 -0
  251. package/server/src/services/heartbeat.ts +3863 -0
  252. package/server/src/services/hire-hook.ts +114 -0
  253. package/server/src/services/index.ts +32 -0
  254. package/server/src/services/instance-settings.ts +138 -0
  255. package/server/src/services/issue-approvals.ts +175 -0
  256. package/server/src/services/issue-assignment-wakeup.ts +48 -0
  257. package/server/src/services/issue-goal-fallback.ts +56 -0
  258. package/server/src/services/issues.ts +1828 -0
  259. package/server/src/services/live-events.ts +55 -0
  260. package/server/src/services/plugin-capability-validator.ts +450 -0
  261. package/server/src/services/plugin-config-validator.ts +55 -0
  262. package/server/src/services/plugin-dev-watcher.ts +339 -0
  263. package/server/src/services/plugin-event-bus.ts +413 -0
  264. package/server/src/services/plugin-host-service-cleanup.ts +59 -0
  265. package/server/src/services/plugin-host-services.ts +1132 -0
  266. package/server/src/services/plugin-job-coordinator.ts +261 -0
  267. package/server/src/services/plugin-job-scheduler.ts +753 -0
  268. package/server/src/services/plugin-job-store.ts +466 -0
  269. package/server/src/services/plugin-lifecycle.ts +822 -0
  270. package/server/src/services/plugin-loader.ts +1955 -0
  271. package/server/src/services/plugin-log-retention.ts +87 -0
  272. package/server/src/services/plugin-manifest-validator.ts +164 -0
  273. package/server/src/services/plugin-registry.ts +683 -0
  274. package/server/src/services/plugin-runtime-sandbox.ts +222 -0
  275. package/server/src/services/plugin-secrets-handler.ts +355 -0
  276. package/server/src/services/plugin-state-store.ts +238 -0
  277. package/server/src/services/plugin-stream-bus.ts +81 -0
  278. package/server/src/services/plugin-tool-dispatcher.ts +449 -0
  279. package/server/src/services/plugin-tool-registry.ts +450 -0
  280. package/server/src/services/plugin-worker-manager.ts +1343 -0
  281. package/server/src/services/projects.ts +860 -0
  282. package/server/src/services/quota-windows.ts +65 -0
  283. package/server/src/services/routines.ts +1269 -0
  284. package/server/src/services/run-log-store.ts +156 -0
  285. package/server/src/services/secrets.ts +370 -0
  286. package/server/src/services/sidebar-badges.ts +56 -0
  287. package/server/src/services/work-products.ts +124 -0
  288. package/server/src/services/workspace-operation-log-store.ts +156 -0
  289. package/server/src/services/workspace-operations.ts +262 -0
  290. package/server/src/services/workspace-runtime.ts +1565 -0
  291. package/server/src/startup-banner.ts +176 -0
  292. package/server/src/storage/index.ts +35 -0
  293. package/server/src/storage/local-disk-provider.ts +89 -0
  294. package/server/src/storage/provider-registry.ts +18 -0
  295. package/server/src/storage/s3-provider.ts +153 -0
  296. package/server/src/storage/service.ts +131 -0
  297. package/server/src/storage/types.ts +63 -0
  298. package/server/src/ui-branding.ts +217 -0
  299. package/server/src/version.ts +10 -0
  300. package/server/src/worktree-config.ts +468 -0
  301. package/server/tsconfig.json +9 -0
  302. package/server/vitest.config.ts +7 -0
  303. package/skills/paperclip/SKILL.md +365 -0
  304. package/skills/paperclip/references/api-reference.md +647 -0
  305. package/skills/paperclip/references/company-skills.md +193 -0
  306. package/skills/paperclip-create-agent/SKILL.md +142 -0
  307. package/skills/paperclip-create-agent/references/api-reference.md +105 -0
  308. package/skills/paperclip-create-plugin/SKILL.md +102 -0
  309. package/skills/para-memory-files/SKILL.md +104 -0
  310. package/skills/para-memory-files/references/schemas.md +35 -0
  311. package/tests/e2e/onboarding.spec.ts +142 -0
  312. package/tests/e2e/playwright.config.ts +35 -0
  313. package/tests/release-smoke/docker-auth-onboarding.spec.ts +141 -0
  314. package/tests/release-smoke/playwright.config.ts +28 -0
  315. package/tsconfig.base.json +18 -0
  316. package/tsconfig.json +18 -0
  317. package/ui/README.md +12 -0
  318. package/ui/components.json +21 -0
  319. package/ui/index.html +47 -0
  320. package/ui/package.json +73 -0
  321. package/ui/public/android-chrome-192x192.png +0 -0
  322. package/ui/public/android-chrome-512x512.png +0 -0
  323. package/ui/public/apple-touch-icon.png +0 -0
  324. package/ui/public/brands/opencode-logo-dark-square.svg +18 -0
  325. package/ui/public/brands/opencode-logo-light-square.svg +18 -0
  326. package/ui/public/favicon-16x16.png +0 -0
  327. package/ui/public/favicon-32x32.png +0 -0
  328. package/ui/public/favicon.ico +0 -0
  329. package/ui/public/favicon.svg +9 -0
  330. package/ui/public/site.webmanifest +30 -0
  331. package/ui/public/sprites/1-D-1.png +0 -0
  332. package/ui/public/sprites/1-D-2.png +0 -0
  333. package/ui/public/sprites/1-D-3.png +0 -0
  334. package/ui/public/sprites/1-L-1.png +0 -0
  335. package/ui/public/sprites/1-R-1.png +0 -0
  336. package/ui/public/sprites/10-D-1.png +0 -0
  337. package/ui/public/sprites/10-D-2.png +0 -0
  338. package/ui/public/sprites/10-D-3.png +0 -0
  339. package/ui/public/sprites/10-L-1.png +0 -0
  340. package/ui/public/sprites/10-R-1.png +0 -0
  341. package/ui/public/sprites/11-D-1.png +0 -0
  342. package/ui/public/sprites/11-D-2.png +0 -0
  343. package/ui/public/sprites/11-D-3.png +0 -0
  344. package/ui/public/sprites/11-L-1.png +0 -0
  345. package/ui/public/sprites/11-R-1.png +0 -0
  346. package/ui/public/sprites/12-D-1.png +0 -0
  347. package/ui/public/sprites/12-D-2.png +0 -0
  348. package/ui/public/sprites/12-D-3.png +0 -0
  349. package/ui/public/sprites/12-L-1.png +0 -0
  350. package/ui/public/sprites/12-R-1.png +0 -0
  351. package/ui/public/sprites/13-D-1.png +0 -0
  352. package/ui/public/sprites/13-D-2.png +0 -0
  353. package/ui/public/sprites/13-D-3.png +0 -0
  354. package/ui/public/sprites/13-L-1.png +0 -0
  355. package/ui/public/sprites/13-R-1.png +0 -0
  356. package/ui/public/sprites/14-D-1.png +0 -0
  357. package/ui/public/sprites/14-D-2.png +0 -0
  358. package/ui/public/sprites/14-D-3.png +0 -0
  359. package/ui/public/sprites/14-L-1.png +0 -0
  360. package/ui/public/sprites/14-R-1.png +0 -0
  361. package/ui/public/sprites/2-D-1.png +0 -0
  362. package/ui/public/sprites/2-D-2.png +0 -0
  363. package/ui/public/sprites/2-D-3.png +0 -0
  364. package/ui/public/sprites/2-L-1.png +0 -0
  365. package/ui/public/sprites/2-R-1.png +0 -0
  366. package/ui/public/sprites/3-D-1.png +0 -0
  367. package/ui/public/sprites/3-D-2.png +0 -0
  368. package/ui/public/sprites/3-D-3.png +0 -0
  369. package/ui/public/sprites/3-L-1.png +0 -0
  370. package/ui/public/sprites/3-R-1.png +0 -0
  371. package/ui/public/sprites/4-D-1.png +0 -0
  372. package/ui/public/sprites/4-D-2.png +0 -0
  373. package/ui/public/sprites/4-D-3.png +0 -0
  374. package/ui/public/sprites/4-L-1.png +0 -0
  375. package/ui/public/sprites/4-R-1.png +0 -0
  376. package/ui/public/sprites/5-D-1.png +0 -0
  377. package/ui/public/sprites/5-D-2.png +0 -0
  378. package/ui/public/sprites/5-D-3.png +0 -0
  379. package/ui/public/sprites/5-L-1.png +0 -0
  380. package/ui/public/sprites/5-R-1.png +0 -0
  381. package/ui/public/sprites/6-D-1.png +0 -0
  382. package/ui/public/sprites/6-D-2.png +0 -0
  383. package/ui/public/sprites/6-D-3.png +0 -0
  384. package/ui/public/sprites/6-L-1.png +0 -0
  385. package/ui/public/sprites/6-R-1.png +0 -0
  386. package/ui/public/sprites/7-D-1.png +0 -0
  387. package/ui/public/sprites/7-D-2.png +0 -0
  388. package/ui/public/sprites/7-D-3.png +0 -0
  389. package/ui/public/sprites/7-L-1.png +0 -0
  390. package/ui/public/sprites/7-R-1.png +0 -0
  391. package/ui/public/sprites/8-D-1.png +0 -0
  392. package/ui/public/sprites/8-D-2.png +0 -0
  393. package/ui/public/sprites/8-D-3.png +0 -0
  394. package/ui/public/sprites/8-L-1.png +0 -0
  395. package/ui/public/sprites/8-R-1.png +0 -0
  396. package/ui/public/sprites/9-D-1.png +0 -0
  397. package/ui/public/sprites/9-D-2.png +0 -0
  398. package/ui/public/sprites/9-D-3.png +0 -0
  399. package/ui/public/sprites/9-L-1.png +0 -0
  400. package/ui/public/sprites/9-R-1.png +0 -0
  401. package/ui/public/sprites/ceo-lobster.png +0 -0
  402. package/ui/public/sw.js +42 -0
  403. package/ui/public/worktree-favicon-16x16.png +0 -0
  404. package/ui/public/worktree-favicon-32x32.png +0 -0
  405. package/ui/public/worktree-favicon.ico +0 -0
  406. package/ui/public/worktree-favicon.svg +9 -0
  407. package/ui/src/App.tsx +354 -0
  408. package/ui/src/adapters/claude-local/config-fields.tsx +138 -0
  409. package/ui/src/adapters/claude-local/index.ts +13 -0
  410. package/ui/src/adapters/codex-local/config-fields.tsx +104 -0
  411. package/ui/src/adapters/codex-local/index.ts +13 -0
  412. package/ui/src/adapters/cursor/config-fields.tsx +49 -0
  413. package/ui/src/adapters/cursor/index.ts +13 -0
  414. package/ui/src/adapters/gemini-local/config-fields.tsx +51 -0
  415. package/ui/src/adapters/gemini-local/index.ts +13 -0
  416. package/ui/src/adapters/http/build-config.ts +9 -0
  417. package/ui/src/adapters/http/config-fields.tsx +38 -0
  418. package/ui/src/adapters/http/index.ts +12 -0
  419. package/ui/src/adapters/http/parse-stdout.ts +5 -0
  420. package/ui/src/adapters/index.ts +9 -0
  421. package/ui/src/adapters/local-workspace-runtime-fields.tsx +5 -0
  422. package/ui/src/adapters/openclaw-gateway/config-fields.tsx +237 -0
  423. package/ui/src/adapters/openclaw-gateway/index.ts +13 -0
  424. package/ui/src/adapters/opencode-local/config-fields.tsx +72 -0
  425. package/ui/src/adapters/opencode-local/index.ts +13 -0
  426. package/ui/src/adapters/pi-local/config-fields.tsx +49 -0
  427. package/ui/src/adapters/pi-local/index.ts +13 -0
  428. package/ui/src/adapters/process/build-config.ts +18 -0
  429. package/ui/src/adapters/process/config-fields.tsx +77 -0
  430. package/ui/src/adapters/process/index.ts +12 -0
  431. package/ui/src/adapters/process/parse-stdout.ts +5 -0
  432. package/ui/src/adapters/registry.ts +34 -0
  433. package/ui/src/adapters/runtime-json-fields.tsx +122 -0
  434. package/ui/src/adapters/transcript.test.ts +30 -0
  435. package/ui/src/adapters/transcript.ts +62 -0
  436. package/ui/src/adapters/types.ts +34 -0
  437. package/ui/src/api/access.ts +160 -0
  438. package/ui/src/api/activity.ts +37 -0
  439. package/ui/src/api/agents.ts +194 -0
  440. package/ui/src/api/approvals.ts +25 -0
  441. package/ui/src/api/assets.ts +30 -0
  442. package/ui/src/api/auth.ts +74 -0
  443. package/ui/src/api/budgets.ts +21 -0
  444. package/ui/src/api/client.ts +50 -0
  445. package/ui/src/api/companies.ts +59 -0
  446. package/ui/src/api/companySkills.ts +55 -0
  447. package/ui/src/api/costs.ts +60 -0
  448. package/ui/src/api/dashboard.ts +7 -0
  449. package/ui/src/api/execution-workspaces.ts +27 -0
  450. package/ui/src/api/goals.ts +12 -0
  451. package/ui/src/api/health.ts +41 -0
  452. package/ui/src/api/heartbeats.ts +62 -0
  453. package/ui/src/api/index.ts +18 -0
  454. package/ui/src/api/instanceSettings.ts +19 -0
  455. package/ui/src/api/issues.ts +115 -0
  456. package/ui/src/api/plugins.ts +424 -0
  457. package/ui/src/api/projects.ts +34 -0
  458. package/ui/src/api/routines.ts +59 -0
  459. package/ui/src/api/secrets.ts +26 -0
  460. package/ui/src/api/sidebarBadges.ts +7 -0
  461. package/ui/src/components/AccountingModelCard.tsx +69 -0
  462. package/ui/src/components/ActiveAgentsPanel.tsx +157 -0
  463. package/ui/src/components/ActivityCharts.tsx +264 -0
  464. package/ui/src/components/ActivityRow.tsx +147 -0
  465. package/ui/src/components/AgentActionButtons.tsx +51 -0
  466. package/ui/src/components/AgentConfigForm.tsx +1468 -0
  467. package/ui/src/components/AgentIconPicker.tsx +81 -0
  468. package/ui/src/components/AgentProperties.tsx +107 -0
  469. package/ui/src/components/ApprovalCard.tsx +107 -0
  470. package/ui/src/components/ApprovalPayload.tsx +134 -0
  471. package/ui/src/components/AsciiArtAnimation.tsx +355 -0
  472. package/ui/src/components/BillerSpendCard.tsx +146 -0
  473. package/ui/src/components/BreadcrumbBar.tsx +113 -0
  474. package/ui/src/components/BudgetIncidentCard.tsx +101 -0
  475. package/ui/src/components/BudgetPolicyCard.tsx +220 -0
  476. package/ui/src/components/BudgetSidebarMarker.tsx +13 -0
  477. package/ui/src/components/ClaudeSubscriptionPanel.tsx +141 -0
  478. package/ui/src/components/CodexSubscriptionPanel.tsx +158 -0
  479. package/ui/src/components/CommandPalette.tsx +239 -0
  480. package/ui/src/components/CommentThread.tsx +503 -0
  481. package/ui/src/components/CompanyPatternIcon.tsx +212 -0
  482. package/ui/src/components/CompanyRail.tsx +329 -0
  483. package/ui/src/components/CompanySwitcher.tsx +81 -0
  484. package/ui/src/components/CopyText.tsx +56 -0
  485. package/ui/src/components/DevRestartBanner.tsx +89 -0
  486. package/ui/src/components/EmptyState.tsx +27 -0
  487. package/ui/src/components/EntityRow.tsx +69 -0
  488. package/ui/src/components/FilterBar.tsx +39 -0
  489. package/ui/src/components/FinanceBillerCard.tsx +45 -0
  490. package/ui/src/components/FinanceKindCard.tsx +44 -0
  491. package/ui/src/components/FinanceTimelineCard.tsx +72 -0
  492. package/ui/src/components/GoalProperties.tsx +165 -0
  493. package/ui/src/components/GoalTree.tsx +118 -0
  494. package/ui/src/components/Identity.tsx +39 -0
  495. package/ui/src/components/InlineEditor.tsx +248 -0
  496. package/ui/src/components/InlineEntitySelector.tsx +206 -0
  497. package/ui/src/components/InstanceSidebar.tsx +53 -0
  498. package/ui/src/components/IssueDocumentsSection.tsx +892 -0
  499. package/ui/src/components/IssueProperties.tsx +621 -0
  500. package/ui/src/components/IssueRow.tsx +149 -0
  501. package/ui/src/components/IssueWorkspaceCard.tsx +404 -0
  502. package/ui/src/components/IssuesList.tsx +889 -0
  503. package/ui/src/components/JsonSchemaForm.tsx +1048 -0
  504. package/ui/src/components/KanbanBoard.tsx +275 -0
  505. package/ui/src/components/Layout.tsx +441 -0
  506. package/ui/src/components/LiveRunWidget.tsx +160 -0
  507. package/ui/src/components/MarkdownBody.test.tsx +50 -0
  508. package/ui/src/components/MarkdownBody.tsx +152 -0
  509. package/ui/src/components/MarkdownEditor.tsx +622 -0
  510. package/ui/src/components/MetricCard.tsx +53 -0
  511. package/ui/src/components/MobileBottomNav.tsx +123 -0
  512. package/ui/src/components/NewAgentDialog.tsx +223 -0
  513. package/ui/src/components/NewGoalDialog.tsx +283 -0
  514. package/ui/src/components/NewIssueDialog.tsx +1473 -0
  515. package/ui/src/components/NewProjectDialog.tsx +451 -0
  516. package/ui/src/components/OnboardingWizard.tsx +1392 -0
  517. package/ui/src/components/OpenCodeLogoIcon.tsx +22 -0
  518. package/ui/src/components/PackageFileTree.tsx +318 -0
  519. package/ui/src/components/PageSkeleton.tsx +180 -0
  520. package/ui/src/components/PageTabBar.tsx +45 -0
  521. package/ui/src/components/PathInstructionsModal.tsx +143 -0
  522. package/ui/src/components/PriorityIcon.tsx +77 -0
  523. package/ui/src/components/ProjectProperties.tsx +1127 -0
  524. package/ui/src/components/PropertiesPanel.tsx +29 -0
  525. package/ui/src/components/ProviderQuotaCard.tsx +417 -0
  526. package/ui/src/components/QuotaBar.tsx +65 -0
  527. package/ui/src/components/ReportsToPicker.tsx +127 -0
  528. package/ui/src/components/ScheduleEditor.tsx +344 -0
  529. package/ui/src/components/ScrollToBottom.tsx +79 -0
  530. package/ui/src/components/Sidebar.tsx +130 -0
  531. package/ui/src/components/SidebarAgents.tsx +146 -0
  532. package/ui/src/components/SidebarNavItem.tsx +92 -0
  533. package/ui/src/components/SidebarProjects.tsx +234 -0
  534. package/ui/src/components/SidebarSection.tsx +17 -0
  535. package/ui/src/components/StatusBadge.tsx +15 -0
  536. package/ui/src/components/StatusIcon.tsx +71 -0
  537. package/ui/src/components/SwipeToArchive.tsx +152 -0
  538. package/ui/src/components/ToastViewport.tsx +99 -0
  539. package/ui/src/components/WorktreeBanner.tsx +25 -0
  540. package/ui/src/components/agent-config-defaults.ts +31 -0
  541. package/ui/src/components/agent-config-primitives.tsx +476 -0
  542. package/ui/src/components/transcript/RunTranscriptView.test.tsx +84 -0
  543. package/ui/src/components/transcript/RunTranscriptView.tsx +1015 -0
  544. package/ui/src/components/transcript/useLiveRunTranscripts.ts +297 -0
  545. package/ui/src/components/ui/avatar.tsx +107 -0
  546. package/ui/src/components/ui/badge.tsx +48 -0
  547. package/ui/src/components/ui/breadcrumb.tsx +109 -0
  548. package/ui/src/components/ui/button.tsx +64 -0
  549. package/ui/src/components/ui/card.tsx +92 -0
  550. package/ui/src/components/ui/checkbox.tsx +32 -0
  551. package/ui/src/components/ui/collapsible.tsx +33 -0
  552. package/ui/src/components/ui/command.tsx +194 -0
  553. package/ui/src/components/ui/dialog.tsx +156 -0
  554. package/ui/src/components/ui/dropdown-menu.tsx +257 -0
  555. package/ui/src/components/ui/input.tsx +21 -0
  556. package/ui/src/components/ui/label.tsx +22 -0
  557. package/ui/src/components/ui/popover.tsx +88 -0
  558. package/ui/src/components/ui/scroll-area.tsx +56 -0
  559. package/ui/src/components/ui/select.tsx +188 -0
  560. package/ui/src/components/ui/separator.tsx +28 -0
  561. package/ui/src/components/ui/sheet.tsx +143 -0
  562. package/ui/src/components/ui/skeleton.tsx +13 -0
  563. package/ui/src/components/ui/tabs.tsx +89 -0
  564. package/ui/src/components/ui/textarea.tsx +18 -0
  565. package/ui/src/components/ui/tooltip.tsx +57 -0
  566. package/ui/src/components/visual-office/AgentAvatar.tsx +99 -0
  567. package/ui/src/components/visual-office/OfficeViewExact.tsx +417 -0
  568. package/ui/src/components/visual-office/i18n.ts +52 -0
  569. package/ui/src/components/visual-office/office-view/CliUsagePanel.tsx +240 -0
  570. package/ui/src/components/visual-office/office-view/VirtualPadOverlay.tsx +104 -0
  571. package/ui/src/components/visual-office/office-view/buildScene-break-room.ts +248 -0
  572. package/ui/src/components/visual-office/office-view/buildScene-ceo-hallway.ts +345 -0
  573. package/ui/src/components/visual-office/office-view/buildScene-department-agent.ts +242 -0
  574. package/ui/src/components/visual-office/office-view/buildScene-departments.ts +360 -0
  575. package/ui/src/components/visual-office/office-view/buildScene-final-layers.ts +113 -0
  576. package/ui/src/components/visual-office/office-view/buildScene-types.ts +91 -0
  577. package/ui/src/components/visual-office/office-view/buildScene.ts +232 -0
  578. package/ui/src/components/visual-office/office-view/drawing-core.ts +374 -0
  579. package/ui/src/components/visual-office/office-view/drawing-furniture-a.ts +338 -0
  580. package/ui/src/components/visual-office/office-view/drawing-furniture-b.ts +241 -0
  581. package/ui/src/components/visual-office/office-view/model.ts +301 -0
  582. package/ui/src/components/visual-office/office-view/officeTicker.ts +455 -0
  583. package/ui/src/components/visual-office/office-view/officeTickerRoomAndDelivery.ts +133 -0
  584. package/ui/src/components/visual-office/office-view/themes-locale.ts +460 -0
  585. package/ui/src/components/visual-office/office-view/useCliUsage.ts +37 -0
  586. package/ui/src/components/visual-office/office-view/useOfficeDeliveryEffects.ts +465 -0
  587. package/ui/src/components/visual-office/office-view/useOfficePixiRuntime.ts +282 -0
  588. package/ui/src/components/visual-office/types.ts +123 -0
  589. package/ui/src/context/BreadcrumbContext.tsx +44 -0
  590. package/ui/src/context/CompanyContext.tsx +151 -0
  591. package/ui/src/context/DialogContext.tsx +135 -0
  592. package/ui/src/context/LiveUpdatesProvider.test.ts +119 -0
  593. package/ui/src/context/LiveUpdatesProvider.tsx +760 -0
  594. package/ui/src/context/PanelContext.tsx +73 -0
  595. package/ui/src/context/SidebarContext.tsx +43 -0
  596. package/ui/src/context/ThemeContext.tsx +83 -0
  597. package/ui/src/context/ToastContext.tsx +172 -0
  598. package/ui/src/fixtures/runTranscriptFixtures.ts +226 -0
  599. package/ui/src/hooks/useAgentOrder.ts +105 -0
  600. package/ui/src/hooks/useAutosaveIndicator.ts +72 -0
  601. package/ui/src/hooks/useCompanyPageMemory.test.ts +90 -0
  602. package/ui/src/hooks/useCompanyPageMemory.ts +79 -0
  603. package/ui/src/hooks/useDateRange.ts +120 -0
  604. package/ui/src/hooks/useInboxBadge.ts +132 -0
  605. package/ui/src/hooks/useKeyboardShortcuts.ts +40 -0
  606. package/ui/src/hooks/useProjectOrder.ts +106 -0
  607. package/ui/src/index.css +770 -0
  608. package/ui/src/lib/agent-icons.ts +99 -0
  609. package/ui/src/lib/agent-order.ts +107 -0
  610. package/ui/src/lib/agent-skills-state.test.ts +90 -0
  611. package/ui/src/lib/agent-skills-state.ts +41 -0
  612. package/ui/src/lib/assignees.test.ts +92 -0
  613. package/ui/src/lib/assignees.ts +82 -0
  614. package/ui/src/lib/color-contrast.ts +107 -0
  615. package/ui/src/lib/company-export-selection.test.ts +41 -0
  616. package/ui/src/lib/company-export-selection.ts +57 -0
  617. package/ui/src/lib/company-page-memory.ts +65 -0
  618. package/ui/src/lib/company-portability-sidebar.test.ts +101 -0
  619. package/ui/src/lib/company-portability-sidebar.ts +62 -0
  620. package/ui/src/lib/company-routes.ts +88 -0
  621. package/ui/src/lib/company-selection.test.ts +34 -0
  622. package/ui/src/lib/company-selection.ts +18 -0
  623. package/ui/src/lib/groupBy.ts +11 -0
  624. package/ui/src/lib/inbox.test.ts +404 -0
  625. package/ui/src/lib/inbox.ts +292 -0
  626. package/ui/src/lib/instance-settings.test.ts +26 -0
  627. package/ui/src/lib/instance-settings.ts +25 -0
  628. package/ui/src/lib/issueDetailBreadcrumb.ts +24 -0
  629. package/ui/src/lib/legacy-agent-config.test.ts +40 -0
  630. package/ui/src/lib/legacy-agent-config.ts +17 -0
  631. package/ui/src/lib/mention-aware-link-node.test.ts +50 -0
  632. package/ui/src/lib/mention-aware-link-node.ts +67 -0
  633. package/ui/src/lib/mention-chips.ts +168 -0
  634. package/ui/src/lib/mention-deletion.test.ts +87 -0
  635. package/ui/src/lib/mention-deletion.ts +143 -0
  636. package/ui/src/lib/model-utils.ts +16 -0
  637. package/ui/src/lib/onboarding-goal.test.ts +22 -0
  638. package/ui/src/lib/onboarding-goal.ts +18 -0
  639. package/ui/src/lib/onboarding-launch.test.ts +131 -0
  640. package/ui/src/lib/onboarding-launch.ts +54 -0
  641. package/ui/src/lib/onboarding-route.test.ts +80 -0
  642. package/ui/src/lib/onboarding-route.ts +51 -0
  643. package/ui/src/lib/portable-files.ts +42 -0
  644. package/ui/src/lib/project-order.ts +71 -0
  645. package/ui/src/lib/queryKeys.ts +140 -0
  646. package/ui/src/lib/recent-assignees.ts +36 -0
  647. package/ui/src/lib/router.tsx +76 -0
  648. package/ui/src/lib/routine-trigger-patch.test.ts +72 -0
  649. package/ui/src/lib/routine-trigger-patch.ts +31 -0
  650. package/ui/src/lib/status-colors.ts +108 -0
  651. package/ui/src/lib/timeAgo.ts +31 -0
  652. package/ui/src/lib/utils.ts +168 -0
  653. package/ui/src/lib/worktree-branding.ts +65 -0
  654. package/ui/src/lib/zip.test.ts +289 -0
  655. package/ui/src/lib/zip.ts +284 -0
  656. package/ui/src/main.tsx +67 -0
  657. package/ui/src/pages/Activity.tsx +141 -0
  658. package/ui/src/pages/AgentDetail.tsx +4053 -0
  659. package/ui/src/pages/Agents.tsx +415 -0
  660. package/ui/src/pages/ApprovalDetail.tsx +369 -0
  661. package/ui/src/pages/Approvals.tsx +132 -0
  662. package/ui/src/pages/Auth.tsx +180 -0
  663. package/ui/src/pages/BoardClaim.tsx +125 -0
  664. package/ui/src/pages/CliAuth.tsx +184 -0
  665. package/ui/src/pages/Companies.tsx +297 -0
  666. package/ui/src/pages/CompanyExport.tsx +1019 -0
  667. package/ui/src/pages/CompanyImport.tsx +1355 -0
  668. package/ui/src/pages/CompanySettings.tsx +661 -0
  669. package/ui/src/pages/CompanySkills.tsx +1171 -0
  670. package/ui/src/pages/Costs.tsx +1103 -0
  671. package/ui/src/pages/Dashboard.tsx +388 -0
  672. package/ui/src/pages/DesignGuide.tsx +1330 -0
  673. package/ui/src/pages/ExecutionWorkspaceDetail.tsx +82 -0
  674. package/ui/src/pages/GoalDetail.tsx +197 -0
  675. package/ui/src/pages/Goals.tsx +63 -0
  676. package/ui/src/pages/Inbox.tsx +1291 -0
  677. package/ui/src/pages/InstanceExperimentalSettings.tsx +139 -0
  678. package/ui/src/pages/InstanceGeneralSettings.tsx +104 -0
  679. package/ui/src/pages/InstanceSettings.tsx +284 -0
  680. package/ui/src/pages/InviteLanding.tsx +320 -0
  681. package/ui/src/pages/IssueDetail.tsx +1201 -0
  682. package/ui/src/pages/Issues.tsx +116 -0
  683. package/ui/src/pages/MyIssues.tsx +72 -0
  684. package/ui/src/pages/NewAgent.tsx +353 -0
  685. package/ui/src/pages/NotFound.tsx +66 -0
  686. package/ui/src/pages/Org.tsx +132 -0
  687. package/ui/src/pages/OrgChart.tsx +447 -0
  688. package/ui/src/pages/PluginManager.tsx +510 -0
  689. package/ui/src/pages/PluginPage.tsx +156 -0
  690. package/ui/src/pages/PluginSettings.tsx +836 -0
  691. package/ui/src/pages/ProjectDetail.tsx +633 -0
  692. package/ui/src/pages/Projects.tsx +87 -0
  693. package/ui/src/pages/RoutineDetail.tsx +1022 -0
  694. package/ui/src/pages/Routines.tsx +661 -0
  695. package/ui/src/pages/RunTranscriptUxLab.tsx +334 -0
  696. package/ui/src/pages/VisualOffice.tsx +243 -0
  697. package/ui/src/plugins/bridge-init.ts +69 -0
  698. package/ui/src/plugins/bridge.ts +476 -0
  699. package/ui/src/plugins/launchers.tsx +834 -0
  700. package/ui/src/plugins/slots.tsx +855 -0
  701. package/ui/tsconfig.json +21 -0
  702. package/ui/vite.config.ts +23 -0
  703. package/ui/vitest.config.ts +14 -0
  704. package/vitest.config.ts +11 -0
@@ -0,0 +1,661 @@
1
+ import { ChangeEvent, useEffect, useState } from "react";
2
+ import { useMutation, useQueryClient } from "@tanstack/react-query";
3
+ import { useCompany } from "../context/CompanyContext";
4
+ import { useBreadcrumbs } from "../context/BreadcrumbContext";
5
+ import { useToast } from "../context/ToastContext";
6
+ import { companiesApi } from "../api/companies";
7
+ import { accessApi } from "../api/access";
8
+ import { assetsApi } from "../api/assets";
9
+ import { queryKeys } from "../lib/queryKeys";
10
+ import { Button } from "@/components/ui/button";
11
+ import { Settings, Check, Download, Upload } from "lucide-react";
12
+ import { CompanyPatternIcon } from "../components/CompanyPatternIcon";
13
+ import {
14
+ Field,
15
+ ToggleField,
16
+ HintIcon
17
+ } from "../components/agent-config-primitives";
18
+
19
+ type AgentSnippetInput = {
20
+ onboardingTextUrl: string;
21
+ connectionCandidates?: string[] | null;
22
+ testResolutionUrl?: string | null;
23
+ };
24
+
25
+ export function CompanySettings() {
26
+ const {
27
+ companies,
28
+ selectedCompany,
29
+ selectedCompanyId,
30
+ setSelectedCompanyId
31
+ } = useCompany();
32
+ const { setBreadcrumbs } = useBreadcrumbs();
33
+ const { pushToast } = useToast();
34
+ const queryClient = useQueryClient();
35
+ // General settings local state
36
+ const [companyName, setCompanyName] = useState("");
37
+ const [description, setDescription] = useState("");
38
+ const [brandColor, setBrandColor] = useState("");
39
+ const [logoUrl, setLogoUrl] = useState("");
40
+ const [logoUploadError, setLogoUploadError] = useState<string | null>(null);
41
+
42
+ // Sync local state from selected company
43
+ useEffect(() => {
44
+ if (!selectedCompany) return;
45
+ setCompanyName(selectedCompany.name);
46
+ setDescription(selectedCompany.description ?? "");
47
+ setBrandColor(selectedCompany.brandColor ?? "");
48
+ setLogoUrl(selectedCompany.logoUrl ?? "");
49
+ }, [selectedCompany]);
50
+
51
+ const [inviteError, setInviteError] = useState<string | null>(null);
52
+ const [inviteSnippet, setInviteSnippet] = useState<string | null>(null);
53
+ const [snippetCopied, setSnippetCopied] = useState(false);
54
+ const [snippetCopyDelightId, setSnippetCopyDelightId] = useState(0);
55
+
56
+ const generalDirty =
57
+ !!selectedCompany &&
58
+ (companyName !== selectedCompany.name ||
59
+ description !== (selectedCompany.description ?? "") ||
60
+ brandColor !== (selectedCompany.brandColor ?? ""));
61
+
62
+ const generalMutation = useMutation({
63
+ mutationFn: (data: {
64
+ name: string;
65
+ description: string | null;
66
+ brandColor: string | null;
67
+ }) => companiesApi.update(selectedCompanyId!, data),
68
+ onSuccess: () => {
69
+ queryClient.invalidateQueries({ queryKey: queryKeys.companies.all });
70
+ }
71
+ });
72
+
73
+ const settingsMutation = useMutation({
74
+ mutationFn: (requireApproval: boolean) =>
75
+ companiesApi.update(selectedCompanyId!, {
76
+ requireBoardApprovalForNewAgents: requireApproval
77
+ }),
78
+ onSuccess: () => {
79
+ queryClient.invalidateQueries({ queryKey: queryKeys.companies.all });
80
+ }
81
+ });
82
+
83
+ const inviteMutation = useMutation({
84
+ mutationFn: () =>
85
+ accessApi.createOpenClawInvitePrompt(selectedCompanyId!),
86
+ onSuccess: async (invite) => {
87
+ setInviteError(null);
88
+ const base = window.location.origin.replace(/\/+$/, "");
89
+ const onboardingTextLink =
90
+ invite.onboardingTextUrl ??
91
+ invite.onboardingTextPath ??
92
+ `/api/invites/${invite.token}/onboarding.txt`;
93
+ const absoluteUrl = onboardingTextLink.startsWith("http")
94
+ ? onboardingTextLink
95
+ : `${base}${onboardingTextLink}`;
96
+ setSnippetCopied(false);
97
+ setSnippetCopyDelightId(0);
98
+ let snippet: string;
99
+ try {
100
+ const manifest = await accessApi.getInviteOnboarding(invite.token);
101
+ snippet = buildAgentSnippet({
102
+ onboardingTextUrl: absoluteUrl,
103
+ connectionCandidates:
104
+ manifest.onboarding.connectivity?.connectionCandidates ?? null,
105
+ testResolutionUrl:
106
+ manifest.onboarding.connectivity?.testResolutionEndpoint?.url ??
107
+ null
108
+ });
109
+ } catch {
110
+ snippet = buildAgentSnippet({
111
+ onboardingTextUrl: absoluteUrl,
112
+ connectionCandidates: null,
113
+ testResolutionUrl: null
114
+ });
115
+ }
116
+ setInviteSnippet(snippet);
117
+ try {
118
+ await navigator.clipboard.writeText(snippet);
119
+ setSnippetCopied(true);
120
+ setSnippetCopyDelightId((prev) => prev + 1);
121
+ setTimeout(() => setSnippetCopied(false), 2000);
122
+ } catch {
123
+ /* clipboard may not be available */
124
+ }
125
+ queryClient.invalidateQueries({
126
+ queryKey: queryKeys.sidebarBadges(selectedCompanyId!)
127
+ });
128
+ },
129
+ onError: (err) => {
130
+ setInviteError(
131
+ err instanceof Error ? err.message : "Failed to create invite"
132
+ );
133
+ }
134
+ });
135
+
136
+ const syncLogoState = (nextLogoUrl: string | null) => {
137
+ setLogoUrl(nextLogoUrl ?? "");
138
+ void queryClient.invalidateQueries({ queryKey: queryKeys.companies.all });
139
+ };
140
+
141
+ const logoUploadMutation = useMutation({
142
+ mutationFn: (file: File) =>
143
+ assetsApi
144
+ .uploadCompanyLogo(selectedCompanyId!, file)
145
+ .then((asset) => companiesApi.update(selectedCompanyId!, { logoAssetId: asset.assetId })),
146
+ onSuccess: (company) => {
147
+ syncLogoState(company.logoUrl);
148
+ setLogoUploadError(null);
149
+ }
150
+ });
151
+
152
+ const clearLogoMutation = useMutation({
153
+ mutationFn: () => companiesApi.update(selectedCompanyId!, { logoAssetId: null }),
154
+ onSuccess: (company) => {
155
+ setLogoUploadError(null);
156
+ syncLogoState(company.logoUrl);
157
+ }
158
+ });
159
+
160
+ function handleLogoFileChange(event: ChangeEvent<HTMLInputElement>) {
161
+ const file = event.target.files?.[0] ?? null;
162
+ event.currentTarget.value = "";
163
+ if (!file) return;
164
+ setLogoUploadError(null);
165
+ logoUploadMutation.mutate(file);
166
+ }
167
+
168
+ function handleClearLogo() {
169
+ clearLogoMutation.mutate();
170
+ }
171
+
172
+ useEffect(() => {
173
+ setInviteError(null);
174
+ setInviteSnippet(null);
175
+ setSnippetCopied(false);
176
+ setSnippetCopyDelightId(0);
177
+ }, [selectedCompanyId]);
178
+
179
+ const archiveMutation = useMutation({
180
+ mutationFn: ({
181
+ companyId,
182
+ nextCompanyId
183
+ }: {
184
+ companyId: string;
185
+ nextCompanyId: string | null;
186
+ }) => companiesApi.archive(companyId).then(() => ({ nextCompanyId })),
187
+ onSuccess: async ({ nextCompanyId }) => {
188
+ if (nextCompanyId) {
189
+ setSelectedCompanyId(nextCompanyId);
190
+ }
191
+ await queryClient.invalidateQueries({
192
+ queryKey: queryKeys.companies.all
193
+ });
194
+ await queryClient.invalidateQueries({
195
+ queryKey: queryKeys.companies.stats
196
+ });
197
+ }
198
+ });
199
+
200
+ useEffect(() => {
201
+ setBreadcrumbs([
202
+ { label: selectedCompany?.name ?? "Company", href: "/dashboard" },
203
+ { label: "Settings" }
204
+ ]);
205
+ }, [setBreadcrumbs, selectedCompany?.name]);
206
+
207
+ if (!selectedCompany) {
208
+ return (
209
+ <div className="text-sm text-muted-foreground">
210
+ No company selected. Select a company from the switcher above.
211
+ </div>
212
+ );
213
+ }
214
+
215
+ function handleSaveGeneral() {
216
+ generalMutation.mutate({
217
+ name: companyName.trim(),
218
+ description: description.trim() || null,
219
+ brandColor: brandColor || null
220
+ });
221
+ }
222
+
223
+ return (
224
+ <div className="max-w-2xl space-y-6">
225
+ <div className="flex items-center gap-2">
226
+ <Settings className="h-5 w-5 text-muted-foreground" />
227
+ <h1 className="text-lg font-semibold">Company Settings</h1>
228
+ </div>
229
+
230
+ {/* General */}
231
+ <div className="space-y-4">
232
+ <div className="text-xs font-medium text-muted-foreground uppercase tracking-wide">
233
+ General
234
+ </div>
235
+ <div className="space-y-3 rounded-md border border-border px-4 py-4">
236
+ <Field label="Company name" hint="The display name for your company.">
237
+ <input
238
+ className="w-full rounded-md border border-border bg-transparent px-2.5 py-1.5 text-sm outline-none"
239
+ type="text"
240
+ value={companyName}
241
+ onChange={(e) => setCompanyName(e.target.value)}
242
+ />
243
+ </Field>
244
+ <Field
245
+ label="Description"
246
+ hint="Optional description shown in the company profile."
247
+ >
248
+ <input
249
+ className="w-full rounded-md border border-border bg-transparent px-2.5 py-1.5 text-sm outline-none"
250
+ type="text"
251
+ value={description}
252
+ placeholder="Optional company description"
253
+ onChange={(e) => setDescription(e.target.value)}
254
+ />
255
+ </Field>
256
+ </div>
257
+ </div>
258
+
259
+ {/* Appearance */}
260
+ <div className="space-y-4">
261
+ <div className="text-xs font-medium text-muted-foreground uppercase tracking-wide">
262
+ Appearance
263
+ </div>
264
+ <div className="space-y-3 rounded-md border border-border px-4 py-4">
265
+ <div className="flex items-start gap-4">
266
+ <div className="shrink-0">
267
+ <CompanyPatternIcon
268
+ companyName={companyName || selectedCompany.name}
269
+ logoUrl={logoUrl || null}
270
+ brandColor={brandColor || null}
271
+ className="rounded-[14px]"
272
+ />
273
+ </div>
274
+ <div className="flex-1 space-y-3">
275
+ <Field
276
+ label="Logo"
277
+ hint="Upload a PNG, JPEG, WEBP, GIF, or SVG logo image."
278
+ >
279
+ <div className="space-y-2">
280
+ <input
281
+ type="file"
282
+ accept="image/png,image/jpeg,image/webp,image/gif,image/svg+xml"
283
+ onChange={handleLogoFileChange}
284
+ className="w-full rounded-md border border-border bg-transparent px-2.5 py-1.5 text-sm outline-none file:mr-4 file:rounded-md file:border-0 file:bg-muted file:px-2.5 file:py-1 file:text-xs"
285
+ />
286
+ {logoUrl && (
287
+ <div className="flex items-center gap-2">
288
+ <Button
289
+ size="sm"
290
+ variant="outline"
291
+ onClick={handleClearLogo}
292
+ disabled={clearLogoMutation.isPending}
293
+ >
294
+ {clearLogoMutation.isPending ? "Removing..." : "Remove logo"}
295
+ </Button>
296
+ </div>
297
+ )}
298
+ {(logoUploadMutation.isError || logoUploadError) && (
299
+ <span className="text-xs text-destructive">
300
+ {logoUploadError ??
301
+ (logoUploadMutation.error instanceof Error
302
+ ? logoUploadMutation.error.message
303
+ : "Logo upload failed")}
304
+ </span>
305
+ )}
306
+ {clearLogoMutation.isError && (
307
+ <span className="text-xs text-destructive">
308
+ {clearLogoMutation.error.message}
309
+ </span>
310
+ )}
311
+ {logoUploadMutation.isPending && (
312
+ <span className="text-xs text-muted-foreground">Uploading logo...</span>
313
+ )}
314
+ </div>
315
+ </Field>
316
+ <Field
317
+ label="Brand color"
318
+ hint="Sets the hue for the company icon. Leave empty for auto-generated color."
319
+ >
320
+ <div className="flex items-center gap-2">
321
+ <input
322
+ type="color"
323
+ value={brandColor || "#6366f1"}
324
+ onChange={(e) => setBrandColor(e.target.value)}
325
+ className="h-8 w-8 cursor-pointer rounded border border-border bg-transparent p-0"
326
+ />
327
+ <input
328
+ type="text"
329
+ value={brandColor}
330
+ onChange={(e) => {
331
+ const v = e.target.value;
332
+ if (v === "" || /^#[0-9a-fA-F]{0,6}$/.test(v)) {
333
+ setBrandColor(v);
334
+ }
335
+ }}
336
+ placeholder="Auto"
337
+ className="w-28 rounded-md border border-border bg-transparent px-2.5 py-1.5 text-sm font-mono outline-none"
338
+ />
339
+ {brandColor && (
340
+ <Button
341
+ size="sm"
342
+ variant="ghost"
343
+ onClick={() => setBrandColor("")}
344
+ className="text-xs text-muted-foreground"
345
+ >
346
+ Clear
347
+ </Button>
348
+ )}
349
+ </div>
350
+ </Field>
351
+ </div>
352
+ </div>
353
+ </div>
354
+ </div>
355
+
356
+ {/* Save button for General + Appearance */}
357
+ {generalDirty && (
358
+ <div className="flex items-center gap-2">
359
+ <Button
360
+ size="sm"
361
+ onClick={handleSaveGeneral}
362
+ disabled={generalMutation.isPending || !companyName.trim()}
363
+ >
364
+ {generalMutation.isPending ? "Saving..." : "Save changes"}
365
+ </Button>
366
+ {generalMutation.isSuccess && (
367
+ <span className="text-xs text-muted-foreground">Saved</span>
368
+ )}
369
+ {generalMutation.isError && (
370
+ <span className="text-xs text-destructive">
371
+ {generalMutation.error instanceof Error
372
+ ? generalMutation.error.message
373
+ : "Failed to save"}
374
+ </span>
375
+ )}
376
+ </div>
377
+ )}
378
+
379
+ {/* Hiring */}
380
+ <div className="space-y-4">
381
+ <div className="text-xs font-medium text-muted-foreground uppercase tracking-wide">
382
+ Hiring
383
+ </div>
384
+ <div className="rounded-md border border-border px-4 py-3">
385
+ <ToggleField
386
+ label="Require board approval for new hires"
387
+ hint="New agent hires stay pending until approved by board."
388
+ checked={!!selectedCompany.requireBoardApprovalForNewAgents}
389
+ onChange={(v) => settingsMutation.mutate(v)}
390
+ />
391
+ </div>
392
+ </div>
393
+
394
+ {/* Invites */}
395
+ <div className="space-y-4">
396
+ <div className="text-xs font-medium text-muted-foreground uppercase tracking-wide">
397
+ Invites
398
+ </div>
399
+ <div className="space-y-3 rounded-md border border-border px-4 py-4">
400
+ <div className="flex items-center gap-1.5">
401
+ <span className="text-xs text-muted-foreground">
402
+ Generate an OpenClaw agent invite snippet.
403
+ </span>
404
+ <HintIcon text="Creates a short-lived OpenClaw agent invite and renders a copy-ready prompt." />
405
+ </div>
406
+ <div className="flex flex-wrap items-center gap-2">
407
+ <Button
408
+ size="sm"
409
+ onClick={() => inviteMutation.mutate()}
410
+ disabled={inviteMutation.isPending}
411
+ >
412
+ {inviteMutation.isPending
413
+ ? "Generating..."
414
+ : "Generate OpenClaw Invite Prompt"}
415
+ </Button>
416
+ </div>
417
+ {inviteError && (
418
+ <p className="text-sm text-destructive">{inviteError}</p>
419
+ )}
420
+ {inviteSnippet && (
421
+ <div className="rounded-md border border-border bg-muted/30 p-2">
422
+ <div className="flex items-center justify-between gap-2">
423
+ <div className="text-xs text-muted-foreground">
424
+ OpenClaw Invite Prompt
425
+ </div>
426
+ {snippetCopied && (
427
+ <span
428
+ key={snippetCopyDelightId}
429
+ className="flex items-center gap-1 text-xs text-green-600 animate-pulse"
430
+ >
431
+ <Check className="h-3 w-3" />
432
+ Copied
433
+ </span>
434
+ )}
435
+ </div>
436
+ <div className="mt-1 space-y-1.5">
437
+ <textarea
438
+ className="h-[28rem] w-full rounded-md border border-border bg-background px-2 py-1.5 font-mono text-xs outline-none"
439
+ value={inviteSnippet}
440
+ readOnly
441
+ />
442
+ <div className="flex justify-end">
443
+ <Button
444
+ size="sm"
445
+ variant="ghost"
446
+ onClick={async () => {
447
+ try {
448
+ await navigator.clipboard.writeText(inviteSnippet);
449
+ setSnippetCopied(true);
450
+ setSnippetCopyDelightId((prev) => prev + 1);
451
+ setTimeout(() => setSnippetCopied(false), 2000);
452
+ } catch {
453
+ /* clipboard may not be available */
454
+ }
455
+ }}
456
+ >
457
+ {snippetCopied ? "Copied snippet" : "Copy snippet"}
458
+ </Button>
459
+ </div>
460
+ </div>
461
+ </div>
462
+ )}
463
+ </div>
464
+ </div>
465
+
466
+ {/* Import / Export */}
467
+ <div className="space-y-4">
468
+ <div className="text-xs font-medium text-muted-foreground uppercase tracking-wide">
469
+ Company Packages
470
+ </div>
471
+ <div className="rounded-md border border-border px-4 py-4">
472
+ <p className="text-sm text-muted-foreground">
473
+ Import and export have moved to dedicated pages accessible from the{" "}
474
+ <a href="/org" className="underline hover:text-foreground">Org Chart</a> header.
475
+ </p>
476
+ <div className="mt-3 flex items-center gap-2">
477
+ <Button size="sm" variant="outline" asChild>
478
+ <a href="/company/export">
479
+ <Download className="mr-1.5 h-3.5 w-3.5" />
480
+ Export
481
+ </a>
482
+ </Button>
483
+ <Button size="sm" variant="outline" asChild>
484
+ <a href="/company/import">
485
+ <Upload className="mr-1.5 h-3.5 w-3.5" />
486
+ Import
487
+ </a>
488
+ </Button>
489
+ </div>
490
+ </div>
491
+ </div>
492
+
493
+ {/* Danger Zone */}
494
+ <div className="space-y-4">
495
+ <div className="text-xs font-medium text-destructive uppercase tracking-wide">
496
+ Danger Zone
497
+ </div>
498
+ <div className="space-y-3 rounded-md border border-destructive/40 bg-destructive/5 px-4 py-4">
499
+ <p className="text-sm text-muted-foreground">
500
+ Archive this company to hide it from the sidebar. This persists in
501
+ the database.
502
+ </p>
503
+ <div className="flex items-center gap-2">
504
+ <Button
505
+ size="sm"
506
+ variant="destructive"
507
+ disabled={
508
+ archiveMutation.isPending ||
509
+ selectedCompany.status === "archived"
510
+ }
511
+ onClick={() => {
512
+ if (!selectedCompanyId) return;
513
+ const confirmed = window.confirm(
514
+ `Archive company "${selectedCompany.name}"? It will be hidden from the sidebar.`
515
+ );
516
+ if (!confirmed) return;
517
+ const nextCompanyId =
518
+ companies.find(
519
+ (company) =>
520
+ company.id !== selectedCompanyId &&
521
+ company.status !== "archived"
522
+ )?.id ?? null;
523
+ archiveMutation.mutate({
524
+ companyId: selectedCompanyId,
525
+ nextCompanyId
526
+ });
527
+ }}
528
+ >
529
+ {archiveMutation.isPending
530
+ ? "Archiving..."
531
+ : selectedCompany.status === "archived"
532
+ ? "Already archived"
533
+ : "Archive company"}
534
+ </Button>
535
+ {archiveMutation.isError && (
536
+ <span className="text-xs text-destructive">
537
+ {archiveMutation.error instanceof Error
538
+ ? archiveMutation.error.message
539
+ : "Failed to archive company"}
540
+ </span>
541
+ )}
542
+ </div>
543
+ </div>
544
+ </div>
545
+ </div>
546
+ );
547
+ }
548
+
549
+ function buildAgentSnippet(input: AgentSnippetInput) {
550
+ const candidateUrls = buildCandidateOnboardingUrls(input);
551
+ const resolutionTestUrl = buildResolutionTestUrl(input);
552
+
553
+ const candidateList =
554
+ candidateUrls.length > 0
555
+ ? candidateUrls.map((u) => `- ${u}`).join("\n")
556
+ : "- (No candidate URLs available yet.)";
557
+
558
+ const connectivityBlock =
559
+ candidateUrls.length === 0
560
+ ? `No candidate URLs are available. Ask your user to configure a reachable hostname in Corporate, then retry.
561
+ Suggested steps:
562
+ - choose a hostname that resolves to the Corporate host from your runtime
563
+ - run: pnpm corporateai allowed-hostname <host>
564
+ - restart Corporate
565
+ - verify with: curl -fsS http://<host>:3100/api/health
566
+ - regenerate this invite snippet`
567
+ : `If none are reachable, ask your user to add a reachable hostname in Corporate, restart, and retry.
568
+ Suggested command:
569
+ - pnpm corporateai allowed-hostname <host>
570
+ Then verify with: curl -fsS <base-url>/api/health`;
571
+
572
+ const resolutionLine = resolutionTestUrl
573
+ ? `\nYou MUST test Corporate-to-gateway reachability, call: ${resolutionTestUrl}?url=<urlencoded-gateway-url> (using the hostname that worked above). Do not assume your 172.x is necessarily reachable from Corporate. Test it. `
574
+ : "";
575
+
576
+ return `You're invited to join a Corporate organization.
577
+
578
+ The URLs you should try are:
579
+ ${candidateList}
580
+
581
+ Connectivity guidance:
582
+ If you are running on a different machine than Corporate, Corporate must be reachable at one of the hostnames used above.
583
+ Verify the hostname works from your runtime with: GET <base-url>/api/health
584
+
585
+ ${connectivityBlock}
586
+
587
+ For your "agentName", just use your own agent name (OpenClaw or whatever your name is) and send it directly.
588
+ You also need to send a gateway URL that Corporate can access. Check your config and include that URL.${resolutionLine}
589
+
590
+ ---
591
+
592
+ This onboarding flow is for OpenClaw Gateway.
593
+ When you submit the join request, use:
594
+ - \`adapterType: "openclaw_gateway"\`
595
+ - \`agentDefaultsPayload.url\` as your \`ws://\` or \`wss://\` gateway URL
596
+ - \`agentDefaultsPayload.headers["x-openclaw-token"]\` with your gateway token
597
+ - (legacy accepted) \`agentDefaultsPayload.headers["x-openclaw-auth"]\`
598
+ - Keep device auth enabled (recommended). If \`devicePrivateKeyPem\` is omitted, Corporate will generate and persist one during join so pairing approvals remain stable.
599
+ - Only use \`disableDeviceAuth=true\` for special environments where pairing cannot be completed.
600
+
601
+ Do NOT use \`/v1/responses\` or \`/hooks/*\` in this join flow.
602
+
603
+ Before you do anything, please respond to your user that you understand the instructions and you're going to work on them. Then do the step above in another session called "corporate-onboarding" and then tell your user when you're done. Update your user in intermediate steps along the way so they know what's going on.
604
+
605
+ Then after you've connected to Corporate (exchanged keys etc.) you MUST review and follow the onboarding instructions in onboarding.txt they give you.
606
+
607
+ `;
608
+ }
609
+
610
+ function buildCandidateOnboardingUrls(input: AgentSnippetInput): string[] {
611
+ const candidates = (input.connectionCandidates ?? [])
612
+ .map((candidate) => candidate.trim())
613
+ .filter(Boolean);
614
+ const urls = new Set<string>();
615
+ let onboardingUrl: URL | null = null;
616
+
617
+ try {
618
+ onboardingUrl = new URL(input.onboardingTextUrl);
619
+ urls.add(onboardingUrl.toString());
620
+ } catch {
621
+ const trimmed = input.onboardingTextUrl.trim();
622
+ if (trimmed) {
623
+ urls.add(trimmed);
624
+ }
625
+ }
626
+
627
+ if (!onboardingUrl) {
628
+ for (const candidate of candidates) {
629
+ urls.add(candidate);
630
+ }
631
+ return Array.from(urls);
632
+ }
633
+
634
+ const onboardingPath = `${onboardingUrl.pathname}${onboardingUrl.search}`;
635
+ for (const candidate of candidates) {
636
+ try {
637
+ const base = new URL(candidate);
638
+ urls.add(`${base.origin}${onboardingPath}`);
639
+ } catch {
640
+ urls.add(candidate);
641
+ }
642
+ }
643
+
644
+ return Array.from(urls);
645
+ }
646
+
647
+ function buildResolutionTestUrl(input: AgentSnippetInput): string | null {
648
+ const explicit = input.testResolutionUrl?.trim();
649
+ if (explicit) return explicit;
650
+
651
+ try {
652
+ const onboardingUrl = new URL(input.onboardingTextUrl);
653
+ const testPath = onboardingUrl.pathname.replace(
654
+ /\/onboarding\.txt$/,
655
+ "/test-resolution"
656
+ );
657
+ return `${onboardingUrl.origin}${testPath}`;
658
+ } catch {
659
+ return null;
660
+ }
661
+ }