@tianshu-ai/tianshu 0.3.0 → 0.3.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 (244) hide show
  1. package/README.md +27 -7
  2. package/node_modules/@tianshu-ai/plugin-sdk/dist/agent-loop.d.ts +96 -0
  3. package/node_modules/@tianshu-ai/plugin-sdk/dist/agent-loop.d.ts.map +1 -0
  4. package/node_modules/@tianshu-ai/plugin-sdk/dist/agent-loop.js +11 -0
  5. package/node_modules/@tianshu-ai/plugin-sdk/dist/agent-loop.js.map +1 -0
  6. package/node_modules/@tianshu-ai/plugin-sdk/dist/capabilities.d.ts +48 -0
  7. package/node_modules/@tianshu-ai/plugin-sdk/dist/capabilities.d.ts.map +1 -0
  8. package/node_modules/@tianshu-ai/plugin-sdk/dist/capabilities.js +61 -0
  9. package/node_modules/@tianshu-ai/plugin-sdk/dist/capabilities.js.map +1 -0
  10. package/node_modules/@tianshu-ai/plugin-sdk/dist/catalog.d.ts +60 -0
  11. package/node_modules/@tianshu-ai/plugin-sdk/dist/catalog.d.ts.map +1 -0
  12. package/node_modules/@tianshu-ai/plugin-sdk/dist/catalog.js +11 -0
  13. package/node_modules/@tianshu-ai/plugin-sdk/dist/catalog.js.map +1 -0
  14. package/node_modules/@tianshu-ai/plugin-sdk/dist/client.d.ts +171 -0
  15. package/node_modules/@tianshu-ai/plugin-sdk/dist/client.d.ts.map +1 -0
  16. package/node_modules/@tianshu-ai/plugin-sdk/dist/client.js +96 -0
  17. package/node_modules/@tianshu-ai/plugin-sdk/dist/client.js.map +1 -0
  18. package/node_modules/@tianshu-ai/plugin-sdk/dist/index.d.ts +9 -0
  19. package/node_modules/@tianshu-ai/plugin-sdk/dist/index.d.ts.map +1 -0
  20. package/node_modules/@tianshu-ai/plugin-sdk/dist/index.js +19 -0
  21. package/node_modules/@tianshu-ai/plugin-sdk/dist/index.js.map +1 -0
  22. package/node_modules/@tianshu-ai/plugin-sdk/dist/lsp.d.ts +32 -0
  23. package/node_modules/@tianshu-ai/plugin-sdk/dist/lsp.d.ts.map +1 -0
  24. package/node_modules/@tianshu-ai/plugin-sdk/dist/lsp.js +19 -0
  25. package/node_modules/@tianshu-ai/plugin-sdk/dist/lsp.js.map +1 -0
  26. package/node_modules/@tianshu-ai/plugin-sdk/dist/manifest.d.ts +423 -0
  27. package/node_modules/@tianshu-ai/plugin-sdk/dist/manifest.d.ts.map +1 -0
  28. package/node_modules/@tianshu-ai/plugin-sdk/dist/manifest.js +7 -0
  29. package/node_modules/@tianshu-ai/plugin-sdk/dist/manifest.js.map +1 -0
  30. package/node_modules/@tianshu-ai/plugin-sdk/dist/mcp-fetch.d.ts +10 -0
  31. package/node_modules/@tianshu-ai/plugin-sdk/dist/mcp-fetch.d.ts.map +1 -0
  32. package/node_modules/@tianshu-ai/plugin-sdk/dist/mcp-fetch.js +130 -0
  33. package/node_modules/@tianshu-ai/plugin-sdk/dist/mcp-fetch.js.map +1 -0
  34. package/node_modules/@tianshu-ai/plugin-sdk/dist/mcp-toolset.d.ts +128 -0
  35. package/node_modules/@tianshu-ai/plugin-sdk/dist/mcp-toolset.d.ts.map +1 -0
  36. package/node_modules/@tianshu-ai/plugin-sdk/dist/mcp-toolset.js +246 -0
  37. package/node_modules/@tianshu-ai/plugin-sdk/dist/mcp-toolset.js.map +1 -0
  38. package/node_modules/@tianshu-ai/plugin-sdk/dist/server.d.ts +486 -0
  39. package/node_modules/@tianshu-ai/plugin-sdk/dist/server.d.ts.map +1 -0
  40. package/node_modules/@tianshu-ai/plugin-sdk/dist/server.js +10 -0
  41. package/node_modules/@tianshu-ai/plugin-sdk/dist/server.js.map +1 -0
  42. package/node_modules/@tianshu-ai/plugin-sdk/dist/session-inbox.d.ts +56 -0
  43. package/node_modules/@tianshu-ai/plugin-sdk/dist/session-inbox.d.ts.map +1 -0
  44. package/node_modules/@tianshu-ai/plugin-sdk/dist/session-inbox.js +12 -0
  45. package/node_modules/@tianshu-ai/plugin-sdk/dist/session-inbox.js.map +1 -0
  46. package/node_modules/@tianshu-ai/plugin-sdk/package.json +36 -0
  47. package/node_modules/@tianshu-ai/plugin-sdk/src/agent-loop.ts +115 -0
  48. package/node_modules/@tianshu-ai/plugin-sdk/src/capabilities.ts +79 -0
  49. package/node_modules/@tianshu-ai/plugin-sdk/src/catalog.ts +71 -0
  50. package/node_modules/@tianshu-ai/plugin-sdk/src/client.test.ts +47 -0
  51. package/node_modules/@tianshu-ai/plugin-sdk/src/client.ts +321 -0
  52. package/node_modules/@tianshu-ai/plugin-sdk/src/index.ts +29 -0
  53. package/node_modules/@tianshu-ai/plugin-sdk/src/lsp.ts +51 -0
  54. package/node_modules/@tianshu-ai/plugin-sdk/src/manifest.ts +457 -0
  55. package/node_modules/@tianshu-ai/plugin-sdk/src/mcp-fetch.ts +133 -0
  56. package/node_modules/@tianshu-ai/plugin-sdk/src/mcp-toolset.test.ts +72 -0
  57. package/node_modules/@tianshu-ai/plugin-sdk/src/mcp-toolset.ts +357 -0
  58. package/node_modules/@tianshu-ai/plugin-sdk/src/server.test.ts +32 -0
  59. package/node_modules/@tianshu-ai/plugin-sdk/src/server.ts +531 -0
  60. package/node_modules/@tianshu-ai/plugin-sdk/src/session-inbox.ts +72 -0
  61. package/package.json +27 -2
  62. package/packages/plugin-sdk/dist/client.d.ts +1 -1
  63. package/packages/plugin-sdk/dist/client.js +1 -1
  64. package/packages/plugin-sdk/dist/client.js.map +1 -1
  65. package/packages/plugin-sdk/dist/index.js +2 -2
  66. package/packages/plugin-sdk/dist/index.js.map +1 -1
  67. package/packages/plugin-sdk/package.json +2 -2
  68. package/packages/server/dist/chat/session-inbox.d.ts +1 -1
  69. package/packages/server/dist/chat/session-inbox.d.ts.map +1 -1
  70. package/packages/server/dist/cli.d.ts.map +1 -1
  71. package/packages/server/dist/cli.js +9 -0
  72. package/packages/server/dist/cli.js.map +1 -1
  73. package/packages/server/dist/core/agent-seeds.d.ts +1 -1
  74. package/packages/server/dist/core/agent-seeds.d.ts.map +1 -1
  75. package/packages/server/dist/core/mcp-manager.d.ts +1 -1
  76. package/packages/server/dist/core/mcp-manager.d.ts.map +1 -1
  77. package/packages/server/dist/core/mcp-manager.js +1 -1
  78. package/packages/server/dist/core/mcp-manager.js.map +1 -1
  79. package/packages/server/dist/core/plugins/builtin-loader.d.ts +1 -1
  80. package/packages/server/dist/core/plugins/builtin-loader.d.ts.map +1 -1
  81. package/packages/server/dist/core/plugins/discovery.d.ts +1 -1
  82. package/packages/server/dist/core/plugins/discovery.d.ts.map +1 -1
  83. package/packages/server/dist/core/plugins/manifest.d.ts +1 -1
  84. package/packages/server/dist/core/plugins/manifest.d.ts.map +1 -1
  85. package/packages/server/dist/core/plugins/manifest.js +4 -4
  86. package/packages/server/dist/core/plugins/manifest.js.map +1 -1
  87. package/packages/server/dist/core/plugins/registry.d.ts +3 -3
  88. package/packages/server/dist/core/plugins/registry.d.ts.map +1 -1
  89. package/packages/server/dist/core/plugins/registry.js +1 -1
  90. package/packages/server/dist/core/plugins/registry.js.map +1 -1
  91. package/packages/server/dist/core/plugins/secrets.d.ts +1 -1
  92. package/packages/server/dist/core/plugins/secrets.d.ts.map +1 -1
  93. package/packages/server/dist/core/plugins/skills.d.ts +1 -1
  94. package/packages/server/dist/core/plugins/skills.d.ts.map +1 -1
  95. package/packages/server/dist/plugins-routes.d.ts +2 -2
  96. package/packages/server/dist/setup/update.d.ts +20 -0
  97. package/packages/server/dist/setup/update.d.ts.map +1 -0
  98. package/packages/server/dist/setup/update.js +213 -0
  99. package/packages/server/dist/setup/update.js.map +1 -0
  100. package/packages/server/dist/tools/index.d.ts +1 -1
  101. package/packages/server/dist/tools/index.d.ts.map +1 -1
  102. package/packages/server/package.json +1 -1
  103. package/plugins/README.md +1 -1
  104. package/plugins/files/dist/client.d.ts +2 -2
  105. package/plugins/files/dist/client.d.ts.map +1 -1
  106. package/plugins/files/dist/client.js +1 -1
  107. package/plugins/files/dist/client.js.map +1 -1
  108. package/plugins/files/dist/server.d.ts +1 -1
  109. package/plugins/files/dist/server.d.ts.map +1 -1
  110. package/plugins/files/dist/tools/index.d.ts +1 -1
  111. package/plugins/files/dist/tools/index.d.ts.map +1 -1
  112. package/plugins/files/package.json +1 -1
  113. package/plugins/microsandbox/dist/admin/browser-routes.d.ts +1 -1
  114. package/plugins/microsandbox/dist/admin/browser-routes.d.ts.map +1 -1
  115. package/plugins/microsandbox/dist/admin/browser-routes.js +1 -1
  116. package/plugins/microsandbox/dist/admin/browser-routes.js.map +1 -1
  117. package/plugins/microsandbox/dist/admin/routes.d.ts +1 -1
  118. package/plugins/microsandbox/dist/admin/routes.d.ts.map +1 -1
  119. package/plugins/microsandbox/dist/client.d.ts +2 -2
  120. package/plugins/microsandbox/dist/client.d.ts.map +1 -1
  121. package/plugins/microsandbox/dist/client.js +1 -1
  122. package/plugins/microsandbox/dist/client.js.map +1 -1
  123. package/plugins/microsandbox/dist/runner/browser.d.ts +1 -1
  124. package/plugins/microsandbox/dist/runner/browser.d.ts.map +1 -1
  125. package/plugins/microsandbox/dist/runner/index.d.ts +1 -1
  126. package/plugins/microsandbox/dist/runner/index.d.ts.map +1 -1
  127. package/plugins/microsandbox/dist/runner/microsandbox.d.ts +1 -1
  128. package/plugins/microsandbox/dist/runner/microsandbox.d.ts.map +1 -1
  129. package/plugins/microsandbox/dist/runner/nullable.d.ts +1 -1
  130. package/plugins/microsandbox/dist/runner/nullable.d.ts.map +1 -1
  131. package/plugins/microsandbox/dist/runner/pool.d.ts +1 -1
  132. package/plugins/microsandbox/dist/runner/pool.d.ts.map +1 -1
  133. package/plugins/microsandbox/dist/server.d.ts +1 -1
  134. package/plugins/microsandbox/dist/server.d.ts.map +1 -1
  135. package/plugins/microsandbox/dist/tools/browser.d.ts +2 -2
  136. package/plugins/microsandbox/dist/tools/browser.d.ts.map +1 -1
  137. package/plugins/microsandbox/dist/tools/browser.js +1 -1
  138. package/plugins/microsandbox/dist/tools/browser.js.map +1 -1
  139. package/plugins/microsandbox/dist/tools/build.d.ts +1 -1
  140. package/plugins/microsandbox/dist/tools/build.d.ts.map +1 -1
  141. package/plugins/microsandbox/dist/tools/build.js +1 -1
  142. package/plugins/microsandbox/dist/tools/build.js.map +1 -1
  143. package/plugins/microsandbox/dist/tools/index.d.ts +1 -1
  144. package/plugins/microsandbox/dist/tools/index.d.ts.map +1 -1
  145. package/plugins/microsandbox/package.json +1 -1
  146. package/plugins/web-search/dist/server.d.ts +1 -1
  147. package/plugins/web-search/dist/server.d.ts.map +1 -1
  148. package/plugins/web-search/dist/tools/web-search.d.ts +1 -1
  149. package/plugins/web-search/dist/tools/web-search.d.ts.map +1 -1
  150. package/plugins/web-search/node_modules/@esbuild/linux-x64/README.md +3 -0
  151. package/plugins/web-search/node_modules/@esbuild/{darwin-arm64 → linux-x64}/package.json +4 -4
  152. package/plugins/web-search/package.json +1 -1
  153. package/plugins/workboard/dist/client.d.ts +2 -2
  154. package/plugins/workboard/dist/client.d.ts.map +1 -1
  155. package/plugins/workboard/dist/client.js +1 -1
  156. package/plugins/workboard/dist/client.js.map +1 -1
  157. package/plugins/workboard/dist/db/schema.d.ts +1 -1
  158. package/plugins/workboard/dist/db/schema.d.ts.map +1 -1
  159. package/plugins/workboard/dist/db/session-history.d.ts +1 -1
  160. package/plugins/workboard/dist/db/session-history.d.ts.map +1 -1
  161. package/plugins/workboard/dist/db/tasks.d.ts +1 -1
  162. package/plugins/workboard/dist/db/tasks.d.ts.map +1 -1
  163. package/plugins/workboard/dist/effective-skills.d.ts +1 -1
  164. package/plugins/workboard/dist/effective-skills.d.ts.map +1 -1
  165. package/plugins/workboard/dist/routes/handlers.d.ts +1 -1
  166. package/plugins/workboard/dist/routes/handlers.d.ts.map +1 -1
  167. package/plugins/workboard/dist/routes/handlers.js.map +1 -1
  168. package/plugins/workboard/dist/server.d.ts +1 -1
  169. package/plugins/workboard/dist/server.d.ts.map +1 -1
  170. package/plugins/workboard/dist/tools/index.d.ts +1 -1
  171. package/plugins/workboard/dist/tools/index.d.ts.map +1 -1
  172. package/plugins/workboard/dist/worker/pool.d.ts +1 -1
  173. package/plugins/workboard/dist/worker/pool.d.ts.map +1 -1
  174. package/plugins/workboard/package.json +1 -1
  175. package/packages/plugin-sdk/dist/mcp-client.d.ts +0 -74
  176. package/packages/plugin-sdk/dist/mcp-client.d.ts.map +0 -1
  177. package/packages/plugin-sdk/dist/mcp-client.js +0 -226
  178. package/packages/plugin-sdk/dist/mcp-client.js.map +0 -1
  179. package/packages/server/builtinConfig/plugins/microsandbox/skills/microsandbox-main-orchestration.md +0 -75
  180. package/packages/server/dist/core/migrations/003-worker-agents.d.ts +0 -4
  181. package/packages/server/dist/core/migrations/003-worker-agents.d.ts.map +0 -1
  182. package/packages/server/dist/core/migrations/003-worker-agents.js +0 -65
  183. package/packages/server/dist/core/migrations/003-worker-agents.js.map +0 -1
  184. package/packages/server/dist/core/worker-agents.d.ts +0 -77
  185. package/packages/server/dist/core/worker-agents.d.ts.map +0 -1
  186. package/packages/server/dist/core/worker-agents.js +0 -191
  187. package/packages/server/dist/core/worker-agents.js.map +0 -1
  188. package/packages/server/dist/setup/checks/plugins.d.ts +0 -9
  189. package/packages/server/dist/setup/checks/plugins.d.ts.map +0 -1
  190. package/packages/server/dist/setup/checks/plugins.js +0 -194
  191. package/packages/server/dist/setup/checks/plugins.js.map +0 -1
  192. package/packages/server/dist/tools/edit-file.d.ts +0 -13
  193. package/packages/server/dist/tools/edit-file.d.ts.map +0 -1
  194. package/packages/server/dist/tools/edit-file.js +0 -90
  195. package/packages/server/dist/tools/edit-file.js.map +0 -1
  196. package/packages/server/dist/tools/glob.d.ts +0 -12
  197. package/packages/server/dist/tools/glob.d.ts.map +0 -1
  198. package/packages/server/dist/tools/glob.js +0 -82
  199. package/packages/server/dist/tools/glob.js.map +0 -1
  200. package/packages/server/dist/tools/list-dir.d.ts +0 -24
  201. package/packages/server/dist/tools/list-dir.d.ts.map +0 -1
  202. package/packages/server/dist/tools/list-dir.js +0 -99
  203. package/packages/server/dist/tools/list-dir.js.map +0 -1
  204. package/packages/server/dist/tools/path-helper.d.ts +0 -15
  205. package/packages/server/dist/tools/path-helper.d.ts.map +0 -1
  206. package/packages/server/dist/tools/path-helper.js +0 -72
  207. package/packages/server/dist/tools/path-helper.js.map +0 -1
  208. package/packages/server/dist/tools/read-file.d.ts +0 -17
  209. package/packages/server/dist/tools/read-file.d.ts.map +0 -1
  210. package/packages/server/dist/tools/read-file.js +0 -94
  211. package/packages/server/dist/tools/read-file.js.map +0 -1
  212. package/packages/server/dist/tools/sandbox.d.ts +0 -57
  213. package/packages/server/dist/tools/sandbox.d.ts.map +0 -1
  214. package/packages/server/dist/tools/sandbox.js +0 -291
  215. package/packages/server/dist/tools/sandbox.js.map +0 -1
  216. package/packages/server/dist/tools/write-file.d.ts +0 -12
  217. package/packages/server/dist/tools/write-file.d.ts.map +0 -1
  218. package/packages/server/dist/tools/write-file.js +0 -67
  219. package/packages/server/dist/tools/write-file.js.map +0 -1
  220. package/packages/server/dist/worker-agents-routes.d.ts +0 -11
  221. package/packages/server/dist/worker-agents-routes.d.ts.map +0 -1
  222. package/packages/server/dist/worker-agents-routes.js +0 -253
  223. package/packages/server/dist/worker-agents-routes.js.map +0 -1
  224. package/plugins/microsandbox/dist/admin.d.ts +0 -5
  225. package/plugins/microsandbox/dist/admin.d.ts.map +0 -1
  226. package/plugins/microsandbox/dist/admin.js +0 -256
  227. package/plugins/microsandbox/dist/admin.js.map +0 -1
  228. package/plugins/microsandbox/dist/tools/mcp-client.d.ts +0 -63
  229. package/plugins/microsandbox/dist/tools/mcp-client.d.ts.map +0 -1
  230. package/plugins/microsandbox/dist/tools/mcp-client.js +0 -226
  231. package/plugins/microsandbox/dist/tools/mcp-client.js.map +0 -1
  232. package/plugins/web-search/node_modules/@esbuild/darwin-arm64/README.md +0 -3
  233. package/plugins/workboard/dist/db/agents.d.ts +0 -100
  234. package/plugins/workboard/dist/db/agents.d.ts.map +0 -1
  235. package/plugins/workboard/dist/db/agents.js +0 -280
  236. package/plugins/workboard/dist/db/agents.js.map +0 -1
  237. package/plugins/workboard/dist/db/worker-agents.d.ts +0 -16
  238. package/plugins/workboard/dist/db/worker-agents.d.ts.map +0 -1
  239. package/plugins/workboard/dist/db/worker-agents.js +0 -62
  240. package/plugins/workboard/dist/db/worker-agents.js.map +0 -1
  241. package/plugins/workboard/dist/migrate-worker-agents.d.ts +0 -11
  242. package/plugins/workboard/dist/migrate-worker-agents.d.ts.map +0 -1
  243. package/plugins/workboard/dist/migrate-worker-agents.js +0 -89
  244. package/plugins/workboard/dist/migrate-worker-agents.js.map +0 -1
