@skillcdn/console 0.4.0 → 0.4.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 (308) hide show
  1. package/README.md +20 -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 +579 -45
  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 +277 -6
  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 +60 -7
  16. package/dist/cli/help.js.map +1 -1
  17. package/dist/cli/plugin-check.d.ts +21 -0
  18. package/dist/cli/plugin-check.d.ts.map +1 -0
  19. package/dist/cli/plugin-check.js +374 -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 +123 -0
  24. package/dist/cli/plugin-cli.js.map +1 -0
  25. package/dist/cli/plugin-init.d.ts +20 -0
  26. package/dist/cli/plugin-init.d.ts.map +1 -0
  27. package/dist/cli/plugin-init.js +74 -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 +109 -2
  34. package/dist/client.d.ts.map +1 -1
  35. package/dist/client.js +67 -2
  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/event-feed.d.ts +1 -1
  44. package/dist/components/event-feed.d.ts.map +1 -1
  45. package/dist/components/event-feed.js +33 -1
  46. package/dist/components/event-feed.js.map +1 -1
  47. package/dist/components/markdown.d.ts.map +1 -1
  48. package/dist/components/markdown.js +6 -3
  49. package/dist/components/markdown.js.map +1 -1
  50. package/dist/components/pack-connect.d.ts +3 -1
  51. package/dist/components/pack-connect.d.ts.map +1 -1
  52. package/dist/components/pack-connect.js +4 -4
  53. package/dist/components/pack-connect.js.map +1 -1
  54. package/dist/components/pack-token.d.ts +3 -1
  55. package/dist/components/pack-token.d.ts.map +1 -1
  56. package/dist/components/pack-token.js +1 -1
  57. package/dist/components/pack-token.js.map +1 -1
  58. package/dist/components/people.d.ts.map +1 -1
  59. package/dist/components/people.js +14 -3
  60. package/dist/components/people.js.map +1 -1
  61. package/dist/components/plugin-frame.d.ts +52 -0
  62. package/dist/components/plugin-frame.d.ts.map +1 -0
  63. package/dist/components/plugin-frame.js +314 -0
  64. package/dist/components/plugin-frame.js.map +1 -0
  65. package/dist/components/plugin-settings.d.ts +38 -0
  66. package/dist/components/plugin-settings.d.ts.map +1 -0
  67. package/dist/components/plugin-settings.js +348 -0
  68. package/dist/components/plugin-settings.js.map +1 -0
  69. package/dist/components/remote-pictures.d.ts +6 -0
  70. package/dist/components/remote-pictures.d.ts.map +1 -0
  71. package/dist/components/remote-pictures.js +8 -0
  72. package/dist/components/remote-pictures.js.map +1 -0
  73. package/dist/components/shell.d.ts +2 -0
  74. package/dist/components/shell.d.ts.map +1 -1
  75. package/dist/components/shell.js +26 -1
  76. package/dist/components/shell.js.map +1 -1
  77. package/dist/components/sign-in.d.ts.map +1 -1
  78. package/dist/components/sign-in.js +49 -2
  79. package/dist/components/sign-in.js.map +1 -1
  80. package/dist/components/ui.d.ts +3 -2
  81. package/dist/components/ui.d.ts.map +1 -1
  82. package/dist/components/ui.js +6 -3
  83. package/dist/components/ui.js.map +1 -1
  84. package/dist/components/workspace.d.ts +7 -1
  85. package/dist/components/workspace.d.ts.map +1 -1
  86. package/dist/components/workspace.js +1 -1
  87. package/dist/components/workspace.js.map +1 -1
  88. package/dist/console.css +384 -5
  89. package/dist/console.d.ts.map +1 -1
  90. package/dist/console.js +146 -29
  91. package/dist/console.js.map +1 -1
  92. package/dist/data.d.ts +11 -2
  93. package/dist/data.d.ts.map +1 -1
  94. package/dist/data.js +35 -21
  95. package/dist/data.js.map +1 -1
  96. package/dist/i18n/en.d.ts +163 -1
  97. package/dist/i18n/en.d.ts.map +1 -1
  98. package/dist/i18n/en.js +174 -1
  99. package/dist/i18n/en.js.map +1 -1
  100. package/dist/i18n/ko.d.ts.map +1 -1
  101. package/dist/i18n/ko.js +154 -1
  102. package/dist/i18n/ko.js.map +1 -1
  103. package/dist/index.d.ts +3 -1
  104. package/dist/index.d.ts.map +1 -1
  105. package/dist/index.js +3 -1
  106. package/dist/index.js.map +1 -1
  107. package/dist/limits.d.ts +14 -0
  108. package/dist/limits.d.ts.map +1 -1
  109. package/dist/limits.js +14 -0
  110. package/dist/limits.js.map +1 -1
  111. package/dist/plugin/args.d.ts +148 -0
  112. package/dist/plugin/args.d.ts.map +1 -0
  113. package/dist/plugin/args.js +369 -0
  114. package/dist/plugin/args.js.map +1 -0
  115. package/dist/plugin/bridge.d.ts +146 -0
  116. package/dist/plugin/bridge.d.ts.map +1 -0
  117. package/dist/plugin/bridge.js +125 -0
  118. package/dist/plugin/bridge.js.map +1 -0
  119. package/dist/plugin/capabilities.d.ts +20 -0
  120. package/dist/plugin/capabilities.d.ts.map +1 -0
  121. package/dist/plugin/capabilities.js +133 -0
  122. package/dist/plugin/capabilities.js.map +1 -0
  123. package/dist/plugin/context.d.ts +374 -0
  124. package/dist/plugin/context.d.ts.map +1 -0
  125. package/dist/plugin/context.js +2 -0
  126. package/dist/plugin/context.js.map +1 -0
  127. package/dist/plugin/define.d.ts +208 -0
  128. package/dist/plugin/define.d.ts.map +1 -0
  129. package/dist/plugin/define.js +482 -0
  130. package/dist/plugin/define.js.map +1 -0
  131. package/dist/plugin/definition-error.d.ts +11 -0
  132. package/dist/plugin/definition-error.d.ts.map +1 -0
  133. package/dist/plugin/definition-error.js +17 -0
  134. package/dist/plugin/definition-error.js.map +1 -0
  135. package/dist/plugin/limits.d.ts +67 -0
  136. package/dist/plugin/limits.d.ts.map +1 -0
  137. package/dist/plugin/limits.js +70 -0
  138. package/dist/plugin/limits.js.map +1 -0
  139. package/dist/plugin/load-worker.d.ts +7 -0
  140. package/dist/plugin/load-worker.d.ts.map +1 -0
  141. package/dist/plugin/load-worker.js +41 -0
  142. package/dist/plugin/load-worker.js.map +1 -0
  143. package/dist/plugin/load.d.ts +18 -0
  144. package/dist/plugin/load.d.ts.map +1 -0
  145. package/dist/plugin/load.js +62 -0
  146. package/dist/plugin/load.js.map +1 -0
  147. package/dist/plugin/manifest.d.ts +237 -0
  148. package/dist/plugin/manifest.d.ts.map +1 -0
  149. package/dist/plugin/manifest.js +411 -0
  150. package/dist/plugin/manifest.js.map +1 -0
  151. package/dist/plugin/refusals.d.ts +49 -0
  152. package/dist/plugin/refusals.d.ts.map +1 -0
  153. package/dist/plugin/refusals.js +79 -0
  154. package/dist/plugin/refusals.js.map +1 -0
  155. package/dist/plugin/rest-schemas.d.ts +556 -0
  156. package/dist/plugin/rest-schemas.d.ts.map +1 -0
  157. package/dist/plugin/rest-schemas.js +262 -0
  158. package/dist/plugin/rest-schemas.js.map +1 -0
  159. package/dist/plugin/sandbox.d.ts +23 -0
  160. package/dist/plugin/sandbox.d.ts.map +1 -0
  161. package/dist/plugin/sandbox.js +99 -0
  162. package/dist/plugin/sandbox.js.map +1 -0
  163. package/dist/plugin/testing.d.ts +45 -0
  164. package/dist/plugin/testing.d.ts.map +1 -0
  165. package/dist/plugin/testing.js +420 -0
  166. package/dist/plugin/testing.js.map +1 -0
  167. package/dist/plugin/web-react.d.ts +11 -0
  168. package/dist/plugin/web-react.d.ts.map +1 -0
  169. package/dist/plugin/web-react.js +34 -0
  170. package/dist/plugin/web-react.js.map +1 -0
  171. package/dist/plugin/web.d.ts +95 -0
  172. package/dist/plugin/web.d.ts.map +1 -0
  173. package/dist/plugin/web.js +245 -0
  174. package/dist/plugin/web.js.map +1 -0
  175. package/dist/plugin-nav.d.ts +29 -0
  176. package/dist/plugin-nav.d.ts.map +1 -0
  177. package/dist/plugin-nav.js +92 -0
  178. package/dist/plugin-nav.js.map +1 -0
  179. package/dist/plugin-testing.d.ts +2 -0
  180. package/dist/plugin-testing.d.ts.map +1 -0
  181. package/dist/plugin-testing.js +4 -0
  182. package/dist/plugin-testing.js.map +1 -0
  183. package/dist/plugin-web-react.d.ts +3 -0
  184. package/dist/plugin-web-react.d.ts.map +1 -0
  185. package/dist/plugin-web-react.js +3 -0
  186. package/dist/plugin-web-react.js.map +1 -0
  187. package/dist/plugin-web.d.ts +4 -0
  188. package/dist/plugin-web.d.ts.map +1 -0
  189. package/dist/plugin-web.js +5 -0
  190. package/dist/plugin-web.js.map +1 -0
  191. package/dist/plugin.d.ts +11 -0
  192. package/dist/plugin.d.ts.map +1 -0
  193. package/dist/plugin.js +15 -0
  194. package/dist/plugin.js.map +1 -0
  195. package/dist/router.d.ts +28 -0
  196. package/dist/router.d.ts.map +1 -1
  197. package/dist/router.js +47 -0
  198. package/dist/router.js.map +1 -1
  199. package/dist/routes.d.ts +6 -0
  200. package/dist/routes.d.ts.map +1 -1
  201. package/dist/routes.js +8 -0
  202. package/dist/routes.js.map +1 -1
  203. package/dist/schemas.d.ts +147 -1
  204. package/dist/schemas.d.ts.map +1 -1
  205. package/dist/schemas.js +55 -5
  206. package/dist/schemas.js.map +1 -1
  207. package/dist/tokens.d.ts +2 -0
  208. package/dist/tokens.d.ts.map +1 -0
  209. package/dist/tokens.js +101 -0
  210. package/dist/tokens.js.map +1 -0
  211. package/dist/vocabulary.d.ts +11 -1
  212. package/dist/vocabulary.d.ts.map +1 -1
  213. package/dist/vocabulary.js +24 -0
  214. package/dist/vocabulary.js.map +1 -1
  215. package/dist/web.d.ts.map +1 -1
  216. package/dist/web.js +5 -2
  217. package/dist/web.js.map +1 -1
  218. package/docs/specs/cli.md +16 -9
  219. package/docs/specs/plugins.md +487 -0
  220. package/docs/specs/rest.md +25 -13
  221. package/package.json +21 -3
  222. package/skills/building-a-console/SKILL.md +25 -26
  223. package/skills/building-a-console/references/configuring.md +40 -0
  224. package/skills/building-a-console/references/the-default-console.md +1 -1
  225. package/skills/building-a-console/references/the-look-from-a-website.md +5 -5
  226. package/skills/building-a-plugin/SKILL.md +137 -0
  227. package/skills/deploying-a-console/SKILL.md +24 -26
  228. package/skills/deploying-a-console/references/access.md +13 -9
  229. package/skills/deploying-a-console/references/resources.md +25 -10
  230. package/skills/deploying-a-console/references/running-it-again.md +15 -0
  231. package/skills/deploying-a-console/references/sizing.md +2 -0
  232. package/skills/planning-the-board/SKILL.md +96 -0
  233. package/skills/planning-the-board/references/a-task.md +36 -0
  234. package/skills/planning-the-board/references/setting-up.md +44 -0
  235. package/skills/working-the-board/SKILL.md +43 -34
  236. package/skills/working-the-board/references/the-pack.md +19 -0
  237. package/src/api.ts +16 -0
  238. package/src/cli/cli.ts +736 -45
  239. package/src/cli/format.ts +356 -9
  240. package/src/cli/help.ts +71 -6
  241. package/src/cli/plugin-check.ts +470 -0
  242. package/src/cli/plugin-cli.ts +148 -0
  243. package/src/cli/plugin-init.ts +90 -0
  244. package/src/cli/plugin-main.ts +30 -0
  245. package/src/client.ts +324 -1
  246. package/src/compat.ts +2 -2
  247. package/src/components/board.tsx +62 -14
  248. package/src/components/event-feed.tsx +42 -1
  249. package/src/components/markdown.tsx +6 -3
  250. package/src/components/pack-connect.tsx +10 -7
  251. package/src/components/pack-token.tsx +4 -1
  252. package/src/components/people.tsx +17 -7
  253. package/src/components/plugin-frame.tsx +437 -0
  254. package/src/components/plugin-settings.tsx +1111 -0
  255. package/src/components/remote-pictures.ts +19 -0
  256. package/src/components/shell.tsx +82 -14
  257. package/src/components/sign-in.tsx +114 -13
  258. package/src/components/ui.tsx +6 -3
  259. package/src/components/workspace.tsx +18 -0
  260. package/src/console.tsx +309 -23
  261. package/src/data.ts +47 -22
  262. package/src/i18n/en.ts +183 -1
  263. package/src/i18n/ko.ts +159 -1
  264. package/src/index.ts +12 -0
  265. package/src/limits.ts +14 -0
  266. package/src/plugin/args.ts +526 -0
  267. package/src/plugin/bridge.ts +314 -0
  268. package/src/plugin/capabilities.ts +150 -0
  269. package/src/plugin/context.ts +416 -0
  270. package/src/plugin/define.ts +792 -0
  271. package/src/plugin/definition-error.ts +19 -0
  272. package/src/plugin/limits.ts +70 -0
  273. package/src/plugin/load-worker.ts +50 -0
  274. package/src/plugin/load.ts +82 -0
  275. package/src/plugin/manifest.ts +561 -0
  276. package/src/plugin/refusals.ts +94 -0
  277. package/src/plugin/rest-schemas.ts +354 -0
  278. package/src/plugin/sandbox.ts +123 -0
  279. package/src/plugin/testing.ts +612 -0
  280. package/src/plugin/web-react.ts +45 -0
  281. package/src/plugin/web.ts +403 -0
  282. package/src/plugin-nav.ts +132 -0
  283. package/src/plugin-testing.ts +10 -0
  284. package/src/plugin-web-react.ts +4 -0
  285. package/src/plugin-web.ts +35 -0
  286. package/src/plugin.ts +126 -0
  287. package/src/router.ts +73 -0
  288. package/src/routes.ts +9 -0
  289. package/src/schemas.ts +60 -4
  290. package/src/styles/console.css +384 -5
  291. package/src/tokens.ts +101 -0
  292. package/src/vocabulary.ts +30 -0
  293. package/src/web.ts +5 -2
  294. package/template/plugin/.gitignore +2 -0
  295. package/template/plugin/README.md +26 -0
  296. package/template/plugin/SKILLCDN.md +13 -0
  297. package/template/plugin/build.mjs +40 -0
  298. package/template/plugin/console-plugin.json +50 -0
  299. package/template/plugin/package.json +27 -0
  300. package/template/plugin/skills/__key__/SKILL.md +23 -0
  301. package/template/plugin/src/check.test.ts +34 -0
  302. package/template/plugin/src/server/index.test.ts +41 -0
  303. package/template/plugin/src/server/index.ts +72 -0
  304. package/template/plugin/src/web/index.css +51 -0
  305. package/template/plugin/src/web/index.ts +115 -0
  306. package/template/plugin/tsconfig.json +17 -0
  307. package/skills/working-the-board/references/setting-up.md +0 -3
  308. /package/skills/{working-the-board → planning-the-board}/references/project-rules.md +0 -0
