@skillcdn/console 0.4.1 → 0.4.3

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 (299) hide show
  1. package/README.md +19 -2
  2. package/SKILLCDN.md +7 -5
  3. package/dist/api.d.ts +5 -4
  4. package/dist/api.d.ts.map +1 -1
  5. package/dist/api.js +5 -4
  6. package/dist/api.js.map +1 -1
  7. package/dist/cli/cli.d.ts.map +1 -1
  8. package/dist/cli/cli.js +569 -48
  9. package/dist/cli/cli.js.map +1 -1
  10. package/dist/cli/format.d.ts +34 -3
  11. package/dist/cli/format.d.ts.map +1 -1
  12. package/dist/cli/format.js +283 -7
  13. package/dist/cli/format.js.map +1 -1
  14. package/dist/cli/help.d.ts.map +1 -1
  15. package/dist/cli/help.js +44 -7
  16. package/dist/cli/help.js.map +1 -1
  17. package/dist/cli/plugin-check.d.ts +26 -0
  18. package/dist/cli/plugin-check.d.ts.map +1 -0
  19. package/dist/cli/plugin-check.js +396 -0
  20. package/dist/cli/plugin-check.js.map +1 -0
  21. package/dist/cli/plugin-cli.d.ts +20 -0
  22. package/dist/cli/plugin-cli.d.ts.map +1 -0
  23. package/dist/cli/plugin-cli.js +189 -0
  24. package/dist/cli/plugin-cli.js.map +1 -0
  25. package/dist/cli/plugin-init.d.ts +37 -0
  26. package/dist/cli/plugin-init.d.ts.map +1 -0
  27. package/dist/cli/plugin-init.js +206 -0
  28. package/dist/cli/plugin-init.js.map +1 -0
  29. package/dist/cli/plugin-main.d.ts +3 -0
  30. package/dist/cli/plugin-main.d.ts.map +1 -0
  31. package/dist/cli/plugin-main.js +28 -0
  32. package/dist/cli/plugin-main.js.map +1 -0
  33. package/dist/client.d.ts +100 -3
  34. package/dist/client.d.ts.map +1 -1
  35. package/dist/client.js +79 -7
  36. package/dist/client.js.map +1 -1
  37. package/dist/compat.d.ts +1 -1
  38. package/dist/compat.js +2 -2
  39. package/dist/components/board.d.ts +8 -0
  40. package/dist/components/board.d.ts.map +1 -1
  41. package/dist/components/board.js +59 -15
  42. package/dist/components/board.js.map +1 -1
  43. package/dist/components/comments.d.ts.map +1 -1
  44. package/dist/components/comments.js +1 -1
  45. package/dist/components/comments.js.map +1 -1
  46. package/dist/components/decision-form.d.ts +2 -1
  47. package/dist/components/decision-form.d.ts.map +1 -1
  48. package/dist/components/decision-form.js +36 -4
  49. package/dist/components/decision-form.js.map +1 -1
  50. package/dist/components/decision-list.d.ts +4 -0
  51. package/dist/components/decision-list.d.ts.map +1 -1
  52. package/dist/components/decision-list.js +29 -3
  53. package/dist/components/decision-list.js.map +1 -1
  54. package/dist/components/event-feed.d.ts +1 -1
  55. package/dist/components/event-feed.d.ts.map +1 -1
  56. package/dist/components/event-feed.js +33 -1
  57. package/dist/components/event-feed.js.map +1 -1
  58. package/dist/components/my-decisions.d.ts +2 -0
  59. package/dist/components/my-decisions.d.ts.map +1 -1
  60. package/dist/components/my-decisions.js +2 -2
  61. package/dist/components/my-decisions.js.map +1 -1
  62. package/dist/components/plugin-frame.d.ts +52 -0
  63. package/dist/components/plugin-frame.d.ts.map +1 -0
  64. package/dist/components/plugin-frame.js +314 -0
  65. package/dist/components/plugin-frame.js.map +1 -0
  66. package/dist/components/plugin-settings.d.ts +38 -0
  67. package/dist/components/plugin-settings.d.ts.map +1 -0
  68. package/dist/components/plugin-settings.js +348 -0
  69. package/dist/components/plugin-settings.js.map +1 -0
  70. package/dist/components/shell.d.ts +2 -0
  71. package/dist/components/shell.d.ts.map +1 -1
  72. package/dist/components/shell.js +26 -1
  73. package/dist/components/shell.js.map +1 -1
  74. package/dist/components/task-view.d.ts +2 -1
  75. package/dist/components/task-view.d.ts.map +1 -1
  76. package/dist/components/task-view.js.map +1 -1
  77. package/dist/components/workspace.d.ts +7 -1
  78. package/dist/components/workspace.d.ts.map +1 -1
  79. package/dist/components/workspace.js +1 -1
  80. package/dist/components/workspace.js.map +1 -1
  81. package/dist/console.css +330 -1
  82. package/dist/console.d.ts.map +1 -1
  83. package/dist/console.js +152 -41
  84. package/dist/console.js.map +1 -1
  85. package/dist/data.d.ts +9 -2
  86. package/dist/data.d.ts.map +1 -1
  87. package/dist/data.js +45 -9
  88. package/dist/data.js.map +1 -1
  89. package/dist/i18n/en.d.ts +155 -0
  90. package/dist/i18n/en.d.ts.map +1 -1
  91. package/dist/i18n/en.js +166 -0
  92. package/dist/i18n/en.js.map +1 -1
  93. package/dist/i18n/ko.d.ts.map +1 -1
  94. package/dist/i18n/ko.js +150 -0
  95. package/dist/i18n/ko.js.map +1 -1
  96. package/dist/index.d.ts +3 -1
  97. package/dist/index.d.ts.map +1 -1
  98. package/dist/index.js +3 -1
  99. package/dist/index.js.map +1 -1
  100. package/dist/limits.d.ts +2 -0
  101. package/dist/limits.d.ts.map +1 -1
  102. package/dist/limits.js +2 -0
  103. package/dist/limits.js.map +1 -1
  104. package/dist/plugin/args.d.ts +148 -0
  105. package/dist/plugin/args.d.ts.map +1 -0
  106. package/dist/plugin/args.js +369 -0
  107. package/dist/plugin/args.js.map +1 -0
  108. package/dist/plugin/bridge.d.ts +146 -0
  109. package/dist/plugin/bridge.d.ts.map +1 -0
  110. package/dist/plugin/bridge.js +125 -0
  111. package/dist/plugin/bridge.js.map +1 -0
  112. package/dist/plugin/capabilities.d.ts +20 -0
  113. package/dist/plugin/capabilities.d.ts.map +1 -0
  114. package/dist/plugin/capabilities.js +133 -0
  115. package/dist/plugin/capabilities.js.map +1 -0
  116. package/dist/plugin/context.d.ts +380 -0
  117. package/dist/plugin/context.d.ts.map +1 -0
  118. package/dist/plugin/context.js +2 -0
  119. package/dist/plugin/context.js.map +1 -0
  120. package/dist/plugin/define.d.ts +208 -0
  121. package/dist/plugin/define.d.ts.map +1 -0
  122. package/dist/plugin/define.js +482 -0
  123. package/dist/plugin/define.js.map +1 -0
  124. package/dist/plugin/definition-error.d.ts +11 -0
  125. package/dist/plugin/definition-error.d.ts.map +1 -0
  126. package/dist/plugin/definition-error.js +17 -0
  127. package/dist/plugin/definition-error.js.map +1 -0
  128. package/dist/plugin/limits.d.ts +67 -0
  129. package/dist/plugin/limits.d.ts.map +1 -0
  130. package/dist/plugin/limits.js +70 -0
  131. package/dist/plugin/limits.js.map +1 -0
  132. package/dist/plugin/load-worker.d.ts +7 -0
  133. package/dist/plugin/load-worker.d.ts.map +1 -0
  134. package/dist/plugin/load-worker.js +41 -0
  135. package/dist/plugin/load-worker.js.map +1 -0
  136. package/dist/plugin/load.d.ts +18 -0
  137. package/dist/plugin/load.d.ts.map +1 -0
  138. package/dist/plugin/load.js +62 -0
  139. package/dist/plugin/load.js.map +1 -0
  140. package/dist/plugin/manifest.d.ts +237 -0
  141. package/dist/plugin/manifest.d.ts.map +1 -0
  142. package/dist/plugin/manifest.js +411 -0
  143. package/dist/plugin/manifest.js.map +1 -0
  144. package/dist/plugin/refusals.d.ts +49 -0
  145. package/dist/plugin/refusals.d.ts.map +1 -0
  146. package/dist/plugin/refusals.js +79 -0
  147. package/dist/plugin/refusals.js.map +1 -0
  148. package/dist/plugin/rest-schemas.d.ts +556 -0
  149. package/dist/plugin/rest-schemas.d.ts.map +1 -0
  150. package/dist/plugin/rest-schemas.js +262 -0
  151. package/dist/plugin/rest-schemas.js.map +1 -0
  152. package/dist/plugin/sandbox.d.ts +23 -0
  153. package/dist/plugin/sandbox.d.ts.map +1 -0
  154. package/dist/plugin/sandbox.js +99 -0
  155. package/dist/plugin/sandbox.js.map +1 -0
  156. package/dist/plugin/testing.d.ts +45 -0
  157. package/dist/plugin/testing.d.ts.map +1 -0
  158. package/dist/plugin/testing.js +420 -0
  159. package/dist/plugin/testing.js.map +1 -0
  160. package/dist/plugin/web-react.d.ts +11 -0
  161. package/dist/plugin/web-react.d.ts.map +1 -0
  162. package/dist/plugin/web-react.js +34 -0
  163. package/dist/plugin/web-react.js.map +1 -0
  164. package/dist/plugin/web.d.ts +95 -0
  165. package/dist/plugin/web.d.ts.map +1 -0
  166. package/dist/plugin/web.js +245 -0
  167. package/dist/plugin/web.js.map +1 -0
  168. package/dist/plugin-nav.d.ts +29 -0
  169. package/dist/plugin-nav.d.ts.map +1 -0
  170. package/dist/plugin-nav.js +92 -0
  171. package/dist/plugin-nav.js.map +1 -0
  172. package/dist/plugin-testing.d.ts +2 -0
  173. package/dist/plugin-testing.d.ts.map +1 -0
  174. package/dist/plugin-testing.js +4 -0
  175. package/dist/plugin-testing.js.map +1 -0
  176. package/dist/plugin-web-react.d.ts +3 -0
  177. package/dist/plugin-web-react.d.ts.map +1 -0
  178. package/dist/plugin-web-react.js +3 -0
  179. package/dist/plugin-web-react.js.map +1 -0
  180. package/dist/plugin-web.d.ts +4 -0
  181. package/dist/plugin-web.d.ts.map +1 -0
  182. package/dist/plugin-web.js +5 -0
  183. package/dist/plugin-web.js.map +1 -0
  184. package/dist/plugin.d.ts +11 -0
  185. package/dist/plugin.d.ts.map +1 -0
  186. package/dist/plugin.js +15 -0
  187. package/dist/plugin.js.map +1 -0
  188. package/dist/router.d.ts +28 -0
  189. package/dist/router.d.ts.map +1 -1
  190. package/dist/router.js +47 -0
  191. package/dist/router.js.map +1 -1
  192. package/dist/routes.d.ts +4 -0
  193. package/dist/routes.d.ts.map +1 -1
  194. package/dist/routes.js +6 -0
  195. package/dist/routes.js.map +1 -1
  196. package/dist/schemas.d.ts +194 -9
  197. package/dist/schemas.d.ts.map +1 -1
  198. package/dist/schemas.js +98 -17
  199. package/dist/schemas.js.map +1 -1
  200. package/dist/tokens.d.ts +2 -0
  201. package/dist/tokens.d.ts.map +1 -0
  202. package/dist/tokens.js +101 -0
  203. package/dist/tokens.js.map +1 -0
  204. package/dist/vocabulary.d.ts +11 -1
  205. package/dist/vocabulary.d.ts.map +1 -1
  206. package/dist/vocabulary.js +24 -0
  207. package/dist/vocabulary.js.map +1 -1
  208. package/dist/web.d.ts.map +1 -1
  209. package/dist/web.js +2 -0
  210. package/dist/web.js.map +1 -1
  211. package/docs/specs/cli.md +12 -5
  212. package/docs/specs/plugins.md +488 -0
  213. package/docs/specs/rest.md +11 -9
  214. package/package.json +26 -8
  215. package/skills/building-a-console/SKILL.md +25 -26
  216. package/skills/building-a-console/references/configuring.md +40 -0
  217. package/skills/building-a-console/references/the-default-console.md +1 -1
  218. package/skills/building-a-console/references/the-look-from-a-website.md +5 -5
  219. package/skills/building-a-plugin/SKILL.md +137 -0
  220. package/skills/deploying-a-console/SKILL.md +24 -26
  221. package/skills/deploying-a-console/references/access.md +13 -9
  222. package/skills/deploying-a-console/references/resources.md +25 -10
  223. package/skills/deploying-a-console/references/running-it-again.md +15 -0
  224. package/skills/deploying-a-console/references/sizing.md +2 -0
  225. package/skills/planning-the-board/SKILL.md +96 -0
  226. package/skills/planning-the-board/references/a-task.md +36 -0
  227. package/skills/planning-the-board/references/setting-up.md +44 -0
  228. package/skills/working-the-board/SKILL.md +43 -34
  229. package/skills/working-the-board/references/the-pack.md +19 -0
  230. package/src/api.ts +12 -0
  231. package/src/cli/cli.ts +737 -55
  232. package/src/cli/format.ts +368 -10
  233. package/src/cli/help.ts +50 -6
  234. package/src/cli/plugin-check.ts +497 -0
  235. package/src/cli/plugin-cli.ts +237 -0
  236. package/src/cli/plugin-init.ts +257 -0
  237. package/src/cli/plugin-main.ts +30 -0
  238. package/src/client.ts +322 -9
  239. package/src/compat.ts +2 -2
  240. package/src/components/board.tsx +62 -14
  241. package/src/components/comments.tsx +1 -0
  242. package/src/components/decision-form.tsx +92 -11
  243. package/src/components/decision-list.tsx +71 -2
  244. package/src/components/event-feed.tsx +42 -1
  245. package/src/components/my-decisions.tsx +4 -1
  246. package/src/components/plugin-frame.tsx +437 -0
  247. package/src/components/plugin-settings.tsx +1111 -0
  248. package/src/components/shell.tsx +82 -14
  249. package/src/components/task-view.tsx +2 -1
  250. package/src/components/workspace.tsx +18 -0
  251. package/src/console.tsx +304 -31
  252. package/src/data.ts +59 -11
  253. package/src/i18n/en.ts +175 -0
  254. package/src/i18n/ko.ts +155 -0
  255. package/src/index.ts +12 -0
  256. package/src/limits.ts +2 -0
  257. package/src/plugin/args.ts +526 -0
  258. package/src/plugin/bridge.ts +314 -0
  259. package/src/plugin/capabilities.ts +150 -0
  260. package/src/plugin/context.ts +421 -0
  261. package/src/plugin/define.ts +792 -0
  262. package/src/plugin/definition-error.ts +19 -0
  263. package/src/plugin/limits.ts +70 -0
  264. package/src/plugin/load-worker.ts +50 -0
  265. package/src/plugin/load.ts +82 -0
  266. package/src/plugin/manifest.ts +561 -0
  267. package/src/plugin/refusals.ts +94 -0
  268. package/src/plugin/rest-schemas.ts +354 -0
  269. package/src/plugin/sandbox.ts +123 -0
  270. package/src/plugin/testing.ts +612 -0
  271. package/src/plugin/web-react.ts +45 -0
  272. package/src/plugin/web.ts +403 -0
  273. package/src/plugin-nav.ts +132 -0
  274. package/src/plugin-testing.ts +10 -0
  275. package/src/plugin-web-react.ts +4 -0
  276. package/src/plugin-web.ts +35 -0
  277. package/src/plugin.ts +126 -0
  278. package/src/router.ts +73 -0
  279. package/src/routes.ts +7 -0
  280. package/src/schemas.ts +115 -18
  281. package/src/styles/console.css +330 -1
  282. package/src/tokens.ts +101 -0
  283. package/src/vocabulary.ts +30 -0
  284. package/src/web.ts +2 -0
  285. package/template/plugin/.gitignore +2 -0
  286. package/template/plugin/README.md +26 -0
  287. package/template/plugin/SKILLCDN.md +13 -0
  288. package/template/plugin/build.mjs +40 -0
  289. package/template/plugin/console-plugin.json +50 -0
  290. package/template/plugin/package.json +27 -0
  291. package/template/plugin/skills/__key__/SKILL.md +23 -0
  292. package/template/plugin/src/check.test.ts +34 -0
  293. package/template/plugin/src/server/index.test.ts +41 -0
  294. package/template/plugin/src/server/index.ts +72 -0
  295. package/template/plugin/src/web/index.css +51 -0
  296. package/template/plugin/src/web/index.ts +115 -0
  297. package/template/plugin/tsconfig.json +17 -0
  298. package/skills/working-the-board/references/setting-up.md +0 -3
  299. /package/skills/{working-the-board → planning-the-board}/references/project-rules.md +0 -0