package/README.md CHANGED
@@ -119,17 +119,37 @@ Use it whenever something doesn't feel right — it's read-only.
119
119
 
120
120
  ### Installing globally
121
121
 
122
- When 0.x stabilises this will be on npm:
122
+ Published to npm under `@tianshu-ai/tianshu`:
123
123
 
124
124
  ```bash
125
125
  npm install -g @tianshu-ai/tianshu
126
- tianshu setup --wizard
127
- tianshu doctor
128
- tianshu start
126
+ tianshu setup --wizard # interactive: pick provider, key, ports
127
+ tianshu doctor # verify config + reachability
128
+ tianshu start # bootstrap the launchd service (macOS)
129
129
  ```
130
130
 
131
- For now, run from a checkout. Commands are the same, you just invoke
132
- them via `npm run` or `node bin/tianshu.mjs`.
131
+ Day-2 control:
132
+
133
+ ```bash
134
+ tianshu status # what's loaded? port? health?
135
+ tianshu logs --follow # tail server stdout + stderr
136
+ tianshu restart # bounce the dev server
137
+ tianshu stop # bootout from launchd
138
+ tianshu tenant list # tenants + users + open-in-browser URLs
139
+ ```
140
+
141
+ Updating:
142
+
143
+ ```bash
144
+ tianshu update --check # peek at what `latest` is on npm
145
+ tianshu update # npm install -g the latest, prints next steps
146
+ tianshu update --tag next # install pre-release channel (if available)
147
+ ```
148
+
149
+ Developing from a checkout: clone the repo, `npm install`, then
150
+ `npm run dev` to get the live server + UI. `bin/tianshu.mjs` works
151
+ the same from the checkout, but `tianshu update` will detect the
152
+ checkout and refuse — use `git pull` instead.
133
153
 