package/src/plugin.ts ADDED
@@ -0,0 +1,126 @@
1
+ // The contract between a console and a plugin's server module (docs/specs/plugins.md): the
2
+ // manifest's schema and words, `definePlugin` and its definers, the arguments, the types of `ctx`,
3
+ // the capabilities and the bounds, and `z`, the schema library a plugin writes its records with.
4
+ // A plugin bundles this into its server module; nothing of it is imported at runtime by the
5
+ // console, which reads the description the module yields.
6
+
7
+ export * as z from "zod";
8
+ export {
9
+ ARG_TYPES,
10
+ type ArgDefinition,
11
+ type ArgDefinitions,
12
+ type ArgDescription,
13
+ type ArgsOf,
14
+ type ArgType,
15
+ type ArgValue,
16
+ arg,
17
+ argProblem,
18
+ argsProblem,
19
+ argUsage,
20
+ argValueFromWord,
21
+ type ParsedArgv,
22
+ type PluginFileHandle,
23
+ type PluginPersonRef,
24
+ type PluginProjectRef,
25
+ parseArgv,
26
+ } from "./plugin/args.js";
27
+ export {
28
+ CAPABILITY_WORDS,
29
+ type CapabilityWords,
30
+ capabilityWords,
31
+ isPluginCapability,
32
+ outboundAllows,
33
+ PLUGIN_CAPABILITIES,
34
+ PLUGIN_CAPABILITY_PREFIXES,
35
+ type PluginCapability,
36
+ } from "./plugin/capabilities.js";
37
+ export type * from "./plugin/context.js";
38
+ export {
39
+ type ApiDefinition,
40
+ type CollectionDescription,
41
+ type CollectionInput,
42
+ type CommandDefinition,
43
+ type CommandInput,
44
+ type CommandResult,
45
+ defineCollection,
46
+ defineCommand,
47
+ defineEndpoint,
48
+ definePlugin,
49
+ defineQuery,
50
+ describePlugin,
51
+ descriptionProblems,
52
+ durationMs,
53
+ type EndpointAuth,
54
+ type EndpointDefinition,
55
+ type EndpointDescription,
56
+ type EndpointInput,
57
+ type HookHandler,
58
+ isPluginDefinition,
59
+ isQueryFile,
60
+ type JobDefinition,
61
+ type Lifecycle,
62
+ type OperationDescription,
63
+ type PluginDefinition,
64
+ type PluginDescription,
65
+ type PluginParts,
66
+ type QueryDefinition,
67
+ type QueryFile,
68
+ type QueryInput,
69
+ type UpgradeDefinition,
70
+ } from "./plugin/define.js";
71
+ export { PluginDefinitionError } from "./plugin/definition-error.js";
72
+ export * from "./plugin/limits.js";
73
+ export {
74
+ CURRENT_PLUGIN_API,
75
+ isPluginKey,
76
+ type Localized,
77
+ localizedText,
78
+ type ManifestParse,
79
+ PLUGIN_API_MAJORS,
80
+ PLUGIN_BOARD_NEEDS,
81
+ PLUGIN_KEY_PATTERN,
82
+ PLUGIN_MENU_GROUPS,
83
+ PLUGIN_PAGE_LEVELS,
84
+ PLUGIN_SETTING_TYPES,
85
+ PLUGIN_WIDGET_PLACES,
86
+ PLUGIN_WIDGET_SIZES,
87
+ type PluginBoard,
88
+ type PluginBoardNeeds,
89
+ type PluginManifest,
90
+ type PluginMenu,
91
+ type PluginMenuGroup,
92
+ type PluginPage,
93
+ type PluginPageLevel,
94
+ type PluginRole,
95
+ type PluginSetting,
96
+ type PluginSettingType,
97
+ type PluginWidget,
98
+ type PluginWidgetPlace,
99
+ type PluginWidgetSize,
100
+ parsePluginManifest,
101
+ pluginManifestSchema,
102
+ RESERVED_COMMAND_NAMES,
103
+ RESERVED_PAGE_KEYS,
104
+ RESERVED_PLUGIN_KEYS,
105
+ SETTING_KEY_PATTERN,
106
+ } from "./plugin/manifest.js";
107
+ export {
108
+ isPluginError,
109
+ isPluginRefusal,
110
+ ownRefusalCode,
111
+ PLUGIN_OWN_REFUSAL_STATUS,
112
+ PLUGIN_REFUSALS,
113
+ PluginError,
114
+ PluginRefusal,
115
+ type PluginRefusalCode,
116
+ } from "./plugin/refusals.js";
117
+ export {
118
+ FORBIDDEN_BUILTINS,
119
+ forbiddenImportsIn,
120
+ forbiddingResolve,
121
+ type HardenedThread,
122
+ hardenThread,
123
+ isForbiddenBuiltin,
124
+ REMOVED_GLOBALS,
125
+ removedGlobalsIn,
126
+ } from "./plugin/sandbox.js";
package/src/router.ts CHANGED
@@ -121,6 +121,24 @@ export type Route =
121
121
  readonly project: string;
