@skillcdn/console 0.4.3 → 0.4.5

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 (268) hide show
  1. package/README.md +6 -6
  2. package/dist/api.d.ts +4 -4
  3. package/dist/api.d.ts.map +1 -1
  4. package/dist/api.js +4 -4
  5. package/dist/api.js.map +1 -1
  6. package/dist/cli/cli.d.ts.map +1 -1
  7. package/dist/cli/cli.js +255 -33
  8. package/dist/cli/cli.js.map +1 -1
  9. package/dist/cli/format.d.ts +20 -5
  10. package/dist/cli/format.d.ts.map +1 -1
  11. package/dist/cli/format.js +98 -26
  12. package/dist/cli/format.js.map +1 -1
  13. package/dist/cli/help.d.ts.map +1 -1
  14. package/dist/cli/help.js +39 -15
  15. package/dist/cli/help.js.map +1 -1
  16. package/dist/cli/plugin-check.d.ts +5 -1
  17. package/dist/cli/plugin-check.d.ts.map +1 -1
  18. package/dist/cli/plugin-check.js +23 -4
  19. package/dist/cli/plugin-check.js.map +1 -1
  20. package/dist/cli/plugin-cli.d.ts.map +1 -1
  21. package/dist/cli/plugin-cli.js +10 -1
  22. package/dist/cli/plugin-cli.js.map +1 -1
  23. package/dist/cli/plugin-init.d.ts +2 -0
  24. package/dist/cli/plugin-init.d.ts.map +1 -1
  25. package/dist/cli/plugin-init.js +6 -0
  26. package/dist/cli/plugin-init.js.map +1 -1
  27. package/dist/client.d.ts +32 -1
  28. package/dist/client.d.ts.map +1 -1
  29. package/dist/client.js +14 -2
  30. package/dist/client.js.map +1 -1
  31. package/dist/compat.js +1 -1
  32. package/dist/components/board.d.ts +8 -0
  33. package/dist/components/board.d.ts.map +1 -1
  34. package/dist/components/board.js +49 -18
  35. package/dist/components/board.js.map +1 -1
  36. package/dist/components/decision-form.d.ts +6 -3
  37. package/dist/components/decision-form.d.ts.map +1 -1
  38. package/dist/components/decision-form.js +24 -18
  39. package/dist/components/decision-form.js.map +1 -1
  40. package/dist/components/decision-list.d.ts +5 -1
  41. package/dist/components/decision-list.d.ts.map +1 -1
  42. package/dist/components/decision-list.js +25 -5
  43. package/dist/components/decision-list.js.map +1 -1
  44. package/dist/components/event-feed.d.ts.map +1 -1
  45. package/dist/components/event-feed.js +34 -8
  46. package/dist/components/event-feed.js.map +1 -1
  47. package/dist/components/goals.d.ts.map +1 -1
  48. package/dist/components/goals.js +2 -2
  49. package/dist/components/goals.js.map +1 -1
  50. package/dist/components/home.d.ts +35 -0
  51. package/dist/components/home.d.ts.map +1 -0
  52. package/dist/components/home.js +326 -0
  53. package/dist/components/home.js.map +1 -0
  54. package/dist/components/my-decisions.d.ts +20 -3
  55. package/dist/components/my-decisions.d.ts.map +1 -1
  56. package/dist/components/my-decisions.js +14 -1
  57. package/dist/components/my-decisions.js.map +1 -1
  58. package/dist/components/pack-connect.d.ts.map +1 -1
  59. package/dist/components/pack-connect.js +5 -4
  60. package/dist/components/pack-connect.js.map +1 -1
  61. package/dist/components/people.d.ts +45 -1
  62. package/dist/components/people.d.ts.map +1 -1
  63. package/dist/components/people.js +125 -4
  64. package/dist/components/people.js.map +1 -1
  65. package/dist/components/picker.d.ts +8 -0
  66. package/dist/components/picker.d.ts.map +1 -1
  67. package/dist/components/picker.js +2 -2
  68. package/dist/components/picker.js.map +1 -1
  69. package/dist/components/plugin-frame.d.ts +3 -13
  70. package/dist/components/plugin-frame.d.ts.map +1 -1
  71. package/dist/components/plugin-frame.js +75 -21
  72. package/dist/components/plugin-frame.js.map +1 -1
  73. package/dist/components/plugin-settings.d.ts +5 -1
  74. package/dist/components/plugin-settings.d.ts.map +1 -1
  75. package/dist/components/plugin-settings.js +283 -45
  76. package/dist/components/plugin-settings.js.map +1 -1
  77. package/dist/components/projects.d.ts +0 -8
  78. package/dist/components/projects.d.ts.map +1 -1
  79. package/dist/components/projects.js +4 -14
  80. package/dist/components/projects.js.map +1 -1
  81. package/dist/components/searches.d.ts +11 -0
  82. package/dist/components/searches.d.ts.map +1 -0
  83. package/dist/components/searches.js +30 -0
  84. package/dist/components/searches.js.map +1 -0
  85. package/dist/components/task-form.d.ts.map +1 -1
  86. package/dist/components/task-form.js +6 -5
  87. package/dist/components/task-form.js.map +1 -1
  88. package/dist/components/task-view.d.ts.map +1 -1
  89. package/dist/components/task-view.js +2 -1
  90. package/dist/components/task-view.js.map +1 -1
  91. package/dist/components/ui.d.ts +16 -0
  92. package/dist/components/ui.d.ts.map +1 -1
  93. package/dist/components/ui.js +15 -2
  94. package/dist/components/ui.js.map +1 -1
  95. package/dist/connect-page.d.ts.map +1 -1
  96. package/dist/connect-page.js +5 -6
  97. package/dist/connect-page.js.map +1 -1
  98. package/dist/console.css +1123 -258
  99. package/dist/console.d.ts +12 -4
  100. package/dist/console.d.ts.map +1 -1
  101. package/dist/console.js +123 -27
  102. package/dist/console.js.map +1 -1
  103. package/dist/data.d.ts +18 -3
  104. package/dist/data.d.ts.map +1 -1
  105. package/dist/data.js +41 -1
  106. package/dist/data.js.map +1 -1
  107. package/dist/docs-page.d.ts.map +1 -1
  108. package/dist/docs-page.js +6 -5
  109. package/dist/docs-page.js.map +1 -1
  110. package/dist/home-tiles.d.ts +92 -0
  111. package/dist/home-tiles.d.ts.map +1 -0
  112. package/dist/home-tiles.js +294 -0
  113. package/dist/home-tiles.js.map +1 -0
  114. package/dist/i18n/en.d.ts +264 -1
  115. package/dist/i18n/en.d.ts.map +1 -1
  116. package/dist/i18n/en.js +260 -1
  117. package/dist/i18n/en.js.map +1 -1
  118. package/dist/i18n/index.d.ts +4 -2
  119. package/dist/i18n/index.d.ts.map +1 -1
  120. package/dist/i18n/index.js +10 -11
  121. package/dist/i18n/index.js.map +1 -1
  122. package/dist/i18n/ko.d.ts.map +1 -1
  123. package/dist/i18n/ko.js +255 -4
  124. package/dist/i18n/ko.js.map +1 -1
  125. package/dist/index.d.ts +7 -5
  126. package/dist/index.d.ts.map +1 -1
  127. package/dist/index.js +7 -5
  128. package/dist/index.js.map +1 -1
  129. package/dist/limits.d.ts +12 -0
  130. package/dist/limits.d.ts.map +1 -1
  131. package/dist/limits.js +12 -0
  132. package/dist/limits.js.map +1 -1
  133. package/dist/plugin/args.d.ts +6 -1
  134. package/dist/plugin/args.d.ts.map +1 -1
  135. package/dist/plugin/args.js +16 -11
  136. package/dist/plugin/args.js.map +1 -1
  137. package/dist/plugin/bridge.d.ts +63 -3
  138. package/dist/plugin/bridge.d.ts.map +1 -1
  139. package/dist/plugin/bridge.js +54 -0
  140. package/dist/plugin/bridge.js.map +1 -1
  141. package/dist/plugin/capabilities.d.ts +7 -1
  142. package/dist/plugin/capabilities.d.ts.map +1 -1
  143. package/dist/plugin/capabilities.js +24 -1
  144. package/dist/plugin/capabilities.js.map +1 -1
  145. package/dist/plugin/context.d.ts +174 -12
  146. package/dist/plugin/context.d.ts.map +1 -1
  147. package/dist/plugin/define.d.ts +14 -1
  148. package/dist/plugin/define.d.ts.map +1 -1
  149. package/dist/plugin/define.js +18 -2
  150. package/dist/plugin/define.js.map +1 -1
  151. package/dist/plugin/limits.d.ts +9 -2
  152. package/dist/plugin/limits.d.ts.map +1 -1
  153. package/dist/plugin/limits.js +9 -2
  154. package/dist/plugin/limits.js.map +1 -1
  155. package/dist/plugin/manifest.d.ts +98 -6
  156. package/dist/plugin/manifest.d.ts.map +1 -1
  157. package/dist/plugin/manifest.js +171 -10
  158. package/dist/plugin/manifest.js.map +1 -1
  159. package/dist/plugin/rest-schemas.d.ts +120 -0
  160. package/dist/plugin/rest-schemas.d.ts.map +1 -1
  161. package/dist/plugin/rest-schemas.js +78 -5
  162. package/dist/plugin/rest-schemas.js.map +1 -1
  163. package/dist/plugin/sandbox.d.ts +4 -3
  164. package/dist/plugin/sandbox.d.ts.map +1 -1
  165. package/dist/plugin/sandbox.js +33 -6
  166. package/dist/plugin/sandbox.js.map +1 -1
  167. package/dist/plugin/semver.d.ts +26 -0
  168. package/dist/plugin/semver.d.ts.map +1 -0
  169. package/dist/plugin/semver.js +76 -0
  170. package/dist/plugin/semver.js.map +1 -0
  171. package/dist/plugin/testing.d.ts +15 -1
  172. package/dist/plugin/testing.d.ts.map +1 -1
  173. package/dist/plugin/testing.js +42 -5
  174. package/dist/plugin/testing.js.map +1 -1
  175. package/dist/plugin/web.d.ts +16 -1
  176. package/dist/plugin/web.d.ts.map +1 -1
  177. package/dist/plugin/web.js +44 -1
  178. package/dist/plugin/web.js.map +1 -1
  179. package/dist/plugin.d.ts +3 -2
  180. package/dist/plugin.d.ts.map +1 -1
  181. package/dist/plugin.js +3 -2
  182. package/dist/plugin.js.map +1 -1
  183. package/dist/router.d.ts +19 -0
  184. package/dist/router.d.ts.map +1 -1
  185. package/dist/router.js +18 -0
  186. package/dist/router.js.map +1 -1
  187. package/dist/routes.d.ts +11 -2
  188. package/dist/routes.d.ts.map +1 -1
  189. package/dist/routes.js +14 -1
  190. package/dist/routes.js.map +1 -1
  191. package/dist/rules.d.ts +2 -2
  192. package/dist/rules.js +3 -3
  193. package/dist/schemas.d.ts +864 -2
  194. package/dist/schemas.d.ts.map +1 -1
  195. package/dist/schemas.js +156 -9
  196. package/dist/schemas.js.map +1 -1
  197. package/dist/use-action.d.ts +8 -2
  198. package/dist/use-action.d.ts.map +1 -1
  199. package/dist/use-action.js +13 -6
  200. package/dist/use-action.js.map +1 -1
  201. package/dist/vocabulary.d.ts +3 -1
  202. package/dist/vocabulary.d.ts.map +1 -1
  203. package/dist/vocabulary.js +9 -0
  204. package/dist/vocabulary.js.map +1 -1
  205. package/docs/specs/cli.md +10 -6
  206. package/docs/specs/plugins.md +83 -62
  207. package/docs/specs/rest.md +34 -16
  208. package/package.json +1 -1
  209. package/skills/building-a-plugin/SKILL.md +15 -12
  210. package/skills/planning-the-board/references/setting-up.md +2 -1
  211. package/skills/working-the-board/SKILL.md +3 -3
  212. package/src/api.ts +23 -0
  213. package/src/cli/cli.ts +323 -30
  214. package/src/cli/format.ts +122 -26
  215. package/src/cli/help.ts +43 -14
  216. package/src/cli/plugin-check.ts +41 -2
  217. package/src/cli/plugin-cli.ts +10 -1
  218. package/src/cli/plugin-init.ts +8 -0
  219. package/src/client.ts +78 -0
  220. package/src/compat.ts +1 -1
  221. package/src/components/board.tsx +86 -45
  222. package/src/components/decision-form.tsx +73 -36
  223. package/src/components/decision-list.tsx +45 -13
  224. package/src/components/event-feed.tsx +40 -7
  225. package/src/components/goals.tsx +4 -1
  226. package/src/components/home.tsx +615 -0
  227. package/src/components/my-decisions.tsx +50 -5
  228. package/src/components/pack-connect.tsx +5 -4
  229. package/src/components/people.tsx +500 -61
  230. package/src/components/picker.tsx +11 -2
  231. package/src/components/plugin-frame.tsx +85 -63
  232. package/src/components/plugin-settings.tsx +735 -185
  233. package/src/components/projects.tsx +14 -69
  234. package/src/components/searches.ts +47 -0
  235. package/src/components/task-form.tsx +23 -28
  236. package/src/components/task-view.tsx +7 -0
  237. package/src/components/ui.tsx +42 -2
  238. package/src/connect-page.tsx +5 -6
  239. package/src/console.tsx +303 -64
  240. package/src/data.ts +62 -3
  241. package/src/docs-page.tsx +6 -5
  242. package/src/home-tiles.ts +438 -0
  243. package/src/i18n/en.ts +274 -0
  244. package/src/i18n/index.ts +17 -14
  245. package/src/i18n/ko.ts +267 -4
  246. package/src/index.ts +18 -5
  247. package/src/limits.ts +12 -0
  248. package/src/plugin/args.ts +16 -11
  249. package/src/plugin/bridge.ts +122 -1
  250. package/src/plugin/capabilities.ts +28 -1
  251. package/src/plugin/context.ts +186 -9
  252. package/src/plugin/define.ts +38 -1
  253. package/src/plugin/limits.ts +9 -2
  254. package/src/plugin/manifest.ts +228 -13
  255. package/src/plugin/rest-schemas.ts +89 -6
  256. package/src/plugin/sandbox.ts +36 -8
  257. package/src/plugin/semver.ts +89 -0
  258. package/src/plugin/testing.ts +63 -6
  259. package/src/plugin/web.ts +66 -0
  260. package/src/plugin.ts +19 -0
  261. package/src/router.ts +25 -0
  262. package/src/routes.ts +17 -2
  263. package/src/rules.ts +3 -3
  264. package/src/schemas.ts +197 -10
  265. package/src/styles/console.css +1123 -258
  266. package/src/use-action.ts +16 -7
  267. package/src/vocabulary.ts +10 -0
  268. package/template/plugin/console-plugin.json +3 -1