134
154
  ### Useful flags
135
155
 
@@ -241,7 +261,7 @@ giants.
241
261
 
242
262
  ### Next (0.3.x)
243
263
 
244
- - [ ] `npm install -g @tianshu-ai/tianshu` published to npm
264
+ - [x] `npm install -g @tianshu-ai/tianshu` published to npm
245
265
  - [ ] `tianshu start` single-port server (web + API together for prod)
246
266
  - [ ] Docker image with sandbox layer baked in
247
267
  - [ ] Hosted demo at `demo.tianshu-ai.com`
@@ -0,0 +1,96 @@
1
+ export interface AgentLoopRunnerRequest {
2
+ /** Owner of the worker session. Tasks are owner-scoped, so this
3
+ * must match the task's owner_user_id when called by a worker
4
+ * pool. */
5
+ userId: string;
6
+ /** Initial user prompt. The headline + a Description block work
7
+ * fine; any well-formed prompt does. */
8
+ initialUserMessage: string;
9
+ /** System-prompt override; falls through to the host default. */
10
+ systemPrompt?: string;
11
+ /** Model id from tenant config; falls through to default. */
12
+ modelId?: string;
13
+ /** Allow-list of tool names. `null` / undefined = all available. */
14
+ toolsAllow?: string[] | null;
15
+ /** Deny-list applied AFTER `toolsAllow`. Used by worker pools to
16
+ * scrub tools that are unsafe in worker context (e.g. workboard's
17
+ * task_create) regardless of what the agent's allow-list says. */
18
+ toolsDeny?: string[] | null;
19
+ /** Allow-list of skill names; same semantics. */
20
+ skillsAllow?: string[] | null;
21
+ /** Friendly title for the worker session row. */
22
+ sessionTitle?: string | null;
23
+ /** Worker role. Use the kind id (e.g. \"llm\") when called from a
24
+ * worker pool. */
25
+ workerRole?: string | null;
26
+ /** Worker filesystem slug — the directory name under
27
+ * `_tenant/config/workers/<slug>/`. Drives the
28
+ * `tenant_config_write` boundary so a worker can author skills
29
+ * inside its own bundle. When omitted, the tools fall back to
30
+ * scoping by `workerRole`. */
31
+ workerSlug?: string | null;
32
+ /** Task id when this run is driven by a workboard task. Plumbed
33
+ * through to `AgentToolContext.taskId` so per-task tools (most
34
+ * importantly the microsandbox `exec` route) can scope their
35
+ * resources to a single task lifecycle: the task pool boots one
36
+ * sandbox per `taskId` and stops it once the task terminates.
37
+ * Absent for chat sessions and ad-hoc agent loops. */
38
+ taskId?: string | null;
39
+ /** Parent session id (the user's main session that requested
40
+ * the worker). Lets the UI render worker sessions as children. */
41
+ parentSessionId?: string | null;
42
+ /** Three layered timeouts. 0 disables the layer. */
43
+ timeouts?: {
44
+ firstResponseMs?: number;
45
+ idleMs?: number;
46
+ maxRunMs?: number;
47
+ };
48
+ /** External abort signal. */
49
+ signal?: AbortSignal;
50
+ /**
51
+ * Fires once, immediately after the worker session row has been
52
+ * inserted into the host DB and before the first LLM call.
53
+ *
54
+ * Plugins use this to link a long-running task row to its
55
+ * session id ASAP — without it, the workboard plugin would have
56
+ * to wait until the run terminated to write back
57
+ * `tasks.session_id`, which means the kanban Execution tab
58
+ * couldn't tail an in-progress conversation.
59
+ *
60
+ * Errors thrown by the callback are caught + logged and do not
61
+ * abort the run.
62
+ */
63
+ onSessionStart?: (sessionId: string) => void;
64
+ /**
65
+ * Resume a previous worker session instead of creating a fresh
66
+ * one. The host opens the existing session row and the LLM sees
67
+ * its prior transcript as context.
68
+ *
69
+ * Workboard uses this to retry a stalled task without losing the
70
+ * transcript that explains *why* it stalled — the new run
71
+ * picks up where the old one left off and (typically) just
72
+ * needs to call task_complete to finish.
73
+ *
74
+ * If the id doesn't exist, the host falls back to creating a new
75
+ * session and logs a warning rather than throwing.
76
+ */
77
+ resumeSessionId?: string;
78
+ /**
79
+ * Prompt to send when `resumeSessionId` is set. Defaults to a
80
+ * generic nudge reminding the agent it didn't call task_complete
81
+ * last time. Ignored when starting a fresh session.
82
+ */
83
+ resumePrompt?: string;
84
+ }
85
+ export interface AgentLoopRunnerResult {
86
+ status: "done" | "stalled" | "aborted" | "error";
87
+ summary: string;
88
+ files: string[];
89
+ sessionId: string;
90
+ turns: number;
91
+ reason: "task_complete" | "no_completion" | "first_response_timeout" | "idle_timeout" | "max_run_timeout" | "aborted" | "stream_error" | "exception";
92
+ }
93
+ export interface AgentLoopRunner {
94
+ run(req: AgentLoopRunnerRequest): Promise<AgentLoopRunnerResult>;
95
+ }
96
+ //# sourceMappingURL=agent-loop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-loop.d.ts","sourceRoot":"","sources":["../src/agent-loop.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,sBAAsB;IACrC;;gBAEY;IACZ,MAAM,EAAE,MAAM,CAAC;IACf;6CACyC;IACzC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC7B;;uEAEmE;IACnE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC5B,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC9B,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B;uBACmB;IACnB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B;;;;mCAI+B;IAC/B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B;;;;;2DAKuD;IACvD,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB;uEACmE;IACnE,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,oDAAoD;IACpD,QAAQ,CAAC,EAAE;QACT,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,6BAA6B;IAC7B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;;;;;;;;;OAYG;IACH,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C;;;;;;;;;;;;OAYG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EACF,eAAe,GACf,eAAe,GACf,wBAAwB,GACxB,cAAc,GACd,iBAAiB,GACjB,SAAS,GACT,cAAc,GACd,WAAW,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,GAAG,EAAE,sBAAsB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;CAClE"}
@@ -0,0 +1,11 @@
1
+ // Capability-side type for `host.agentLoop`.
2
+ //
3
+ // The host registers a runner satisfying this interface; plugins
4
+ // look it up via `ctx.capabilities.get<AgentLoopRunner>(\"host.agentLoop\")`.
5
+ //
6
+ // We deliberately re-declare the request/result shapes in the SDK
7
+ // instead of re-exporting from `@tianshu/server` so plugin builds
8
+ // don't have to depend on the server bundle. The host's actual
9
+ // implementation must remain shape-compatible with this contract.
10
+ export {};
11
+ //# sourceMappingURL=agent-loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-loop.js","sourceRoot":"","sources":["../src/agent-loop.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,EAAE;AACF,iEAAiE;AACjE,8EAA8E;AAC9E,EAAE;AACF,kEAAkE;AAClE,kEAAkE;AAClE,+DAA+D;AAC/D,kEAAkE"}
@@ -0,0 +1,48 @@
1
+ export interface CapabilitySpec {
2
+ readonly exclusive: boolean;
3
+ readonly description: string;
4
+ }
5
+ export declare const KNOWN_CAPABILITIES: {
6
+ readonly "sandbox.shell": {
7
+ readonly exclusive: true;
8
+ readonly description: "Run shell commands and read/write files in an isolated per-tenant workspace.";
9
+ };
10
+ readonly "sandbox.taskPool": {
11
+ readonly exclusive: true;
12
+ readonly description: "Manage per-task sandbox lifecycle: acquire a dedicated sandbox at worker pickup time, release it (stop without removing) when the task terminates, and destroy it on task delete. Workboard binds task ids to agent sessions through this capability so per-task `exec` calls land in the right sandbox.";
13
+ };
14
+ readonly "browser.cdp": {
15
+ readonly exclusive: true;
16
+ readonly description: "Provide a headless chromium reachable via Chrome DevTools Protocol + Playwright MCP, with a noVNC viewport for the user.";
17
+ };
18
+ readonly "host.agentLoop": {
19
+ readonly exclusive: true;
20
+ readonly description: "Run a headless agent loop on behalf of a worker: spin up a kind='worker' session, call the LLM with the tenant's tool/skill set, persist messages, enforce first-response/idle/max-run timeouts, and return a structured terminal result. Provided by the host (not by a plugin); workboard's LLM worker requires it.";
21
+ };
22
+ readonly "host.sessionInbox": {
23
+ readonly exclusive: true;
24
+ readonly description: "Deliver a system-level message to a chat session's inbox. If the session has an active turn running, the message is queued via harness.followUp(); otherwise it persists in the DB and is flushed as a system note the next time the session takes a user turn. Provided by the host; workboard uses this to notify the parent agent when a delegated task finishes.";
25
+ };
26
+ readonly "host.toolCatalog": {
27
+ readonly exclusive: true;
28
+ readonly description: "Read the tool catalog the host can offer to the current tenant: every tool name registered by the host plus every active plugin's contributions. Plugins use this to seed allow-list defaults (e.g. workboard's Default LLM agent grants every tool by default rather than 'unlimited' meaning silent fallthrough).";
29
+ };
30
+ readonly "host.skillCatalog": {
31
+ readonly exclusive: true;
32
+ readonly description: "Read the skill catalog the host can offer to the current tenant: every skill name registered host-side plus every active plugin's contributions. Same role as host.toolCatalog but for the skill allow-list field.";
33
+ };
34
+ readonly "host.modelCatalog": {
35
+ readonly exclusive: true;
36
+ readonly description: "Read the LLM model catalog the host can offer to the current tenant: every provider/model registered in the host's `models.providers` config, plus the default modelId. Used by the main agent and worker-creator to pick a model for new worker bundles instead of hard-coding ids.";
37
+ };
38
+ readonly "host.lsp": {
39
+ readonly exclusive: true;
40
+ readonly description: "Diagnose a file via the host's LSP manager after a write/edit. Plugins (notably `files`) call `diagnoseAfterEdit({ filePath, contents })` and append the formatted diagnostic block to their tool result so the model sees compile errors in the same turn that introduced them. Tenant-scoped: the manager refuses files outside the calling tenant's workspace. See ADR-0005.";
41
+ };
42
+ };
43
+ export type CapabilityName = keyof typeof KNOWN_CAPABILITIES;
44
+ /** True iff the given string is a registered capability name. */
45
+ export declare function isCapabilityName(s: string): s is CapabilityName;
46
+ /** Returns the capability spec or undefined if unknown. */
47
+ export declare function capabilitySpec(name: string): CapabilitySpec | undefined;
48
+ //# sourceMappingURL=capabilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8CoB,CAAC;AAEpD,MAAM,MAAM,cAAc,GAAG,MAAM,OAAO,kBAAkB,CAAC;AAE7D,iEAAiE;AACjE,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,IAAI,cAAc,CAE/D;AAED,2DAA2D;AAC3D,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAEvE"}
@@ -0,0 +1,61 @@
1
+ // Capability vocabulary (ADR-0004 §3).
2
+ //
3
+ // A capability is a maintainer-defined tag that names a concrete
4
+ // platform-level capability a plugin can provide or require. The
5
+ // vocabulary is closed: extending it is a maintainer PR to this file,
6
+ // which forces explicit thought about new platform surface area and
7
+ // keeps capability strings from drifting between plugins.
8
+ //
9
+ // Every entry has:
10
+ // - exclusive: when true, only one plugin in a tenant may provide
11
+ // this capability. The registry rejects a second provider at
12
+ // activation time (ADR-0004 §7).
13
+ // - description: human-readable surface description, shown in the
14
+ // Plugin Manager UI (Catalog tab) and in error messages.
15
+ export const KNOWN_CAPABILITIES = {
16
+ "sandbox.shell": {
17
+ exclusive: true,
18
+ description: "Run shell commands and read/write files in an isolated per-tenant workspace.",
19
+ },
20
+ "sandbox.taskPool": {
21
+ exclusive: true,
22
+ description: "Manage per-task sandbox lifecycle: acquire a dedicated sandbox at worker pickup time, release it (stop without removing) when the task terminates, and destroy it on task delete. Workboard binds task ids to agent sessions through this capability so per-task `exec` calls land in the right sandbox.",
23
+ },
24
+ "browser.cdp": {
25
+ exclusive: true,
26
+ description: "Provide a headless chromium reachable via Chrome DevTools Protocol + Playwright MCP, with a noVNC viewport for the user.",
27
+ },
28
+ "host.agentLoop": {
29
+ exclusive: true,
30
+ description: "Run a headless agent loop on behalf of a worker: spin up a kind='worker' session, call the LLM with the tenant's tool/skill set, persist messages, enforce first-response/idle/max-run timeouts, and return a structured terminal result. Provided by the host (not by a plugin); workboard's LLM worker requires it.",
31
+ },
32
+ "host.sessionInbox": {
33
+ exclusive: true,
34
+ description: "Deliver a system-level message to a chat session's inbox. If the session has an active turn running, the message is queued via harness.followUp(); otherwise it persists in the DB and is flushed as a system note the next time the session takes a user turn. Provided by the host; workboard uses this to notify the parent agent when a delegated task finishes.",
35
+ },
36
+ "host.toolCatalog": {
37
+ exclusive: true,
38
+ description: "Read the tool catalog the host can offer to the current tenant: every tool name registered by the host plus every active plugin's contributions. Plugins use this to seed allow-list defaults (e.g. workboard's Default LLM agent grants every tool by default rather than 'unlimited' meaning silent fallthrough).",
39
+ },
40
+ "host.skillCatalog": {
41
+ exclusive: true,
42
+ description: "Read the skill catalog the host can offer to the current tenant: every skill name registered host-side plus every active plugin's contributions. Same role as host.toolCatalog but for the skill allow-list field.",
43
+ },
44
+ "host.modelCatalog": {
45
+ exclusive: true,
46
+ description: "Read the LLM model catalog the host can offer to the current tenant: every provider/model registered in the host's `models.providers` config, plus the default modelId. Used by the main agent and worker-creator to pick a model for new worker bundles instead of hard-coding ids.",
47
+ },
48
+ "host.lsp": {
49
+ exclusive: true,
50
+ description: "Diagnose a file via the host's LSP manager after a write/edit. Plugins (notably `files`) call `diagnoseAfterEdit({ filePath, contents })` and append the formatted diagnostic block to their tool result so the model sees compile errors in the same turn that introduced them. Tenant-scoped: the manager refuses files outside the calling tenant's workspace. See ADR-0005.",
51
+ },
52
+ };
53
+ /** True iff the given string is a registered capability name. */
54
+ export function isCapabilityName(s) {
55
+ return Object.prototype.hasOwnProperty.call(KNOWN_CAPABILITIES, s);
56
+ }
57
+ /** Returns the capability spec or undefined if unknown. */
58
+ export function capabilitySpec(name) {
59
+ return isCapabilityName(name) ? KNOWN_CAPABILITIES[name] : undefined;
60
+ }
61
+ //# sourceMappingURL=capabilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,EAAE;AACF,iEAAiE;AACjE,iEAAiE;AACjE,sEAAsE;AACtE,oEAAoE;AACpE,0DAA0D;AAC1D,EAAE;AACF,mBAAmB;AACnB,kEAAkE;AAClE,+DAA+D;AAC/D,mCAAmC;AACnC,kEAAkE;AAClE,2DAA2D;AAO3D,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,eAAe,EAAE;QACf,SAAS,EAAE,IAAI;QACf,WAAW,EACT,8EAA8E;KACjF;IACD,kBAAkB,EAAE;QAClB,SAAS,EAAE,IAAI;QACf,WAAW,EACT,0SAA0S;KAC7S;IACD,aAAa,EAAE;QACb,SAAS,EAAE,IAAI;QACf,WAAW,EACT,0HAA0H;KAC7H;IACD,gBAAgB,EAAE;QAChB,SAAS,EAAE,IAAI;QACf,WAAW,EACT,uTAAuT;KAC1T;IACD,mBAAmB,EAAE;QACnB,SAAS,EAAE,IAAI;QACf,WAAW,EACT,sWAAsW;KACzW;IACD,kBAAkB,EAAE;QAClB,SAAS,EAAE,IAAI;QACf,WAAW,EACT,qTAAqT;KACxT;IACD,mBAAmB,EAAE;QACnB,SAAS,EAAE,IAAI;QACf,WAAW,EACT,oNAAoN;KACvN;IACD,mBAAmB,EAAE;QACnB,SAAS,EAAE,IAAI;QACf,WAAW,EACT,sRAAsR;KACzR;IACD,UAAU,EAAE;QACV,SAAS,EAAE,IAAI;QACf,WAAW,EACT,iXAAiX;KACpX;CACgD,CAAC;AAIpD,iEAAiE;AACjE,MAAM,UAAU,gBAAgB,CAAC,CAAS;IACxC,OAAO,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;AACrE,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACvE,CAAC"}
@@ -0,0 +1,60 @@
1
+ export interface ToolCatalogEntry {
2
+ name: string;
3
+ /** Single-line description from the tool's schema. */
4
+ description: string;
5
+ /** Source plugin id, or "host" for tools registered by the
6
+ * server itself. Useful for UI grouping. */
7
+ pluginId: string;
8
+ }
9
+ export interface ToolCatalogCapability {
10
+ /** Read the full tool catalog for the current tenant. Synchronous;
11
+ * the host already has this loaded in memory. */
12
+ list(): ToolCatalogEntry[];
13
+ }
14
+ export interface SkillCatalogEntry {
15
+ name: string;
16
+ description: string;
17
+ pluginId: string;
18
+ /** Frontmatter `scope:` field, if any. "main" hides the skill
19
+ * from worker runs; "worker" hides it from the main chat
20
+ * agent. Undefined means visible to both — the legacy
21
+ * default. Plugins / UIs that surface skills per-agent
22
+ * honour this filter themselves; the host doesn't strip
23
+ * scoped skills from the catalog. */
24
+ scope?: "main" | "worker";
25
+ }
26
+ export interface SkillCatalogCapability {
27
+ list(): SkillCatalogEntry[];
28
+ }
29
+ export interface ModelCatalogEntry {
30
+ /** Provider-prefixed id passed to `modelId` fields, e.g.
31
+ * `sap-proxy/claude-sonnet-4-6`, `anthropic/claude-opus-4-7`,
32
+ * `sap-perplexity/sonar-pro`. This is the value an agent.json
33
+ * or task overrides should set. */
34
+ id: string;
35
+ /** Display name from the host config (`models[].name`). */
36
+ name: string;
37
+ /** Provider id (`anthropic`, `sap-proxy`, etc.). Already in the
38
+ * prefix of `id`; surfaced separately for UI grouping. */
39
+ provider: string;
40
+ /** Optional grouping label (`Cloud`, `Local`, ...). */
41
+ group?: string;
42
+ /** Context window in tokens, from host config. */
43
+ contextWindow: number;
44
+ /** True iff the model emits chain-of-thought / reasoning
45
+ * tokens we shouldn't show to the user verbatim. */
46
+ reasoning: boolean;
47
+ }
48
+ export interface ModelCatalogCapability {
49
+ /** Read the model catalog visible to the current tenant.
50
+ * Driven by `tenant.config.models.providers` resolved via
51
+ * `listModels()` in @tianshu/server. The default model id
52
+ * (used when `agent.json.modelId === null`) is exposed
53
+ * separately so worker-creator and other tools don't have
54
+ * to hard-code which entry is the fallback. */
55
+ list(): {
56
+ models: ModelCatalogEntry[];
57
+ defaultModelId: string | null;
58
+ };
59
+ }
60
+ //# sourceMappingURL=catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,WAAW,EAAE,MAAM,CAAC;IACpB;iDAC6C;IAC7C,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC;sDACkD;IAClD,IAAI,IAAI,gBAAgB,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;0CAKsC;IACtC,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;CAC3B;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,IAAI,iBAAiB,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC;;;wCAGoC;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb;+DAC2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,aAAa,EAAE,MAAM,CAAC;IACtB;yDACqD;IACrD,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC;;;;;oDAKgD;IAChD,IAAI,IAAI;QAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;QAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;CACxE"}
@@ -0,0 +1,11 @@
1
+ // Capability shapes for the host's tool / skill catalogs.
2
+ //
3
+ // Plugins use these to populate allow-list defaults for built-in
4
+ // agents (workboard's Default LLM picks up every tool / skill the
5
+ // host knows about, instead of relying on the magic "null = no
6
+ // restriction" sentinel that's invisible in the UI).
7
+ //
8
+ // Both registered as exclusive host capabilities; see
9
+ // capabilities.ts.
10
+ export {};
11
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,EAAE;AACF,iEAAiE;AACjE,kEAAkE;AAClE,+DAA+D;AAC/D,qDAAqD;AACrD,EAAE;AACF,sDAAsD;AACtD,mBAAmB"}
@@ -0,0 +1,171 @@
1
+ import type { ComponentType } from "react";
2
+ export interface PluginRuntimeInfo {
3
+ id: string;
4
+ version: string;
5
+ displayName: string;
6
+ }
7
+ export interface PanelProps {
8
+ tenantId: string;
9
+ userId: string;
10
+ plugin: PluginRuntimeInfo;
11
+ }
12
+ export interface SidebarSectionProps extends PanelProps {
13
+ isCollapsed: boolean;
14
+ onToggleCollapse: () => void;
15
+ }
16
+ /**
17
+ * Props handed to a plugin's admin-page component
18
+ * (manifest.contributes.adminPages[].component). The host renders
19
+ * these inside the chat shell's `/admin` shell, full-width.
20
+ */
21
+ export interface AdminPageProps extends PanelProps {
22
+ /** The page id from the manifest contribution
23
+ * (e.g. "main", "settings"). */
24
+ pageId: string;
25
+ }
26
+ /**
27
+ * One file (or, in the future, any other inline payload) the user
28
+ * has staged in the composer. The chat shell renders these as chips
29
+ * above the textarea and disables Send until everything is `ready`.
30
+ *
31
+ * Plugins create attachments via `composer.addAttachment(...)` and
32
+ * track upload progress by calling `updateAttachment(id, patch)`.
33
+ */
34
+ export interface Attachment {
35
+ /** Stable id assigned by the host on `addAttachment`. */
36
+ id: string;
37
+ name: string;
38
+ size: number;
39
+ status: "uploading" | "ready" | "error";
40
+ /**
41
+ * Path relative to the user's home (e.g. `/uploads/data.csv`).
42
+ * Populated by the plugin once the file is on disk.
43
+ */
44
+ path?: string;
45
+ /**
46
+ * RFC 6838 mime type. The host forwards this on the wire so the
47
+ * server can decide whether to treat the attachment as a vision
48
+ * input or a plain workspace file. Plugins should pass
49
+ * `File.type` here when available; default to
50
+ * `"application/octet-stream"`.
51
+ */
52
+ mimeType?: string;
53
+ /** 0..1, optional progress for the chip. */
54
+ progress?: number;
55
+ /** Set when status === "error". */
56
+ error?: string;
57
+ /** Plugin-defined metadata (dimensions, hashes, anything). */
58
+ meta?: Record<string, unknown>;
59
+ }
60
+ export type DraftTransform = (
61
+ /** The text the user typed (already trimmed of trailing whitespace). */
62
+ text: string,
63
+ /** All attachments at the moment of send, all with status === "ready". */
64
+ attachments: Attachment[]) => string | Promise<string>;
65
+ /**
66
+ * Composer API surface exposed to plugin client components.
67
+ *
68
+ * Implementation note: the host wires this into a React context. Use
69
+ * `useComposer()` from `@tianshu-ai/plugin-sdk/client` from inside a
70
+ * plugin component to get the live instance.
71
+ */
72
+ export interface ComposerApi {
73
+ /** Live attachments list. Mutations should go through the methods. */
74
+ attachments: Attachment[];
75
+ /** Append a new attachment, host assigns the id. */
76
+ addAttachment(a: Omit<Attachment, "id">): string;
77
+ /** Patch fields on an existing attachment. No-op if id unknown. */
78
+ updateAttachment(id: string, patch: Partial<Omit<Attachment, "id">>): void;
79
+ /** Remove an attachment from the staged list. */
80
+ removeAttachment(id: string): void;
81
+ /**
82
+ * Register a transform that runs (in order of registration) on the
83
+ * draft text right before it's sent to the server. Returns an
84
+ * unregister function. Idempotent when called repeatedly with the
85
+ * same fn.
86
+ */
87
+ registerDraftTransform(fn: DraftTransform): () => void;
88
+ }
89
+ export interface ComposerActionProps extends PanelProps {
90
+ composer: ComposerApi;
91
+ }
92
+ /**
93
+ * One attachment as it lands in a user message. Mirrors the wire
94
+ * shape; the host re-exports it here so plugin authors only depend
95
+ * on the SDK.
96
+ */
97
+ export interface AttachmentDescriptor {
98
+ /** User-home-relative path (always starts with "/"). */
99
+ path: string;
100
+ /** RFC 6838 mime type. */
101
+ mimeType: string;
102
+ /** Original filename for display. */
103
+ name?: string;
104
+ /** Byte size on disk, when known. */
105
+ size?: number;
106
+ }
107
+ export interface AttachmentRendererProps extends PanelProps {
108
+ attachment: AttachmentDescriptor;
109
+ /** "start" for assistant-side, "end" for user-side. The renderer
110
+ * doesn't need to align itself — the host wraps a flex
111
+ * container — but it can use this for asymmetrical decoration. */
112
+ align: "start" | "end";
113
+ /**
114
+ * Resolve a workspace path to an absolute URL the browser can
115
+ * fetch. The host owns this so renderer plugins don't hard-code
116
+ * `/api/p/files/raw` (which would couple them to the files
117
+ * plugin). Today the host implementation routes through the
118
+ * files plugin; tomorrow it might route through a CDN cache.
119
+ */
120
+ rawUrl: (path: string) => string;
121
+ }
122
+ export interface PluginClientExports {
123
+ components: Record<string, ComponentType<PanelProps | SidebarSectionProps | ComposerActionProps | AttachmentRendererProps | AdminPageProps>>;
124
+ }
125
+ /** Host-only: install the live `useComposer` accessor. The web bundle
126
+ * calls this once on bootstrap with a function that reads from its
127
+ * React context. */
128
+ export declare function __installUseComposer(fn: () => ComposerApi): void;
129
+ /** Host-only: clear the installed accessor. Used by tests so each
130
+ * test starts with a clean slate; production code should never
131
+ * call this. */
132
+ export declare function __resetUseComposerForTest(): void;
133
+ export declare function useComposer(): ComposerApi;
134
+ export interface OpenFileApi {
135
+ /** Open a file living inside the user workspace. `path` accepts
136
+ * the same shapes the file tools accept: a `workspace:///foo`
137
+ * URI, a leading-slash absolute path, or a bare relative path.
138
+ * Implementations may render an in-page modal, switch to the
139
+ * files panel, open a new tab — anything UX-appropriate. */
140
+ open(path: string): void;
141
+ }
142
+ /** Host or files-plugin only: register an OpenFileApi. The host
143
+ * installs a fallback at bootstrap; the Files plugin overrides
144
+ * it on mount with its dialog-based implementation. Last writer
145
+ * wins. */
146
+ export declare function __installOpenFileApi(api: OpenFileApi): void;
147
+ /** Test helper. */
148
+ export declare function __resetOpenFileApiForTest(): void;
149
+ /** Hook returning the live `open(path)` callable. Stable across
150
+ * re-renders — always reads from the slot, so a late
151
+ * __installOpenFileApi() takes effect on the next call without
152
+ * forcing a re-mount. Throws only if absolutely no implementation
153
+ * has ever been installed (which means the host bootstrap was
154
+ * skipped). */
155
+ import * as React from "react";
156
+ export interface PluginConfigFormProps {
157
+ /** Plugin id (matches manifest.id). Form pulls schema + values
158
+ * from the host's live plugin store on every render, so a
159
+ * config save in another tab updates this in place. */
160
+ pluginId: string;
161
+ /** Optional className applied to the root form container. */
162
+ className?: string;
163
+ }
164
+ export declare function __installPluginConfigForm(C: React.ComponentType<PluginConfigFormProps>): void;
165
+ export declare function __resetPluginConfigFormForTest(): void;
166
+ /** Renders the auto-generated config form for `pluginId`. If the
167
+ * plugin has no `configSchema` or no fields, renders nothing
168
+ * (so the calling component can drop it in unconditionally). */
169
+ export declare const PluginConfigForm: React.ComponentType<PluginConfigFormProps>;
170
+ export declare function useOpenFile(): OpenFileApi["open"];
171
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ // Client-side plugin authoring types. Imported as
2
+ // `@tianshu-ai/plugin-sdk/client`.
3
+ //
4
+ // The chat shell's PluginRegistry expects a plugin's client module to
5
+ // export a `components` map keyed by the strings used in the manifest's
6
+ // `contributes.{rightPanels|sidebarSections|composerActions}.component`.
7
+ function globalSlot() {
8
+ // `globalThis` is the same in node, browser, and worker runtimes.
9
+ return globalThis;
10
+ }
11
+ /** Host-only: install the live `useComposer` accessor. The web bundle
12
+ * calls this once on bootstrap with a function that reads from its
13
+ * React context. */
14
+ export function __installUseComposer(fn) {
15
+ globalSlot().__tianshuPluginSdkComposer__ = fn;
16
+ }
17
+ /** Host-only: clear the installed accessor. Used by tests so each
18
+ * test starts with a clean slate; production code should never
19
+ * call this. */
20
+ export function __resetUseComposerForTest() {
21
+ delete globalSlot().__tianshuPluginSdkComposer__;
22
+ }
23
+ export function useComposer() {
24
+ const fn = globalSlot().__tianshuPluginSdkComposer__;
25
+ if (!fn) {
26
+ throw new Error("useComposer() called without a host: plugin SDK has no live ComposerApi. " +
27
+ "If you are seeing this in a test, install one with __installUseComposer().");
28
+ }
29
+ return fn();
30
+ }
31
+ function openFileSlot() {
32
+ return globalThis;
33
+ }
34
+ /** Host or files-plugin only: register an OpenFileApi. The host
35
+ * installs a fallback at bootstrap; the Files plugin overrides
36
+ * it on mount with its dialog-based implementation. Last writer
37
+ * wins. */
38
+ export function __installOpenFileApi(api) {
39
+ openFileSlot().__tianshuPluginSdkOpenFile__ = api;
40
+ }
41
+ /** Test helper. */
42
+ export function __resetOpenFileApiForTest() {
43
+ delete openFileSlot().__tianshuPluginSdkOpenFile__;
44
+ }
45
+ /** Hook returning the live `open(path)` callable. Stable across
46
+ * re-renders — always reads from the slot, so a late
47
+ * __installOpenFileApi() takes effect on the next call without
48
+ * forcing a re-mount. Throws only if absolutely no implementation
49
+ * has ever been installed (which means the host bootstrap was
50
+ * skipped). */
51
+ // ─── PluginConfigForm — re-export of the host's auto-generated
52
+ // config form, exposed so a plugin's own admin page can fold it
53
+ // in alongside its richer UI (Sandbox status / build history /
54
+ // etc.) instead of getting a duplicated "Settings" sidebar entry.
55
+ //
56
+ // Same install-once + globalSlot trick. Host installs the
57
+ // component on bootstrap; plugin imports `PluginConfigForm` and
58
+ // renders <PluginConfigForm pluginId="microsandbox" /> wherever
59
+ // makes sense. The form looks up its own data from the live
60
+ // plugin store, so the plugin only needs to pass the id.
61
+ import * as React from "react";
62
+ function pluginConfigFormSlot() {
63
+ return globalThis;
64
+ }
65
+ export function __installPluginConfigForm(C) {
66
+ pluginConfigFormSlot().__tianshuPluginSdkPluginConfigForm__ = C;
67
+ }
68
+ export function __resetPluginConfigFormForTest() {
69
+ delete pluginConfigFormSlot().__tianshuPluginSdkPluginConfigForm__;
70
+ }
71
+ /** Renders the auto-generated config form for `pluginId`. If the
72
+ * plugin has no `configSchema` or no fields, renders nothing
73
+ * (so the calling component can drop it in unconditionally). */
74
+ export const PluginConfigForm = (props) => {
75
+ const C = pluginConfigFormSlot().__tianshuPluginSdkPluginConfigForm__;
76
+ if (!C)
77
+ return null;
78
+ return React.createElement(C, props);
79
+ };
80
+ export function useOpenFile() {
81
+ return (path) => {
82
+ const api = openFileSlot().__tianshuPluginSdkOpenFile__;
83
+ if (!api) {
84
+ // Last-resort UX so the click does *something* useful even
85
+ // before any registrar has installed: stick the path in the
86
+ // URL bar of a new tab. Never reachable in production where
87
+ // the host installs a fallback at bootstrap.
88
+ const cleaned = path.replace(/^workspace:\/\/+/, "/");
89
+ const url = `/api/p/files/raw?path=${encodeURIComponent(cleaned)}`;
90
+ window.open(url, "_blank", "noopener");
91
+ return;
92
+ }
93
+ api.open(path);
94
+ };
95
+ }
96
+ //# sourceMappingURL=client.js.map