122
122
  readonly page: string;
123
123
  }
124
+ /** A plugin's page (docs/specs/plugins.md, "Tabs, sub-tabs and addresses"): the first when the address names none; `rest` is what follows the page, handed to the frame. */
125
+ | {
126
+ readonly name: "plugin";
127
+ readonly level: "workspace";
128
+ readonly plugin: string;
129
+ readonly page: string | undefined;
130
+ readonly rest: string;
131
+ }
132
+ | {
133
+ readonly name: "plugin";
134
+ readonly level: "project";
135
+ readonly project: string;
136
+ readonly plugin: string;
137
+ readonly page: string | undefined;
138
+ readonly rest: string;
139
+ }
140
+ /** The plugins' settings, for an administrator: the list, or one plugin by its key. */
141
+ | { readonly name: "plugins-settings"; readonly plugin: string | undefined }
124
142
  | { readonly name: "not-found" };
125
143
 
126
144
  /** The pages of a project, after its key. */
@@ -158,12 +176,34 @@ export const PATHS = {
158
176
  settings: "/settings",
159
177
  /** Where the pages a console adds of its own are: `/pages/<key>`, and `/projects/<key>/pages/<page>` on a project. */
160
178
  pages: "/pages",
179
+ /** Where the plugins' pages are: `/plugins/<key>[/<page>[/<rest>]]`, and `/projects/<key>/plugins/<key>...` on a project (ADR-0054). */
180
+ plugins: "/plugins",
181
+ /** The plugins' settings, for an administrator: the list, and `/settings/plugins/<key>` for one. */
182
+ pluginSettings: "/settings/plugins",
161
183
  /** Where an agent's connection is approved (ADR-0011): `/connect/<code>`, or the code typed. */
162
184
  connect: "/connect",
163
185
  } as const;