package/src/plugin.ts CHANGED
@@ -29,6 +29,7 @@ export {
29
29
  type CapabilityWords,
30
30
  capabilityWords,
31
31
  isPluginCapability,
32
+ OUTBOUND_WEBRTC,
32
33
  outboundAllows,
33
34
  PLUGIN_CAPABILITIES,
34
35
  PLUGIN_CAPABILITY_PREFIXES,
@@ -72,8 +73,11 @@ export { PluginDefinitionError } from "./plugin/definition-error.js";
72
73
  export * from "./plugin/limits.js";
73
74
  export {
74
75
  CURRENT_PLUGIN_API,
76
+ capabilitiesAsked,
77
+ isCalendarDay,
75
78
  isPluginKey,
76
79
  type Localized,
80
+ legacyWidgetSize,
77
81
  localizedText,
78
82
  type ManifestParse,
79
83
  PLUGIN_API_MAJORS,
@@ -83,6 +87,8 @@ export {
83
87
  PLUGIN_PAGE_LEVELS,
84
88
  PLUGIN_SETTING_TYPES,
85
89
  PLUGIN_WIDGET_PLACES,
90
+ PLUGIN_WIDGET_SIZE_CELLS,
91
+ PLUGIN_WIDGET_SIZE_NAMES,
86
92
  PLUGIN_WIDGET_SIZES,
87
93
  type PluginBoard,
88
94
  type PluginBoardNeeds,
@@ -93,16 +99,20 @@ export {
93
99
  type PluginPageLevel,
94
100
  type PluginRole,
95
101
  type PluginSetting,
102
+ type PluginSettingGroup,
96
103
  type PluginSettingType,
97
104
  type PluginWidget,
98
105
  type PluginWidgetPlace,
99
106
  type PluginWidgetSize,
107
+ type PluginWidgetSizeName,
100
108
  parsePluginManifest,
101
109
  pluginManifestSchema,
102
110
  RESERVED_COMMAND_NAMES,
103
111
  RESERVED_PAGE_KEYS,
104
112
  RESERVED_PLUGIN_KEYS,
105
113
  SETTING_KEY_PATTERN,
114
+ TIME_OF_DAY,
115
+ widgetSizesOf,
106
116
  } from "./plugin/manifest.js";
107
117
  export {
108
118
  isPluginError,
@@ -124,3 +134,12 @@ export {
124
134
  REMOVED_GLOBALS,
125
135
  removedGlobalsIn,
126
136
  } from "./plugin/sandbox.js";
137
+ export {
138
+ compareTriples,
139
+ formatTriple,
140
+ lineRangeFrom,
141
+ parseLooseVersion,
142
+ satisfiesRange,
143
+ type Triple,
144
+ versionOfDependency,
145
+ } from "./plugin/semver.js";
package/src/router.ts CHANGED
@@ -96,6 +96,10 @@ export type Route =
96
96
  | { readonly name: "people" }
97
97
  /** The form where an administrator lets someone in by login (ADR-0022). */
98
98
  | { readonly name: "new-listing" }
99
+ /** The teams of the workspace (ADR-0073), a view of the people's page. */
100
+ | { readonly name: "teams" }
101
+ /** The form where an administrator makes a team. */
102
+ | { readonly name: "new-team" }
99
103
  /** The agents of one person, for an administrator. */
100
104
  | { readonly name: "person-agents"; readonly id: string }
101
105
  /** Another person's plate, for whoever oversees them: a day of the week shown at the top, or today's. */
@@ -107,6 +111,8 @@ export type Route =
107
111
  | { readonly name: "work"; readonly week: string | undefined }
108
112
  /** The decisions addressed to the person (ADR-0042), across the projects they may see. */
109
113
  | { readonly name: "my-decisions" }
114
+ /** One decision wherever it is (ADR-0068), for whoever it reaches: in a project they may see or not. */
115
+ | { readonly name: "my-decision"; readonly id: string }
110
116
  /** The categories tasks are sorted into; an administrator keeps them here. */
111
117
  | { readonly name: "categories" }
112
118
  /** Where a person approves an agent's connection, by the code it showed, or types one. */
@@ -166,6 +172,10 @@ export const PATHS = {
166
172
  people: "/people",
167
173
  /** The form where an administrator lets someone in by login. */
168
174
  newListing: "/people/new",
175
+ /** The teams of the workspace, a view of the people's page. */
176
+ teams: "/people/teams",
177
+ /** The form where an administrator makes a team. */
178
+ newTeam: "/people/teams/new",
169
179
  /** The agents of whoever is signed in, which hold their tokens: their own page. */
170
180
  agents: "/agents",
171
181
  /** The form for a token made by hand, for a script or a console of one's own. */
@@ -293,12 +303,22 @@ export function matchRoute(pathname: string, search = ""): Route {
293
303
  if (path === PATHS.decisions) {
294
304
  return { name: "my-decisions" };
295
305
  }
306
+ if (path.startsWith(`${PATHS.decisions}/`)) {
307
+ const id = path.slice(PATHS.decisions.length + 1);
308
+ return UUID.test(id) ? { name: "my-decision", id } : NOT_FOUND;
309
+ }
296
310
  if (path === PATHS.people) {
297
311
  return { name: "people" };
298
312
  }
299
313
  if (path === PATHS.newListing) {
300
314
  return { name: "new-listing" };
301
315
  }
316
+ if (path === PATHS.teams) {
317
+ return { name: "teams" };
318
+ }
319
+ if (path === PATHS.newTeam) {
320
+ return { name: "new-team" };
321
+ }
302
322
  if (path === PATHS.agents) {
303
323
  return { name: "agents" };
304
324
  }
@@ -569,6 +589,11 @@ export function decisionsHref(key: string, page?: number): string {
569
589
  }
570
590
 
571
591
  /** Where the person's own work is, with the week of a day at the top, or this week's when none is named. */
592
+ /** Where one decision is read wherever it is (ADR-0068), by whoever it reaches: a person outside its project too. */
593
+ export function myDecisionHref(id: string): string {
594
+ return `${PATHS.decisions}/${id}`;
595
+ }
596
+
572
597
  export function workHref(week?: string): string {
573
598
  return week === undefined ? PATHS.work : `${PATHS.work}?week=${week}`;
574
599
  }
package/src/routes.ts CHANGED
@@ -17,6 +17,8 @@ export const REST_ROUTES = {
17
17
  workspacePackToken: "/api/v1/workspace/pack-token",
18
18
  /** The people of the workspace: everyone who has signed in, and the logins let in that have not. */
19
19
  people: "/api/v1/people",
20
+ /** The teams of the workspace (ADR-0073): a name and its members, kept by an administrator. */
21
+ teams: "/api/v1/teams",
20
22
  /** The logins an administrator let in (ADR-0022), made and removed by one. */
21
23
  listings: "/api/v1/listings",
22
24
  /** The projects the asker may see; the board of each is under its key. */
@@ -68,6 +70,19 @@ export function personWorkPath(personId: string): string {
68
70
  return `${restPath("people", personId)}/work`;
69
71
  }
70
72
 
73
+ /** The REST path of one decision wherever it is (ADR-0068), by its id; `/answer` under it answers. */
74
+ export function decisionPath(id: string): string {
75
+ return `${REST_ROUTES.decisions}/${encodeURIComponent(id)}`;
76
+ }
77
+
78
+ /**
79
+ * The REST path of a file put on a decision (ADR-0055), read at the decision's own address, for
80
+ * whoever the decision reaches wherever it is (ADR-0068), in a project they may see or not.
81
+ */
82
+ export function decisionFilePath(decisionId: string, fileId: string): string {
83
+ return `${decisionPath(decisionId)}/files/${encodeURIComponent(fileId)}`;
84
+ }
85
+
71
86
  /** The REST path of a person's tokens, or of one of them: for an administrator. */
72
87
  export function personTokensPath(personId: string, tokenId?: string): string {
73
88
  const base = `${restPath("people", personId)}/tokens`;
@@ -126,9 +141,9 @@ export function signInPath(page: string, failure: SignInFailure): string {
126
141
  return `${page}${page.includes("?") ? "&" : "?"}${SIGN_IN_PARAM}=${failure}`;
127
142
  }
128
143
 
129
- /** The REST path of one person, listing, token or project: the collection, then the id or the key. */
144
+ /** The REST path of one person, listing, token, project or team: the collection, then the id or the key. */
130
145
  export function restPath(
131
- collection: "people" | "listings" | "tokens" | "projects",
146
+ collection: "people" | "listings" | "tokens" | "projects" | "teams",
132
147
  id: string,
133
148
  ): string {
134
149
  return `${REST_ROUTES[collection]}/${encodeURIComponent(id)}`;
package/src/rules.ts CHANGED
@@ -83,7 +83,7 @@ export function isReferenceRules(body: string): boolean {
83
83
  /** What stands in the rules for the language of the person the agent works for. */
84
84
  export const RULES_LANGUAGE_PLACEHOLDER = "{language}";
85
85
 
86
- /** What the rules say when the person chose no language: the task's, as the people of the board wrote it. */
86
+ /** What the rules say for a person with no language yet: the task's, as the people of the board wrote it. */
87
87
  const TASKS_LANGUAGE = "the language the task is written in";
88
88
 
89
89
  /** The name of a language in English, from its tag (`ko` is Korean); the tag itself when it is not one. */
@@ -101,8 +101,8 @@ export function languageNameOf(tag: string): string {
101
101
 
102
102
  /**
103
103
  * The rules as they read for a person: `{language}` filled with the name of the language they
104
- * chose for the pages, or with the task's language when they chose none. The command fills
105
- * them for the person whose token it holds; the pages for whoever reads them.
104
+ * read in (ADR-0065), or with the task's language while they have none. The command fills them
105
+ * for the person whose token it holds; the pages for whoever reads them.
106
106
  */
107
107
  export function fillRules(body: string, language: string | null | undefined): string {
108
108
  const name = language == null ? TASKS_LANGUAGE : languageNameOf(language);
package/src/schemas.ts CHANGED
@@ -16,9 +16,12 @@ import {
16
16
  MAX_BODY_LENGTH,
17
17
  MAX_CATEGORY_KEY_LENGTH,
18
18
  MAX_CATEGORY_NAME_LENGTH,
19
+ MAX_DECIDERS,
19
20
  MAX_DOCUMENT_LENGTH,
20
21
  MAX_DOCUMENT_PATH_LENGTH,
21
22
  MAX_FILE_NAME_LENGTH,
23
+ MAX_HOME_ROW,
24
+ MAX_HOME_TILES,
22
25
  MAX_LANGUAGE_TAG_LENGTH,
23
26
  MAX_LINK_LABEL_LENGTH,
24
27
  MAX_LINKS,
@@ -35,6 +38,8 @@ import {
35
38
  MAX_SECRET_LENGTH,
36
39
  MAX_SKILLS_ADDRESS_LENGTH,
37
40
  MAX_SUMMARY_LENGTH,
41
+ MAX_TEAM_KEY_LENGTH,
42
+ MAX_TEAM_NAME_LENGTH,
38
43
  MAX_TITLE_LENGTH,
39
44
  MAX_TOKEN_DAYS,
40
45
  MAX_TOKEN_NAME_LENGTH,
@@ -42,6 +47,7 @@ import {
42
47
  MAX_WORKERS,
43
48
  MIN_OPTIONS,
44
49
  } from "./limits.js";
50
+ import { PLUGIN_WIDGET_SIZE_NAMES } from "./plugin/manifest.js";
45
51
  import { hasForbiddenCodePoint } from "./text.js";
46
52
  import {
47
53
  ARTIFACT_KINDS,
@@ -100,6 +106,14 @@ const day = z.iso.date();
100
106
  const count = z.int().check(z.nonnegative());
101
107
 
102
108
  /** A person of the workspace, as the pages show them. Nothing here is a secret. */
109
+ /** A language tag as a browser sends one (`en`, `ko-KR`). */
110
+ const languageTag = z
111
+ .string()
112
+ .check(
113
+ z.maxLength(MAX_LANGUAGE_TAG_LENGTH),
114
+ z.regex(/^[A-Za-z]{2,8}(?:-[A-Za-z0-9]{1,8})*$/, "must be a language tag"),
115
+ );
116
+
103
117
  export const restPersonSchema = z.object({
104
118
  id: uuid,
105
119
  /** What the account is called at its provider: a login at the git host, an address at Google. */
@@ -116,6 +130,28 @@ export const restPersonSchema = z.object({
116
130
  source: z.enum(MEMBERSHIP_SOURCES),
117
131
  /** When they were deactivated, or `null`. */
118
132
  deactivatedAt: z.nullable(instant),
133
+ /**
134
+ * The id of the person they report to, the reporting line of the directory an administrator
135
+ * keeps, or `null` for nobody; what a plugin reads as the default approver, the default
136
+ * assignee, in place of a line of its own. Answered from 0.4.4 and read as optional, so that
137
+ * a console built on this package still reads an older console's people.
138
+ */
139
+ managerId: z.optional(z.nullable(uuid)),
140
+ /** The teams the person is in (ADR-0073), by their keys (ADR-0074): on the people listing and to a plugin, from 0.4.5, and read as optional. */
141
+ teams: z.optional(z.array(z.string())),
142
+ /**
143
+ * The language the person reads in (ADR-0065), a tag: the one they chose, else the one the pages
144
+ * first saw them in; `null` until they have opened the pages. What a plugin or an agent writes
145
+ * for them in. Answered from 0.4.4 and read as optional, as `managerId` is.
146
+ */
147
+ language: z.optional(z.nullable(languageTag)),
148
+ /**
149
+ * The person's work email, lowercase: the address they sign in with at Google, else what an
150
+ * administrator wrote; `null` until known. Answered to an administrator and to the person
151
+ * themselves alone, and left out everywhere else, so that a task's owner or a comment's author
152
+ * carries none. Answered from 0.4.5 and read as optional.
153
+ */
154
+ email: z.optional(z.nullable(z.string())),
119
155
  });
120
156
  export type RestPerson = z.infer<typeof restPersonSchema>;
121
157
 
@@ -163,6 +199,47 @@ export const restListingInputSchema = z
163
199
  .check(z.refine((input) => isLoginAt(input.host, input.login), "must be a login at the host"));
164
200
  export type RestListingInput = z.infer<typeof restListingInputSchema>;
165
201
 
202
+ /**
203
+ * A team's key (ADR-0074): what its addresses, a grant, a plugin and the command call it. A
204
+ * project key's shape, one name among the teams' keys and the projects' keys of a workspace;
205
+ * immutable once the team is made.
206
+ */
207
+ const teamKey = z.string().check(
208
+ z.maxLength(MAX_TEAM_KEY_LENGTH),
209
+ z.regex(/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/, "must be lowercase letters, digits and hyphens"),
210
+ z.refine((key) => key !== "new", "is a word the pages reserve"),
211
+ );
212
+
213
+ /** A team of the workspace (ADR-0073): its key, its name and who is in it, among the people the asker may see. */
214
+ export const restTeamSchema = z.object({
215
+ id: uuid,
216
+ key: z.string(),
217
+ name: z.string(),
218
+ memberIds: z.array(uuid),
219
+ createdAt: instant,
220
+ });
221
+ export type RestTeam = z.infer<typeof restTeamSchema>;
222
+
223
+ export const restTeamsSchema = z.object({ items: z.array(restTeamSchema) });
224
+ export type RestTeams = z.infer<typeof restTeamsSchema>;
225
+
226
+ /** What `POST /api/v1/teams` is sent: the key, which stays, and the name. */
227
+ export const restTeamInputSchema = z.object({
228
+ key: teamKey,
229
+ name: line(MAX_TEAM_NAME_LENGTH),
230
+ });
231
+ export type RestTeamInput = z.infer<typeof restTeamInputSchema>;
232
+
233
+ /** What `PATCH /api/v1/teams/<key>` is sent: the name; the key never changes. */
234
+ export const restTeamPatchSchema = z.object({
235
+ name: line(MAX_TEAM_NAME_LENGTH),
236
+ });
237
+ export type RestTeamPatch = z.infer<typeof restTeamPatchSchema>;
238
+
239
+ /** What `POST /api/v1/teams/<key>/members` is sent. */
240
+ export const restTeamMemberInputSchema = z.object({ personId: uuid });
241
+ export type RestTeamMemberInput = z.infer<typeof restTeamMemberInputSchema>;
242
+
166
243
  /** An identity provider people may sign in through, as the pages offer it. */
167
244
  export const restProviderSchema = z.object({
168
245
  key: z.enum(PROVIDER_KEYS),
@@ -195,16 +272,59 @@ export const timeZoneName = z
195
272
  z.regex(/^[A-Za-z0-9_+-]+(?:\/[A-Za-z0-9_+-]+)*$/, "must be a time zone name"),
196
273
  );
197
274
 
198
- /** A language tag as a browser sends one (`en`, `ko-KR`): what the pages speak, by the person's choice. */
199
- const languageTag = z
275
+ /** What `PATCH /api/v1/me` is sent: the language the person chose, or `null` to choose none. */
276
+ /** The sizes of a tile on the front page (ADR-0061): a project's icon, and the widgets' family. */
277
+ export const HOME_TILE_SIZES = ["icon", ...PLUGIN_WIDGET_SIZE_NAMES] as const;
278
+
279
+ /** A tile by what it is: a project by its id, a widget by its plugin's key and its own. */
280
+ const homeTileId = z
200
281
  .string()
201
282
  .check(
202
- z.maxLength(MAX_LANGUAGE_TAG_LENGTH),
203
- z.regex(/^[A-Za-z]{2,8}(?:-[A-Za-z0-9]{1,8})*$/, "must be a language tag"),
283
+ z.regex(
284
+ /^(?:project:[0-9a-f-]{36}|widget:[a-z][a-z0-9-]{0,31}:[a-z][a-z0-9-]{0,31})$/,
285
+ "must name a project or a widget",
286
+ ),
204
287
  );
205
288
 
206
- /** What `PATCH /api/v1/me` is sent: the language the person chose, or `null` to choose none. */
207
- export const restMePatchSchema = z.object({ language: z.nullable(languageTag) });
289
+ /** One tile of a person's own front page, at a place of the grid and at a size. */
290
+ export const restHomeTileSchema = z.object({
291
+ tile: homeTileId,
292
+ x: z.int().check(z.gte(0), z.lte(11)),
293
+ y: z.int().check(z.gte(0), z.lte(MAX_HOME_ROW)),
294
+ size: z.enum(HOME_TILE_SIZES),
295
+ });
296
+ export type RestHomeTile = z.infer<typeof restHomeTileSchema>;
297
+
298
+ const homeLayoutSchema = z.array(restHomeTileSchema).check(z.maxLength(MAX_HOME_TILES));
299
+
300
+ /**
301
+ * A person's own front page (ADR-0061): the tiles they took off it, which stay off, and what
302
+ * they arranged at each width of the grid, by its columns; what they have not seen yet takes
303
+ * the first room.
304
+ */
305
+ export const restHomeSchema = z.object({
306
+ hidden: z.array(homeTileId).check(z.maxLength(MAX_HOME_TILES)),
307
+ layouts: z.object({
308
+ 12: z.optional(homeLayoutSchema),
309
+ 8: z.optional(homeLayoutSchema),
310
+ 6: z.optional(homeLayoutSchema),
311
+ 4: z.optional(homeLayoutSchema),
312
+ }),
313
+ });
314
+ export type RestHome = z.infer<typeof restHomeSchema>;
315
+
316
+ /** What `PATCH /api/v1/me` is sent: the language, the front page, either or both; `null` lets the console choose. */
317
+ export const restMePatchSchema = z
318
+ .object({
319
+ language: z.optional(z.nullable(languageTag)),
320
+ home: z.optional(z.nullable(restHomeSchema)),
321
+ })
322
+ .check(
323
+ z.refine(
324
+ (patch) => patch.language !== undefined || patch.home !== undefined,
325
+ "must name a language or the front page",
326
+ ),
327
+ );
208
328
  export type RestMePatch = z.infer<typeof restMePatchSchema>;
209
329
 
210
330
  /**
@@ -274,8 +394,13 @@ export const restMeSchema = z.object({
274
394
  * person's own knows it holds one. `null` on a session, and for nobody.
275
395
  */
276
396
  agent: z.nullable(z.string()),
277
- /** The language the person chose for the pages (ADR-0012), or `null` for the browser's. */
397
+ /** The language the person reads in (ADR-0065): the one they chose, else the one the pages first saw them in; `null` until then. */
278
398
  language: z.nullable(languageTag),
399
+ /**
400
+ * The person's own front page (ADR-0061), or `null` while they have arranged nothing; answered
401
+ * from 0.4.4 and read as optional.
402
+ */
403
+ home: z.optional(z.nullable(restHomeSchema)),
279
404
  signIn: z.array(restProviderSchema),
280
405
  /**
281
406
  * The console's version and the range of command versions it takes, as npm spells one
@@ -313,11 +438,19 @@ export const restPersonPatchSchema = z
313
438
  .object({
314
439
  role: z.optional(z.enum(PERSON_ROLES)),
315
440
  status: z.optional(z.enum(PERSON_STATUSES)),
441
+ /** Whom the person reports to: another active person of the workspace, or `null` for nobody. */
442
+ managerId: z.optional(z.nullable(uuid)),
443
+ /** The person's work email, one per workspace, or `null` for none; an administrator's to write. */
444
+ email: z.optional(z.nullable(z.email().check(z.maxLength(254)))),
316
445
  })
317
446
  .check(
318
447
  z.refine(
319
- (patch) => patch.role !== undefined || patch.status !== undefined,
320
- "must name a role or a status",
448
+ (patch) =>
449
+ patch.role !== undefined ||
450
+ patch.status !== undefined ||
451
+ patch.managerId !== undefined ||
452
+ patch.email !== undefined,
453
+ "must name a role, a status, a manager or an email",
321
454
  ),
322
455
  );
323
456
  export type RestPersonPatch = z.infer<typeof restPersonPatchSchema>;
@@ -505,6 +638,8 @@ export const restTaskSchema = z.object({
505
638
  owner: restPersonSchema,
506
639
  /** The plugin that made it, by key (ADR-0052), or `null`; left out by a console older than the plugins. */
507
640
  plugin: z.optional(z.nullable(z.string())),
641
+ /** The agent the task was written through, or `null` when a person wrote it themselves (ADR-0056); the owner may have changed since. Left out by an older console. */
642
+ agent: z.optional(z.nullable(z.string())),
508
643
  /** The people at work on it (ADR-0037), in the order they came to it; `[]` while nobody is. */
509
644
  workers: z.array(restPersonSchema),
510
645
  /** The task this one is part of, or `null`. */
@@ -615,6 +750,8 @@ export const restGoalSchema = z.object({
615
750
  /** The day the goal is meant to be reached by, or `null`. */
616
751
  dueOn: z.nullable(day),
617
752
  createdBy: restPersonSchema,
753
+ /** The agent the goal was set through, or `null` when a person set it themselves (ADR-0056); left out by an older console. */
754
+ agent: z.optional(z.nullable(z.string())),
618
755
  /** The tasks that work towards it, counted by state. */
619
756
  taskCounts: restTaskCountsSchema,
620
757
  createdAt: instant,
@@ -714,8 +851,15 @@ export const restDecisionSchema = z.object({
714
851
  /** The task's number, when there is a task, or `null`. */
715
852
  taskNumber: z.nullable(z.int()),
716
853
  raisedBy: restPersonSchema,
717
- /** Who is to answer (ADR-0042): the raiser, unless another person of the project was named. */
854
+ /** The first of those to answer (ADR-0042): the raiser, unless others of the project were named. */
718
855
  decider: restPersonSchema,
856
+ /**
857
+ * Everyone the decision is addressed to (ADR-0057), `decider` first: each finds it among their
858
+ * decisions, any of them may answer, and the first answer ends it. Answered from 0.4.4 and read
859
+ * as optional, so that a console built on this package still reads an older console's
860
+ * decisions, where it is `[decider]`.
861
+ */
862
+ deciders: z.optional(z.array(restPersonSchema)),
719
863
  /** The run that raised it, as the agent asked, or `null` when a person did. */
720
864
  run: z.nullable(z.object({ id: uuid, agent: z.string() })),
721
865
  /** The plugin that raised it, by key (ADR-0052), or `null`; left out by a console older than the plugins. */
@@ -729,10 +873,24 @@ export const restDecisionSchema = z.object({
729
873
  note: z.nullable(z.string()),
730
874
  by: restPersonSchema,
731
875
  at: instant,
876
+ /**
877
+ * The agent the answer came through, when the person's agent wrote it in their name
878
+ * (`console answer`, ADR-0021), or `null` when they answered themselves (ADR-0056).
879
+ * Answered from 0.4.4 and read as optional, so that a console built on this package still
880
+ * reads an older console's decisions.
881
+ */
882
+ agent: z.optional(z.nullable(z.string())),
732
883
  }),
733
884
  ),
734
885
  /** What followed the decision, in Markdown, written afterwards; `null` until someone does. */
735
886
  outcome: z.nullable(z.string()),
887
+ /**
888
+ * Who wrote what followed, the agent they wrote it through (`null` when themselves) and when
889
+ * (ADR-0056); each `null` until someone does. Answered from 0.4.4 and read as optional.
890
+ */
891
+ outcomeBy: z.optional(z.nullable(restPersonSchema)),
892
+ outcomeAgent: z.optional(z.nullable(z.string())),
893
+ outcomeAt: z.optional(z.nullable(instant)),
736
894
  /**
737
895
  * The files put on it when it was raised (ADR-0055), in the order they came; a picture among
738
896
  * them is shown where the context names it as `![words](its name)`, else after it. Answered
@@ -785,6 +943,18 @@ export const restMyDecisionsSchema = z.object({
785
943
  });
786
944
  export type RestMyDecisions = z.infer<typeof restMyDecisionsSchema>;
787
945
 
946
+ /**
947
+ * `GET /api/v1/decisions/<id>`: one decision wherever it is (ADR-0068), in a project the asker
948
+ * may see or one that reaches them from elsewhere, with its project and whether they may answer
949
+ * it (`mayAnswer`, read as optional).
950
+ */
951
+ export const restReachedDecisionSchema = z.object({
952
+ project: projectRef,
953
+ decision: restDecisionSchema,
954
+ mayAnswer: z.optional(z.boolean()),
955
+ });
956
+ export type RestReachedDecision = z.infer<typeof restReachedDecisionSchema>;
957
+
788
958
  /**
789
959
  * What `GET /api/v1/people/<id>/work` answers: another person's open tasks, and their closed
790
960
  * ones for the week, within the projects the asker may see, for whoever oversees them. No
@@ -820,6 +990,11 @@ export const restDecisionInputSchema = z.object({
820
990
  runId: z.optional(z.nullable(uuid)),
821
991
  /** Who is to answer (ADR-0042): a person who may work in the project; the asker when left out. */
822
992
  deciderId: z.optional(uuid),
993
+ /**
994
+ * Several to answer (ADR-0057), in place of `deciderId`: each a person who may work in the
995
+ * project, up to `MAX_DECIDERS`; any of them may answer, and the first answer ends the decision.
996
+ */
997
+ deciderIds: z.optional(z.array(uuid).check(z.minLength(1), z.maxLength(MAX_DECIDERS))),
823
998
  });
824
999
  export type RestDecisionInput = z.infer<typeof restDecisionInputSchema>;
825
1000
 
@@ -873,6 +1048,12 @@ export const restEventDataSchema = z.object({
873
1048
  /** For `person.role_changed` and the events about a project's members: whose role, and what it became. */
874
1049
  login: z.optional(z.string()),
875
1050
  role: z.optional(z.string()),
1051
+ /** For `person.manager_changed`: the login of whom the person reports to now, or `null` for nobody. */
1052
+ manager: z.optional(z.nullable(z.string())),
1053
+ /** For the events about a team (ADR-0073), and for a role granted to one: its name; `team.renamed` holds the name before in `name`, and each event of a team its `key` (ADR-0074). */
1054
+ team: z.optional(z.string()),
1055
+ /** For `person.email_changed`: whether the person has an address now; never the address itself. */
1056
+ set: z.optional(z.boolean()),
876
1057
  /** For the events about a project: its key and its name. */
877
1058
  key: z.optional(z.string()),
878
1059
  name: z.optional(z.string()),
@@ -895,6 +1076,10 @@ export const restEventDataSchema = z.object({
895
1076
  args: z.optional(z.record(z.string(), z.unknown())),
896
1077
  /** For `plugin.enabled` and `plugin.configured`: the capabilities consented to. */
897
1078
  capabilities: z.optional(z.array(z.string())),
1079
+ /** For `plugin.configured` of a secret: `administrator`, or the host of the answer it was sealed from (ADR-0070). */
1080
+ source: z.optional(z.string()),
1081
+ /** For `plugin.granted` and `plugin.revoked`: the plugin the role went to, by key, where one did (ADR-0072). */
1082
+ grantee: z.optional(z.string()),
898
1083
  /** For `plugin.granted` and `plugin.revoked`: whether the role went to everyone. */
899
1084
  everyone: z.optional(z.boolean()),
900
1085
  /** For `plugin.failed`: what went wrong, in words for a person. */
@@ -921,6 +1106,8 @@ export const restEventSchema = z.object({
921
1106
  goalId: z.nullable(uuid),
922
1107
  /** The plugin that caused it, by key, or `null` (ADR-0052). */
923
1108
  plugin: z.nullable(z.string()),
1109
+ /** The plugin the person acted through (ADR-0072), by key, when one acted for them; answered from 0.4.5 and read as optional. */
1110
+ via: z.optional(z.nullable(z.string())),
924
1111
  data: restEventDataSchema,
925
1112
  createdAt: instant,
926
1113
  });