package/src/data.ts CHANGED
@@ -39,12 +39,14 @@ import {
39
39
  type RestPerson,
40
40
  type RestPersonPatch,
41
41
  type RestPersonWork,
42
+ type RestPlugin,
42
43
  type RestProject,
43
44
  type RestProjectInput,
44
45
  type RestProjectPatch,
45
46
  type RestProjectRules,
46
47
  type RestRules,
47
48
  type RestRulesInput,
49
+ type RestRulesPlugin,
48
50
  type RestRun,
49
51
  type RestSkills,
50
52
  type RestTask,
@@ -123,7 +125,8 @@ export interface ConsoleActions {
123
125
  page: { readonly limit: number; readonly offset: number },
124
126
  signal?: AbortSignal,
125
127
  ): Promise<RestGoals>;
126
- raiseDecision(input: RestDecisionInput): Promise<RestDecision>;
128
+ /** Raises a decision in the project; with `files`, the files put on it (ADR-0055). */
129
+ raiseDecision(input: RestDecisionInput, files?: readonly FileUpload[]): Promise<RestDecision>;
127
130
  answerDecision(id: string, input: RestAnswerInput): Promise<RestDecision>;
128
131
  /** Answers a decision of any project the person may see, by its project's key: for the person's own page of decisions (ADR-0042). */
129
132
  answerDecisionIn(projectKey: string, id: string, input: RestAnswerInput): Promise<RestDecision>;
@@ -198,6 +201,8 @@ export interface ConsoleActions {
198
201
  connectRequest(code: string, signal?: AbortSignal): Promise<RestConnectRequest>;
199
202
  approveConnection(code: string, input: RestTokenInput): Promise<RestConnectRequest>;
200
203
  denyConnection(code: string): Promise<void>;
204
+ /** Reads the plugins again: after one was enabled, configured or disabled on the settings. */
205
+ refreshPlugins(): Promise<void>;
201
206
  /** Another person's plate: for an administrator, or an owner of a project they are in. */
202
207
  personWork(personId: string, signal?: AbortSignal): Promise<RestPersonWork>;
203
208
  /** The tokens of another person, and the way to take one away: for an administrator. */
@@ -223,6 +228,8 @@ export interface ConsoleData {
223
228
  readonly organization: RestOrganization | null;
224
229
  /** The categories tasks are sorted into, by name. */
225
230
  readonly categories: readonly RestCategory[];
231
+ /** The plugins the person may know of (docs/specs/plugins.md), by key: the enabled ones, every one for an administrator. */
232
+ readonly plugins: readonly RestPlugin[];
226
233
  /** The tokens of whoever is signed in, newest first. */
227
234
  readonly tokens: readonly RestToken[];
228
235
  /** The project the page is on, once loaded; `undefined` while loading, or when the page is on none. */
@@ -245,6 +252,8 @@ export interface ConsoleData {
245
252
  readonly members: readonly RestMember[];
246
253
  /** The project's skills, as the console answered; `undefined` until it has. */
247
254
  readonly skills: RestSkills | undefined;
255
+ /** The plugins bound to the project that the person holds a role in, as the rules name them. */
256
+ readonly projectPlugins: readonly RestRulesPlugin[];
248
257
  readonly actions: ConsoleActions;
249
258
  /** Asks everything again, from who is signed in on. */
250
259
  reload(): void;
@@ -354,6 +363,7 @@ export function useConsoleData(client: ConsoleClient, projectKey: string | undef
354
363
  const [listed, setListed] = useState<readonly RestListing[]>([]);
355
364
  const [organization, setOrganization] = useState<RestOrganization | null>(null);
356
365
  const [categories, setCategories] = useState<readonly RestCategory[]>([]);
366
+ const [plugins, setPlugins] = useState<readonly RestPlugin[]>([]);
357
367
  const [tokens, setTokens] = useState<readonly RestToken[]>([]);
358
368
  const [project, setProject] = useState<RestProject | undefined>(undefined);
359
369
  const [projectLoaded, setProjectLoaded] = useState(false);
@@ -366,19 +376,36 @@ export function useConsoleData(client: ConsoleClient, projectKey: string | undef
366
376
  const [events, setEvents] = useState<readonly RestEvent[]>([]);
367
377
  const [members, setMembers] = useState<readonly RestMember[]>([]);
368
378
  const [skills, setSkills] = useState<RestSkills | undefined>(undefined);
379
+ const [projectPlugins, setProjectPlugins] = useState<readonly RestRulesPlugin[]>([]);
369
380
  const [generation, setGeneration] = useState(0);
370
381
  const lastEvent = useRef(0);
371
382
  const signedIn = me?.person !== null && me !== undefined;
372
383
 
373
384
  const reload = useCallback(() => setGeneration((current) => current + 1), []);
374
385
 
386
+ /**
387
+ * Asks again who is signed in, for what moves with the board: the decisions waiting for the
388
+ * person, said beside My decisions. What fails stays as it was.
389
+ */
390
+ const refreshMe = useCallback(
391
+ async (signal?: AbortSignal) => {
392
+ const answer = await client.me(signal);
393
+ if (signal?.aborted !== true) {
394
+ setMe(answer);
395
+ }
396
+ },
397
+ [client],
398
+ );
399
+
375
400
  /** Loads the workspace's lists again. What fails stays as it was. */
376
401
  const refreshWorkspace = useCallback(
377
402
  async (signal?: AbortSignal) => {
378
- const [nextProjects, nextPeople, nextCategories] = await Promise.all([
403
+ const [nextProjects, nextPeople, nextCategories, nextPlugins] = await Promise.all([
379
404
  client.projects(signal),
380
405
  client.people(signal),
381
406
  client.categories(signal),
407
+ // A console without plugins answers none; one older than them answers nothing, which is none too.
408
+ client.plugins(signal).catch(() => ({ items: [], sql: false })),
382
409
  ]);
383
410
  if (signal?.aborted === true) {
384
411
  return;
@@ -388,6 +415,7 @@ export function useConsoleData(client: ConsoleClient, projectKey: string | undef
388
415
  setListed(nextPeople.listed);
389
416
  setOrganization(nextPeople.organization);
390
417
  setCategories(nextCategories.items);
418
+ setPlugins(nextPlugins.items);
391
419
  },
392
420
  [client],
393
421
  );
@@ -399,7 +427,7 @@ export function useConsoleData(client: ConsoleClient, projectKey: string | undef
399
427
  return;
400
428
  }
401
429
  const scope = client.project(projectKey);
402
- const [nextProject, nextTasks, nextDecisions, nextGoals, nextRuns, nextMembers] =
430
+ const [nextProject, nextTasks, nextDecisions, nextGoals, nextRuns, nextMembers, nextPlugins] =
403
431
  await Promise.all([
404
432
  scope.get(signal),
405
433
  readTasks(scope, signal),
@@ -407,6 +435,11 @@ export function useConsoleData(client: ConsoleClient, projectKey: string | undef
407
435
  readGoals(scope, signal),
408
436
  scope.runs(undefined, signal),
409
437
  scope.members(signal),
438
+ // The plugins bound to the project come with its rules; a console older than them names none.
439
+ scope
440
+ .rules(signal)
441
+ .then((rules) => rules.plugins ?? [])
442
+ .catch((): readonly RestRulesPlugin[] => []),
410
443
  ]);
411
444
  if (signal?.aborted === true) {
412
445
  return;
@@ -417,6 +450,7 @@ export function useConsoleData(client: ConsoleClient, projectKey: string | undef
417
450
  setGoals(nextGoals.items);
418
451
  setRuns(nextRuns.items);
419
452
  setMembers(nextMembers.items);
453
+ setProjectPlugins(nextPlugins);
420
454
  },
421
455
  [client, projectKey],
422
456
  );
@@ -480,6 +514,7 @@ export function useConsoleData(client: ConsoleClient, projectKey: string | undef
480
514
  setEvents([]);
481
515
  setMembers([]);
482
516
  setSkills(undefined);
517
+ setProjectPlugins([]);
483
518
  setLive(false);
484
519
  if (projectKey === undefined || !signedIn) {
485
520
  return;
@@ -551,6 +586,11 @@ export function useConsoleData(client: ConsoleClient, projectKey: string | undef
551
586
  if (event.kind.startsWith("project.")) {
552
587
  refreshWorkspace(signal).catch(() => undefined);
553
588
  }
589
+ // A decision raised or answered here may be one of the person's own: the count beside
590
+ // My decisions follows it.
591
+ if (event.kind.startsWith("decision.")) {
592
+ refreshMe(signal).catch(() => undefined);
593
+ }
554
594
  }, RELOAD_DELAY_MS);
555
595
  };
556
596
  for (const kind of EVENT_KINDS) {
@@ -564,7 +604,7 @@ export function useConsoleData(client: ConsoleClient, projectKey: string | undef
564
604
  source?.close();
565
605
  setLive(false);
566
606
  };
567
- }, [client, projectKey, signedIn, generation, refreshProject, refreshWorkspace]);
607
+ }, [client, projectKey, signedIn, generation, refreshProject, refreshWorkspace, refreshMe]);
568
608
 
569
609
  const actions = useMemo<ConsoleActions>(() => {
570
610
  /** The project the page is on, for an action that needs one. */
@@ -664,16 +704,19 @@ export function useConsoleData(client: ConsoleClient, projectKey: string | undef
664
704
  scope().tasks({ archived: false, ...searchWordsOf(query), ...page }, signal),
665
705
  findGoals: (query, page, signal) =>
666
706
  scope().goals({ open: true, ...searchWordsOf(query), ...page }, signal),
667
- async raiseDecision(input) {
668
- const decision = await scope().raiseDecision(input);
669
- await refreshProject();
707
+ async raiseDecision(input, files) {
708
+ const decision = await scope().raiseDecision(input, files);
709
+ await Promise.all([refreshProject(), refreshMe().catch(() => undefined)]);
710
+ return decision;
711
+ },
712
+ async answerDecisionIn(projectKey, id, input) {
713
+ const decision = await client.project(projectKey).answerDecision(id, input);
714
+ await refreshMe().catch(() => undefined);
670
715
  return decision;
671
716
  },
672
- answerDecisionIn: (projectKey, id, input) =>
673
- client.project(projectKey).answerDecision(id, input),
674
717
  async answerDecision(id, input) {
675
718
  const decision = await scope().answerDecision(id, input);
676
- await refreshProject();
719
+ await Promise.all([refreshProject(), refreshMe().catch(() => undefined)]);
677
720
  return decision;
678
721
  },
679
722
  async updateDecision(id, patch) {
@@ -766,6 +809,9 @@ export function useConsoleData(client: ConsoleClient, projectKey: string | undef
766
809
  },
767
810
  cancelWorkspacePackTokenConnection: () => client.cancelWorkspacePackTokenConnection(),
768
811
  findPerson: (login, signal) => client.findPerson(login, signal),
812
+ async refreshPlugins() {
813
+ setPlugins((await client.plugins()).items);
814
+ },
769
815
  async abandonRun(id) {
770
816
  const run = await scope().endRun(id, { status: "abandoned" });
771
817
  await refreshProject();
@@ -811,7 +857,7 @@ export function useConsoleData(client: ConsoleClient, projectKey: string | undef
811
857
  setLoaded(false);
812
858
  },
813
859
  };
814
- }, [client, projectKey, refreshProject, refreshWorkspace]);
860
+ }, [client, projectKey, refreshProject, refreshWorkspace, refreshMe]);
815
861
 
816
862
  return {
817
863
  me,
@@ -822,6 +868,7 @@ export function useConsoleData(client: ConsoleClient, projectKey: string | undef
822
868
  listed,
823
869
  organization,
824
870
  categories,
871
+ plugins,
825
872
  tokens,
826
873
  project,
827
874
  projectLoaded,
@@ -834,6 +881,7 @@ export function useConsoleData(client: ConsoleClient, projectKey: string | undef
834
881
  events,
835
882
  members,
836
883
  skills,
884
+ projectPlugins,
837
885
  actions,
838
886
  reload,
839
887
  };
package/src/i18n/en.ts CHANGED
@@ -29,6 +29,15 @@ export const en = {
29
29
  label: "English",
30
30
 
31
31
  vocabulary: {
32
+ /** The states of a plugin (docs/specs/plugins.md, "Lifecycle"). */
33
+ pluginState: {
34
+ installed: "Installed",
35
+ enabled: "Enabled",
36
+ needs_consent: "Needs consent",
37
+ disabled: "Disabled",
38
+ failed: "Failed",
39
+ orphaned: "Orphaned",
40
+ } as Record<string, string>,
32
41
  state: {
33
42
  idea: "Idea",
34
43
  ready: "Ready",
@@ -143,6 +152,138 @@ export const en = {
143
152
  skills: "Skills",
144
153
  members: "Members",
145
154
  settings: "Settings",
155
+ plugins: "Plugins",
156
+ /** The groups of tabs the console knows (docs/specs/plugins.md, "Tabs, sub-tabs and addresses"). */
157
+ pluginGroups: {
158
+ people: "People",
159
+ customers: "Customers",
160
+ money: "Money",
161
+ operations: "Operations",
162
+ marketing: "Marketing",
163
+ engineering: "Engineering",
164
+ reports: "Reports",
165
+ } as Record<string, string>,
166
+ },
167
+
168
+ plugins: {
169
+ frame: (name: string) => `${name}, a plugin's page`,
170
+ noPage: {
171
+ title: "Nothing here",
172
+ body: "This plugin has no page you may see, or it is not on this project.",
173
+ },
174
+ settings: {
175
+ title: "Plugins",
176
+ empty: { title: "No plugins", body: "None is installed in this console's image." },
177
+ none: "The console has no plugins directory: none can be installed.",
178
+ about: "About",
179
+ problems: "Why it cannot run",
180
+ nothing: "None",
181
+ capabilities: "Capabilities",
182
+ board: "Board project",
183
+ boardHint: "Where its decisions, tasks and pages go.",
184
+ boardNone: "None",
185
+ boardCreate: "A new project",
186
+ boardChoose: "An existing project",
187
+ boardKey: "Key",
188
+ boardName: "Name",
189
+ boardDescription: "Description",
190
+ projects: "Projects",
191
+ projectsAll: "Every project",
192
+ projectsSome: "Some projects",
193
+ settingsForm: "Settings",
194
+ secretSet: (when: string) => `Set ${when}`,
195
+ secretUnset: "Not set",
196
+ secretNew: "New value",
197
+ enable: "Enable",
198
+ disable: "Disable",
199
+ roles: "Roles",
200
+ rolesNone: "No roles: every member may use it.",
201
+ roleDefault: "Default",
202
+ everyMember: "Every member",
203
+ grantEveryone: "Everyone",
204
+ grantMembersOf: (project: string) => `Members of ${project}`,
205
+ grantPeople: "People",
206
+ grantProjects: "Members of a project",
207
+ grantWhom: "Grant to…",
208
+ grant: "Grant",
209
+ revoke: "Revoke",
210
+ events: "What happened",
211
+ noEvents: "Nothing yet.",
212
+ data: "Data",
213
+ export: "Export",
214
+ exportHint: "Its records and their versions, as JSON Lines.",
215
+ exportLink: "Download",
216
+ purge: "Purge",
217
+ purgeHint:
218
+ "Removes its records, files, grants and secrets from the console. What it put on the board stays.",
219
+ purgeDisabledFirst: "Disable it first.",
220
+ purgeConfirm: (key: string) => `Type ${key}`,
221
+ purged: "Purged.",
222
+ agentNote: "For agents",
223
+ operations: "Commands and queries",
224
+ },
225
+ /** The capabilities (docs/specs/plugins.md, "Capabilities"), each by a name and the sentence of what it opens, as an administrator reads them before consenting. */
226
+ capability: {
227
+ files: {
228
+ name: "Files",
229
+ opens: "Keeps files on its records, within the bytes the deployment allows.",
230
+ },
231
+ "people:read": { name: "People", opens: "Reads the people the person may see." },
232
+ "people:read:all": {
233
+ name: "Everyone",
234
+ opens: "Reads everyone in the workspace, from its jobs and hooks too.",
235
+ },
236
+ "projects:read": {
237
+ name: "Projects",
238
+ opens: "Reads the projects and members the person may see.",
239
+ },
240
+ "projects:read:all": {
241
+ name: "Every project",
242
+ opens: "Reads every project and its members.",
243
+ },
244
+ "board:read": {
245
+ name: "Board",
246
+ opens:
247
+ "Reads the tasks, decisions, runs, pages and events of its board projects, and of the project a call is on.",
248
+ },
249
+ "board:tasks": {
250
+ name: "Tasks",
251
+ opens: "Creates tasks in its projects; changes, closes and comments on its own.",
252
+ },
253
+ "board:decisions": {
254
+ name: "Decisions",
255
+ opens: "Raises decisions in its projects and reads the answers to its own.",
256
+ },
257
+ "board:documents": {
258
+ name: "Pages",
259
+ opens: "Writes pages in a folder of its own in its projects.",
260
+ },
261
+ "events:console": {
262
+ name: "Console events",
263
+ opens: "Runs hooks on what happens in its board projects.",
264
+ },
265
+ "events:plugins": {
266
+ name: "Other plugins' events",
267
+ opens: "Runs hooks on the events other plugins emit.",
268
+ },
269
+ jobs: { name: "Schedule", opens: "Runs at the times it names." },
270
+ endpoints: {
271
+ name: "Inbound requests",
272
+ opens: "Takes requests under its own path, a person's or a webhook's.",
273
+ },
274
+ "storage:sql": {
275
+ name: "Own database schema",
276
+ opens: "Gets a schema and a login role of its own in the console's database.",
277
+ },
278
+ outbound: (host: string) => ({
279
+ name: `Requests to ${host}`,
280
+ opens: `Sends https requests to ${host}.`,
281
+ }),
282
+ plugins: (key: string) => ({
283
+ name: `Plugin ${key}`,
284
+ opens: `Calls the API of the plugin ${key}, as the person.`,
285
+ }),
286
+ },
146
287
  },
147
288
 
148
289
  shell: {
@@ -407,6 +548,8 @@ export const en = {
407
548
  about: "about",
408
549
  answeredBy: "answered",
409
550
  context: "Context",
551
+ files: "Files",
552
+ picture: (name: string) => `The picture ${name}`,
410
553
  whatFollowed: "What followed",
411
554
  nothingWritten: "Nothing written yet.",
412
555
  outcomePlaceholder: "What was done with the answer, and what came of it, in Markdown.",
@@ -416,6 +559,11 @@ export const en = {
416
559
  question: "Question",
417
560
  context: "Context",
418
561
  contextPlaceholder: "What a person needs to know to answer, in Markdown.",
562
+ files: "Files",
563
+ chooseFiles: "Add files",
564
+ filesHint:
565
+ "A picture pasted or chosen here goes with the decision; ![words](its name) places it in the context.",
566
+ removeFile: (name: string) => `Take ${name} out`,
419
567
  about: "About",
420
568
  noTask: "No task in particular",
421
569
  decider: "Who decides",
@@ -595,6 +743,8 @@ export const en = {
595
743
  workspace: {
596
744
  title: "Workspace",
597
745
  aria: "Workspace settings",
746
+ consoleVersion: "Console version",
747
+ consoleTakes: (range: string) => `Takes the console command ${range}`,
598
748
  peopleVisibility: "Member visibility",
599
749
  peopleVisibilityHint:
600
750
  "Whom a member sees on the People page and in the pickers: everyone of the workspace, or only the people they share a project with. An administrator always sees everyone, and a project open to the workspace has everyone in it.",
@@ -640,6 +790,17 @@ export const en = {
640
790
  as: (agent: string) => `as ${agent}`,
641
791
  asTitle: "The agent the person acted through",
642
792
  aTask: "a task",
793
+ aPlugin: "a plugin",
794
+ /** After the sentence of a board's event a plugin caused (ADR-0052). */
795
+ throughPlugin: (plugin: string) => `through the plugin ${plugin}`,
796
+ everyone: "everyone",
797
+ membersOf: (project: string) => `the members of ${project}`,
798
+ outcome: {
799
+ ok: "done",
800
+ refused: "refused",
801
+ waiting: "waiting for a decision",
802
+ failed: "failed",
803
+ } as Readonly<Record<string, string>>,
643
804
  aProject: "a project",
644
805
  someone: "someone",
645
806
  something: "something",
@@ -725,6 +886,20 @@ export const en = {
725
886
  documentArchived: (page: string) => `archived ${page}`,
726
887
  documentRestored: (page: string) => `restored ${page}`,
727
888
  fileAttached: (label: string, page: string) => `attached ${label} to ${page}`,
889
+ pluginEnabled: (plugin: string) => `enabled the plugin ${plugin}`,
890
+ pluginDisabled: (plugin: string) => `disabled the plugin ${plugin}`,
891
+ pluginConfigured: (fields: string, plugin: string) =>
892
+ `changed ${fields} of the plugin ${plugin}`,
893
+ pluginGranted: (role: string, who: string, plugin: string) =>
894
+ `gave ${who} the role ${role} in the plugin ${plugin}`,
895
+ pluginRevoked: (role: string, who: string, plugin: string) =>
896
+ `took the role ${role} from ${who} in the plugin ${plugin}`,
897
+ pluginUpgraded: (plugin: string, version: string) =>
898
+ `brought the plugin ${plugin} to ${version}`,
899
+ pluginCommand: (command: string, plugin: string, outcome: string) =>
900
+ `ran ${command} of the plugin ${plugin}: ${outcome}`,
901
+ pluginPurged: (plugin: string) => `purged the plugin ${plugin}: everything it kept is gone`,
902
+ pluginFailed: (plugin: string, problem: string) => `the plugin ${plugin} failed: ${problem}`,
728
903
  },
729
904
  },
730
905
 
package/src/i18n/ko.ts CHANGED
@@ -8,6 +8,14 @@ export const ko: Messages = {
8
8
  label: "한국어",
9
9
 
10
10
  vocabulary: {
11
+ pluginState: {
12
+ installed: "설치됨",
13
+ enabled: "활성",
14
+ needs_consent: "동의 필요",
15
+ disabled: "비활성",
16
+ failed: "실패",
17
+ orphaned: "패키지 없음",
18
+ },
11
19
  state: {
12
20
  idea: "아이디어",
13
21
  ready: "준비됨",
@@ -105,6 +113,122 @@ export const ko: Messages = {
105
113
  skills: "스킬",
106
114
  members: "멤버",
107
115
  settings: "설정",
116
+ plugins: "플러그인",
117
+ pluginGroups: {
118
+ people: "사람",
119
+ customers: "고객",
120
+ money: "돈",
121
+ operations: "운영",
122
+ marketing: "마케팅",
123
+ engineering: "엔지니어링",
124
+ reports: "보고",
125
+ },
126
+ },
127
+
128
+ plugins: {
129
+ frame: (name) => `${name}, 플러그인 페이지`,
130
+ noPage: {
131
+ title: "여기엔 없습니다",
132
+ body: "이 플러그인에는 볼 수 있는 페이지가 없거나, 이 프로젝트에 올라가 있지 않습니다.",
133
+ },
134
+ settings: {
135
+ title: "플러그인",
136
+ empty: { title: "플러그인 없음", body: "이 콘솔의 이미지에 설치된 플러그인이 없습니다." },
137
+ none: "콘솔에 플러그인 디렉터리가 없어 설치할 수 없습니다.",
138
+ about: "개요",
139
+ problems: "실행할 수 없는 이유",
140
+ nothing: "없음",
141
+ capabilities: "권한",
142
+ board: "보드 프로젝트",
143
+ boardHint: "플러그인의 결정, 태스크, 문서가 가는 곳입니다.",
144
+ boardNone: "없음",
145
+ boardCreate: "새 프로젝트",
146
+ boardChoose: "기존 프로젝트",
147
+ boardKey: "키",
148
+ boardName: "이름",
149
+ boardDescription: "설명",
150
+ projects: "프로젝트",
151
+ projectsAll: "모든 프로젝트",
152
+ projectsSome: "일부 프로젝트",
153
+ settingsForm: "설정",
154
+ secretSet: (when) => `${when} 설정됨`,
155
+ secretUnset: "설정 안 됨",
156
+ secretNew: "새 값",
157
+ enable: "활성화",
158
+ disable: "비활성화",
159
+ roles: "역할",
160
+ rolesNone: "역할이 없어 모든 멤버가 쓸 수 있습니다.",
161
+ roleDefault: "기본",
162
+ everyMember: "모든 멤버",
163
+ grantEveryone: "모두",
164
+ grantMembersOf: (project) => `${project}의 멤버`,
165
+ grantPeople: "사람",
166
+ grantProjects: "프로젝트의 멤버",
167
+ grantWhom: "부여할 대상…",
168
+ grant: "부여",
169
+ revoke: "회수",
170
+ events: "일어난 일",
171
+ noEvents: "아직 없습니다.",
172
+ data: "데이터",
173
+ export: "내보내기",
174
+ exportHint: "레코드와 그 버전을 JSON Lines로 받습니다.",
175
+ exportLink: "내려받기",
176
+ purge: "삭제",
177
+ purgeHint: "콘솔에 있는 레코드, 파일, 역할, 비밀을 지웁니다. 보드에 남긴 것은 남습니다.",
178
+ purgeDisabledFirst: "삭제하려면 먼저 비활성화하세요.",
179
+ purgeConfirm: (key) => `${key} 입력`,
180
+ purged: "삭제했습니다.",
181
+ agentNote: "에이전트에게",
182
+ operations: "명령과 조회",
183
+ },
184
+ capability: {
185
+ files: { name: "파일", opens: "레코드에 파일을 붙입니다. 배포가 허용한 용량까지." },
186
+ "people:read": { name: "사람 읽기", opens: "보는 사람이 볼 수 있는 사람들을 읽습니다." },
187
+ "people:read:all": {
188
+ name: "모든 사람 읽기",
189
+ opens: "워크스페이스의 모든 사람을 읽습니다. 예약 실행과 훅에서도.",
190
+ },
191
+ "projects:read": {
192
+ name: "프로젝트 읽기",
193
+ opens: "보는 사람이 볼 수 있는 프로젝트와 멤버를 읽습니다.",
194
+ },
195
+ "projects:read:all": {
196
+ name: "모든 프로젝트 읽기",
197
+ opens: "모든 프로젝트와 멤버를 읽습니다.",
198
+ },
199
+ "board:read": {
200
+ name: "보드 읽기",
201
+ opens: "보드 프로젝트와 호출된 프로젝트의 태스크, 결정, 실행, 문서, 이벤트를 읽습니다.",
202
+ },
203
+ "board:tasks": {
204
+ name: "태스크",
205
+ opens: "자기 프로젝트에 태스크를 만들고, 만든 것을 바꾸고 닫고 댓글을 답니다.",
206
+ },
207
+ "board:decisions": { name: "결정", opens: "자기 프로젝트에 결정을 올리고 그 답을 읽습니다." },
208
+ "board:documents": { name: "문서", opens: "자기 프로젝트의 문서에 자기 폴더를 두고 씁니다." },
209
+ "events:console": {
210
+ name: "콘솔 이벤트",
211
+ opens: "보드 프로젝트에서 일어나는 일에 훅을 겁니다.",
212
+ },
213
+ "events:plugins": {
214
+ name: "다른 플러그인의 이벤트",
215
+ opens: "다른 플러그인이 내는 이벤트에 훅을 겁니다.",
216
+ },
217
+ jobs: { name: "예약 실행", opens: "정해진 시간에 실행됩니다." },
218
+ endpoints: {
219
+ name: "요청 받기",
220
+ opens: "자기 경로로 오는 요청을 받습니다. 사람의 요청이나 웹훅.",
221
+ },
222
+ "storage:sql": {
223
+ name: "전용 데이터베이스 스키마",
224
+ opens: "콘솔 데이터베이스에 전용 스키마와 로그인 역할을 갖습니다.",
225
+ },
226
+ outbound: (host) => ({ name: `${host}로 요청`, opens: `${host}에 https 요청을 보냅니다.` }),
227
+ plugins: (key) => ({
228
+ name: `플러그인 ${key} 호출`,
229
+ opens: `플러그인 ${key}의 API를 호출한 사람의 권한으로 호출합니다.`,
230
+ }),
231
+ },
108
232
  },
109
233
 
110
234
  shell: {
@@ -365,6 +489,8 @@ export const ko: Messages = {
365
489
  about: "관련 작업:",
366
490
  answeredBy: "답변",
367
491
  context: "맥락",
492
+ files: "파일",
493
+ picture: (name) => `그림 ${name}`,
368
494
  whatFollowed: "그 뒤에 일어난 일",
369
495
  nothingWritten: "아직 적힌 것이 없습니다.",
370
496
  outcomePlaceholder: "답변으로 무엇을 했고 무엇이 됐는지, Markdown으로.",
@@ -374,6 +500,11 @@ export const ko: Messages = {
374
500
  question: "질문",
375
501
  context: "맥락",
376
502
  contextPlaceholder: "답하려면 알아야 할 것, Markdown으로.",
503
+ files: "파일",
504
+ chooseFiles: "파일 추가",
505
+ filesHint:
506
+ "여기에 붙여 넣거나 고른 그림은 결정과 함께 올라갑니다. ![설명](파일 이름)으로 맥락에 넣을 수 있습니다.",
507
+ removeFile: (name) => `${name} 빼기`,
377
508
  about: "관련 작업",
378
509
  noTask: "특정 작업 없음",
379
510
  decider: "결정할 사람",
@@ -551,6 +682,8 @@ export const ko: Messages = {
551
682
  workspace: {
552
683
  title: "워크스페이스",
553
684
  aria: "워크스페이스 설정",
685
+ consoleVersion: "콘솔 버전",
686
+ consoleTakes: (range) => `받는 console 명령: ${range}`,
554
687
  peopleVisibility: "멤버 공개 범위",
555
688
  peopleVisibilityHint:
556
689
  "멤버가 사람들 페이지와 선택 목록에서 보는 범위: 워크스페이스의 모두, 또는 같은 프로젝트에 속한 사람만. 관리자는 언제나 모두를 보고, 워크스페이스에 공개된 프로젝트에는 모두가 속합니다.",
@@ -596,6 +729,16 @@ export const ko: Messages = {
596
729
  as: (agent) => `${agent}(으)로`,
597
730
  asTitle: "그 사람이 사용한 에이전트",
598
731
  aTask: "작업",
732
+ aPlugin: "플러그인",
733
+ throughPlugin: (plugin) => `플러그인 ${plugin}을(를) 통해`,
734
+ everyone: "모든 구성원",
735
+ membersOf: (project) => `${project}의 구성원`,
736
+ outcome: {
737
+ ok: "완료",
738
+ refused: "거절됨",
739
+ waiting: "결정 대기",
740
+ failed: "실패",
741
+ },
599
742
  aProject: "프로젝트",
600
743
  someone: "누군가",
601
744
  something: "무언가",
@@ -678,6 +821,18 @@ export const ko: Messages = {
678
821
  documentArchived: (page) => `${page}을(를) 보관했습니다`,
679
822
  documentRestored: (page) => `${page}을(를) 복원했습니다`,
680
823
  fileAttached: (label, page) => `${page}에 ${label}을(를) 첨부했습니다`,
824
+ pluginEnabled: (plugin) => `플러그인 ${plugin}을(를) 활성화했습니다`,
825
+ pluginDisabled: (plugin) => `플러그인 ${plugin}을(를) 비활성화했습니다`,
826
+ pluginConfigured: (fields, plugin) => `플러그인 ${plugin}의 ${fields}을(를) 바꿨습니다`,
827
+ pluginGranted: (role, who, plugin) =>
828
+ `${who}에게 플러그인 ${plugin}의 ${role} 역할을 주었습니다`,
829
+ pluginRevoked: (role, who, plugin) =>
830
+ `${who}에게서 플러그인 ${plugin}의 ${role} 역할을 거두었습니다`,
831
+ pluginUpgraded: (plugin, version) => `플러그인 ${plugin}을(를) ${version}으로 올렸습니다`,
832
+ pluginCommand: (command, plugin, outcome) =>
833
+ `플러그인 ${plugin}의 ${command}을(를) 실행했습니다: ${outcome}`,
834
+ pluginPurged: (plugin) => `플러그인 ${plugin}을(를) 완전히 지웠습니다`,
835
+ pluginFailed: (plugin, problem) => `플러그인 ${plugin}이(가) 실패했습니다: ${problem}`,
681
836
  },
682
837
  },
683
838
 
package/src/index.ts CHANGED
@@ -131,6 +131,15 @@ export {
131
131
  ZOOM_STEP,
132
132
  zoomAround,
133
133
  } from "./components/pictures.js";
134
+ export {
135
+ BridgeRefusal,
136
+ PluginFrame,
137
+ type PluginFrameProps,
138
+ PluginWidgets,
139
+ type PluginWidgetsProps,
140
+ performBridgeCall,
141
+ readTheme,
142
+ } from "./components/plugin-frame.js";
134
143
  export {
135
144
  keyOf,
136
145
  MemberList,
@@ -303,6 +312,8 @@ export {
303
312
  type ProjectPage,
304
313
  personAgentsHref,
305
314
  personWorkHref,
315
+ pluginHref,
316
+ pluginSettingsHref,
306
317
  projectHref,
307
318
  projectSettingsHref,
308
319
  type Route,
@@ -314,4 +325,5 @@ export {
314
325
  withoutSignInParam,
315
326
  workHref,
316
327
  } from "./router.js";
328
+ export { CONSOLE_TOKENS } from "./tokens.js";
317
329
  export { errorWords, useAction } from "./use-action.js";
package/src/limits.ts CHANGED
@@ -33,6 +33,8 @@ export const MAX_ARTIFACTS_PER_RUN = 50;
33
33
  /** How many comments one task carries, and how many files one comment carries, together within `MAX_FILE_BYTES`. */
34
34
  export const MAX_COMMENTS_PER_TASK = 500;
35
35
  export const MAX_FILES_PER_COMMENT = 10;
36
+ /** How many files one decision carries, put on it when it is raised (ADR-0055), together within `MAX_FILE_BYTES`. */
37
+ export const MAX_FILES_PER_DECISION = 10;
36
38
  /** A file a run hands in: how many bytes, and its name, one line without a path. */
37
39
  export const MAX_FILE_BYTES = 10 * 1024 * 1024;
38
40
  export const MAX_FILE_NAME_LENGTH = 200;