164
186
 
165
187
  const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
166
188
  const PROJECT_KEY = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
189
+ /** A plugin's key, and a page's: as the manifest spells them. */
190
+ const PLUGIN_KEY = /^[a-z][a-z0-9-]{1,31}$/;
191
+
192
+ /** A plugin's address after its key: the page, if any, and what follows it for the frame. */
193
+ function pluginRouteOf(
194
+ segments: readonly string[],
195
+ ):
196
+ | { readonly plugin: string; readonly page: string | undefined; readonly rest: string }
197
+ | undefined {
198
+ const [plugin, page, ...rest] = segments;
199
+ if (plugin === undefined || !PLUGIN_KEY.test(plugin)) {
200
+ return undefined;
201
+ }
202
+ if (page !== undefined && !PLUGIN_KEY.test(page)) {
203
+ return undefined;
204
+ }
205
+ return { plugin, page, rest: rest.length === 0 ? "" : `/${rest.join("/")}` };
206
+ }
167
207
  const NUMBER = /^[1-9][0-9]{0,8}$/;
168
208
  /** A code as it may be typed into an address: checked for what it is by the page. */
169
209
  const CODE_TEXT = /^[A-Za-z0-9-]{1,16}$/;
@@ -268,6 +308,15 @@ export function matchRoute(pathname: string, search = ""): Route {
268
308
  if (path === PATHS.categories) {
269
309
  return { name: "categories" };
270
310
  }
311
+ if (path === PATHS.pluginSettings) {
312
+ return { name: "plugins-settings", plugin: undefined };
313
+ }
314
+ if (path.startsWith(`${PATHS.pluginSettings}/`)) {
315
+ const [plugin, ...more] = path.slice(PATHS.pluginSettings.length + 1).split("/");
316
+ return plugin !== undefined && PLUGIN_KEY.test(plugin) && more.length === 0
317
+ ? { name: "plugins-settings", plugin }
318
+ : NOT_FOUND;
319
+ }
271
320
  if (path === PATHS.settings) {
272
321
  return {
273
322
  name: "workspace-settings",
@@ -307,6 +356,10 @@ export function matchRoute(pathname: string, search = ""): Route {
307
356
  ? { name: "custom", level: "workspace", page }
308
357
  : NOT_FOUND;
309
358
  }
359
+ if (path.startsWith(`${PATHS.plugins}/`)) {
360
+ const found = pluginRouteOf(path.slice(PATHS.plugins.length + 1).split("/"));
361
+ return found === undefined ? NOT_FOUND : { name: "plugin", level: "workspace", ...found };
362
+ }
310
363
  if (!path.startsWith(`${PATHS.project}/`)) {
311
364
  return NOT_FOUND;
312
365
  }
@@ -331,6 +384,12 @@ export function matchRoute(pathname: string, search = ""): Route {
331
384
  ? { name: "custom", level: "project", project, page: third }
332
385
  : NOT_FOUND;
333
386
  }
387
+ if (page === "plugins") {
388
+ const found = pluginRouteOf([third, ...rest].filter((segment) => segment !== undefined));
389
+ return found === undefined
390
+ ? NOT_FOUND
391
+ : { name: "plugin", level: "project", project, ...found };
392
+ }
334
393
  if (rest.length > 0) {
335
394
  return NOT_FOUND;
336
395
  }
@@ -526,6 +585,20 @@ export function customPageHref(page: string, project?: string): string {
526
585
  return project === undefined ? `${PATHS.pages}/${page}` : `${projectHref(project)}/pages/${page}`;
527
586
  }
528
587
 
588
+ /** Where a plugin's page is (ADR-0054): its first page, or the one named, with what follows it; on a project when its key is given. */
589
+ export function pluginHref(plugin: string, page?: string, project?: string, rest = ""): string {
590
+ const base =
591
+ project === undefined
592
+ ? `${PATHS.plugins}/${plugin}`
593
+ : `${projectHref(project)}/plugins/${plugin}`;
594
+ return page === undefined ? base : `${base}/${page}${rest}`;
595
+ }
596
+
597
+ /** Where the plugins' settings are, or one plugin's. */
598
+ export function pluginSettingsHref(plugin?: string): string {
599
+ return plugin === undefined ? PATHS.pluginSettings : `${PATHS.pluginSettings}/${plugin}`;
600
+ }
601
+
529
602
  /** Where a goal is set: the form. */
530
603
  /** Where a project's roadmap is, from a month on, or from this one when none is named. */
531
604
  export function roadmapHref(key: string, from?: string): string {
package/src/routes.ts CHANGED
@@ -9,6 +9,8 @@ export const REST_ROUTES = {
9
9
  me: "/api/v1/me",
10
10
  /** The token a request is made with, for it to give itself up. */
11
11
  meToken: "/api/v1/me/token",
12
+ /** A picture from elsewhere, fetched by the console for a page (ADR-0048); `?src=` names it. */
13
+ pictures: "/api/v1/pictures",
12
14
  /** The workspace's settings (ADR-0035), changed by an administrator; read through `me`. */
13
15
  workspace: "/api/v1/workspace",
14
16
  /** The SkillCDN token the organization's pack is read with (ADR-0036), an administrator's; `/connect` under it connects one with a code. */
@@ -33,8 +35,15 @@ export const REST_ROUTES = {
33
35
  decisions: "/api/v1/decisions",
34
36
  /** The rules of the board (ADR-0023): the console's own until an administrator writes the organization's. */
35
37
  rules: "/api/v1/rules",
38
+ /** The plugins (ADR-0049): the ones a member may know of, and under each key the plugin's own routes. */
39
+ plugins: "/api/v1/plugins",
36
40
  } as const;
37
41
 
42
+ /** The REST path of one plugin, by its key, and of what is under it. */
43
+ export function pluginPath(key: string, ...parts: readonly string[]): string {
44
+ return [REST_ROUTES.plugins, encodeURIComponent(key), ...parts.map(encodeURIComponent)].join("/");
45
+ }
46
+
38
47
  /** The REST path of the workspace's rules put away, or of their versions. */
39
48
  export function rulesPath(part?: "archive" | "versions"): string {
40
49
  return part === undefined ? REST_ROUTES.rules : `${REST_ROUTES.rules}/${part}`;
package/src/schemas.ts CHANGED
@@ -55,6 +55,7 @@ import {
55
55
  PEOPLE_VISIBILITIES,
56
56
  PERSON_ROLES,
57
57
  PERSON_STATUSES,
58
+ PLUGIN_COMMAND_OUTCOMES,
58
59
  PROJECT_ICON_TYPES,
59
60
  PROJECT_ROLES,
60
61
  PROJECT_VISIBILITIES,
@@ -167,6 +168,18 @@ export const restProviderSchema = z.object({
167
168
  key: z.enum(PROVIDER_KEYS),
168
169
  /** What people read on the button. */
169
170
  label: z.string(),
171
+ /**
172
+ * Who this way in lets in, for the line under the button: the organization at the git host
173
+ * whose members are in, the Workspace domains whose accounts are, or neither, where only the
174
+ * logins an administrator listed get in. Answered from 0.4.1; read as optional, so that a
175
+ * console built on this package reads an older console's answer.
176
+ */
177
+ admits: z.optional(
178
+ z.object({
179
+ organization: z.nullable(z.string()),
180
+ domains: z.array(z.string()),
181
+ }),
182
+ ),
170
183
  });
171
184
  export type RestProvider = z.infer<typeof restProviderSchema>;
172
185
 
@@ -483,6 +496,8 @@ export const restTaskSchema = z.object({
483
496
  priority: z.enum(TASK_PRIORITIES),
484
497
  /** Whose task it is: one person, whoever wrote it. */
485
498
  owner: restPersonSchema,
499
+ /** The plugin that made it, by key (ADR-0052), or `null`; left out by a console older than the plugins. */
500
+ plugin: z.optional(z.nullable(z.string())),
486
501
  /** The people at work on it (ADR-0037), in the order they came to it; `[]` while nobody is. */
487
502
  workers: z.array(restPersonSchema),
488
503
  /** The task this one is part of, or `null`. */
@@ -656,6 +671,8 @@ export const restDecisionSchema = z.object({
656
671
  decider: restPersonSchema,
657
672
  /** The run that raised it, as the agent asked, or `null` when a person did. */
658
673
  run: z.nullable(z.object({ id: uuid, agent: z.string() })),
674
+ /** The plugin that raised it, by key (ADR-0052), or `null`; left out by a console older than the plugins. */
675
+ plugin: z.optional(z.nullable(z.string())),
659
676
  /** The answer, with who gave it and when; `null` while the decision waits. */
660
677
  answer: z.nullable(
661
678
  z.object({
@@ -803,6 +820,18 @@ export const restEventDataSchema = z.object({
803
820
  excerpt: z.optional(z.string()),
804
821
  /** For `task.commented`: how many files came with it. */
805
822
  files: z.optional(z.int()),
823
+ /** For `plugin.command`: the command, how it ended, the refusal's code where it was refused, how long it ran, and the arguments, a secret one as `[hidden]`. */
824
+ command: z.optional(z.string()),
825
+ outcome: z.optional(z.enum(PLUGIN_COMMAND_OUTCOMES)),
826
+ code: z.optional(z.string()),
827
+ durationMs: z.optional(z.int()),
828
+ args: z.optional(z.record(z.string(), z.unknown())),
829
+ /** For `plugin.enabled` and `plugin.configured`: the capabilities consented to. */
830
+ capabilities: z.optional(z.array(z.string())),
831
+ /** For `plugin.granted` and `plugin.revoked`: whether the role went to everyone. */
832
+ everyone: z.optional(z.boolean()),
833
+ /** For `plugin.failed`: what went wrong, in words for a person. */
834
+ problem: z.optional(z.string()),
806
835
  });
807
836
  export type RestEventData = z.infer<typeof restEventDataSchema>;
808
837
 
@@ -823,6 +852,8 @@ export const restEventSchema = z.object({
823
852
  documentId: z.nullable(uuid),
824
853
  /** The goal it is about, or `null`. */
825
854
  goalId: z.nullable(uuid),
855
+ /** The plugin that caused it, by key, or `null` (ADR-0052). */
856
+ plugin: z.nullable(z.string()),
826
857
  data: restEventDataSchema,
827
858
  createdAt: instant,
828
859
  });
@@ -1095,9 +1126,10 @@ export const restPackConnectStartedSchema = z.object({
1095
1126
  export type RestPackConnectStarted = z.infer<typeof restPackConnectStartedSchema>;
1096
1127
 
1097
1128
  /**
1098
- * `GET .../pack-token/connect`: how the connection stands. Nothing asked; waiting for the
1099
- * person, with what they were shown; connected, the token kept and the project as it stands; or
1100
- * ended short of a token, and why.
1129
+ * `GET .../pack-token/connect` and `POST .../pack-token/connect/claim`: how the connection
1130
+ * stands. Nothing asked; waiting for the person, with what they were shown; connected, which
1131
+ * only the claim answers (ADR-0046), the token kept and the project as it stands; or ended
1132
+ * short of a token, and why.
1101
1133
  */
1102
1134
  const packConnectNone = z.object({ status: z.literal("none") });
1103
1135
  const packConnectPending = z.object({
@@ -1119,7 +1151,7 @@ export const restPackConnectSchema = z.union([
1119
1151
  ]);
1120
1152
  export type RestPackConnect = z.infer<typeof restPackConnectSchema>;
1121
1153
 
1122
- /** `GET /api/v1/workspace/pack-token/connect`: the same, for the workspace's token, with the workspace as it stands once connected. */
1154
+ /** `GET /api/v1/workspace/pack-token/connect` and `POST .../connect/claim`: the same, for the workspace's token, with the workspace as it stands once connected. */
1123
1155
  export const restWorkspacePackConnectSchema = z.union([
1124
1156
  packConnectNone,
1125
1157
  packConnectPending,
@@ -1180,6 +1212,8 @@ export const restDocumentSummarySchema = z.object({
1180
1212
  /** Who wrote the latest version, and the agent they wrote it through, or `null`. */
1181
1213
  updatedBy: restPersonSchema,
1182
1214
  agent: z.nullable(z.string()),
1215
+ /** The plugin that wrote it, by key (ADR-0052), or `null`; left out by a console older than the plugins. */
1216
+ plugin: z.optional(z.nullable(z.string())),
1183
1217
  /** When the document was archived, or `null` while it is current. */
1184
1218
  archivedAt: z.nullable(instant),
1185
1219
  createdAt: instant,
@@ -1252,6 +1286,21 @@ export const restDocumentInputSchema = z.object({
1252
1286
  });
1253
1287
  export type RestDocumentInput = z.infer<typeof restDocumentInputSchema>;
1254
1288
 
1289
+ /**
1290
+ * A plugin named after the rules (docs/specs/plugins.md, "The command"): one the asker may use,
1291
+ * bound to the project where the rules are a project's; what agents are told of it, in the
1292
+ * manifest's languages, and the asker's roles in it.
1293
+ */
1294
+ export const restRulesPluginSchema = z.object({
1295
+ key: z.string(),
1296
+ name: z.record(z.string(), z.string()),
1297
+ /** The sentence agents read, by language; `null` for the description. */
1298
+ agentNote: z.nullable(z.record(z.string(), z.string())),
1299
+ description: z.record(z.string(), z.string()),
1300
+ roles: z.array(z.string()),
1301
+ });
1302
+ export type RestRulesPlugin = z.infer<typeof restRulesPluginSchema>;
1303
+
1255
1304
  /**
1256
1305
  * `GET /api/v1/rules`, and each half of a project's (ADR-0023): the rules that hold, and where
1257
1306
  * they come from. `reference`: the console's own, since the organization wrote none;
@@ -1263,6 +1312,8 @@ export const restRulesSchema = z.object({
1263
1312
  body: z.nullable(z.string()),
1264
1313
  /** The page they are written on, or `null` for the console's own and for none. */
1265
1314
  page: z.nullable(restDocumentSummarySchema),
1315
+ /** At the workspace: every plugin the asker may use, by key; left out in the halves of a project's answer. */
1316
+ plugins: z.optional(z.array(restRulesPluginSchema)),
1266
1317
  });
1267
1318
  export type RestRules = z.infer<typeof restRulesSchema>;
1268
1319
 
@@ -1270,6 +1321,8 @@ export type RestRules = z.infer<typeof restRulesSchema>;
1270
1321
  export const restProjectRulesSchema = z.object({
1271
1322
  workspace: restRulesSchema,
1272
1323
  project: restRulesSchema,
1324
+ /** The plugins bound to the project, as its board project or on it, that the asker holds a role in. */
1325
+ plugins: z.optional(z.array(restRulesPluginSchema)),
1273
1326
  });
1274
1327
  export type RestProjectRules = z.infer<typeof restProjectRulesSchema>;
1275
1328
 
@@ -1377,3 +1430,6 @@ export const restRunEndInputSchema = z.object({
1377
1430
  summary: z.optional(summary),
1378
1431
  });
1379
1432
  export type RestRunEndInput = z.infer<typeof restRunEndInputSchema>;
1433
+
1434
+ // The plugins' routes (docs/specs/plugins.md, "REST"), beside the board's.
1435
+ export * from "./plugin/rest-schemas.js";