@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.
- package/README.md +19 -2
- package/SKILLCDN.md +7 -5
- package/dist/api.d.ts +5 -4
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +5 -4
- package/dist/api.js.map +1 -1
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +569 -48
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/format.d.ts +34 -3
- package/dist/cli/format.d.ts.map +1 -1
- package/dist/cli/format.js +283 -7
- package/dist/cli/format.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +44 -7
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/plugin-check.d.ts +26 -0
- package/dist/cli/plugin-check.d.ts.map +1 -0
- package/dist/cli/plugin-check.js +396 -0
- package/dist/cli/plugin-check.js.map +1 -0
- package/dist/cli/plugin-cli.d.ts +20 -0
- package/dist/cli/plugin-cli.d.ts.map +1 -0
- package/dist/cli/plugin-cli.js +189 -0
- package/dist/cli/plugin-cli.js.map +1 -0
- package/dist/cli/plugin-init.d.ts +37 -0
- package/dist/cli/plugin-init.d.ts.map +1 -0
- package/dist/cli/plugin-init.js +206 -0
- package/dist/cli/plugin-init.js.map +1 -0
- package/dist/cli/plugin-main.d.ts +3 -0
- package/dist/cli/plugin-main.d.ts.map +1 -0
- package/dist/cli/plugin-main.js +28 -0
- package/dist/cli/plugin-main.js.map +1 -0
- package/dist/client.d.ts +100 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +79 -7
- package/dist/client.js.map +1 -1
- package/dist/compat.d.ts +1 -1
- package/dist/compat.js +2 -2
- package/dist/components/board.d.ts +8 -0
- package/dist/components/board.d.ts.map +1 -1
- package/dist/components/board.js +59 -15
- package/dist/components/board.js.map +1 -1
- package/dist/components/comments.d.ts.map +1 -1
- package/dist/components/comments.js +1 -1
- package/dist/components/comments.js.map +1 -1
- package/dist/components/decision-form.d.ts +2 -1
- package/dist/components/decision-form.d.ts.map +1 -1
- package/dist/components/decision-form.js +36 -4
- package/dist/components/decision-form.js.map +1 -1
- package/dist/components/decision-list.d.ts +4 -0
- package/dist/components/decision-list.d.ts.map +1 -1
- package/dist/components/decision-list.js +29 -3
- package/dist/components/decision-list.js.map +1 -1
- package/dist/components/event-feed.d.ts +1 -1
- package/dist/components/event-feed.d.ts.map +1 -1
- package/dist/components/event-feed.js +33 -1
- package/dist/components/event-feed.js.map +1 -1
- package/dist/components/my-decisions.d.ts +2 -0
- package/dist/components/my-decisions.d.ts.map +1 -1
- package/dist/components/my-decisions.js +2 -2
- package/dist/components/my-decisions.js.map +1 -1
- package/dist/components/plugin-frame.d.ts +52 -0
- package/dist/components/plugin-frame.d.ts.map +1 -0
- package/dist/components/plugin-frame.js +314 -0
- package/dist/components/plugin-frame.js.map +1 -0
- package/dist/components/plugin-settings.d.ts +38 -0
- package/dist/components/plugin-settings.d.ts.map +1 -0
- package/dist/components/plugin-settings.js +348 -0
- package/dist/components/plugin-settings.js.map +1 -0
- package/dist/components/shell.d.ts +2 -0
- package/dist/components/shell.d.ts.map +1 -1
- package/dist/components/shell.js +26 -1
- package/dist/components/shell.js.map +1 -1
- package/dist/components/task-view.d.ts +2 -1
- package/dist/components/task-view.d.ts.map +1 -1
- package/dist/components/task-view.js.map +1 -1
- package/dist/components/workspace.d.ts +7 -1
- package/dist/components/workspace.d.ts.map +1 -1
- package/dist/components/workspace.js +1 -1
- package/dist/components/workspace.js.map +1 -1
- package/dist/console.css +330 -1
- package/dist/console.d.ts.map +1 -1
- package/dist/console.js +152 -41
- package/dist/console.js.map +1 -1
- package/dist/data.d.ts +9 -2
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +45 -9
- package/dist/data.js.map +1 -1
- package/dist/i18n/en.d.ts +155 -0
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +166 -0
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/ko.d.ts.map +1 -1
- package/dist/i18n/ko.js +150 -0
- package/dist/i18n/ko.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/limits.d.ts +2 -0
- package/dist/limits.d.ts.map +1 -1
- package/dist/limits.js +2 -0
- package/dist/limits.js.map +1 -1
- package/dist/plugin/args.d.ts +148 -0
- package/dist/plugin/args.d.ts.map +1 -0
- package/dist/plugin/args.js +369 -0
- package/dist/plugin/args.js.map +1 -0
- package/dist/plugin/bridge.d.ts +146 -0
- package/dist/plugin/bridge.d.ts.map +1 -0
- package/dist/plugin/bridge.js +125 -0
- package/dist/plugin/bridge.js.map +1 -0
- package/dist/plugin/capabilities.d.ts +20 -0
- package/dist/plugin/capabilities.d.ts.map +1 -0
- package/dist/plugin/capabilities.js +133 -0
- package/dist/plugin/capabilities.js.map +1 -0
- package/dist/plugin/context.d.ts +380 -0
- package/dist/plugin/context.d.ts.map +1 -0
- package/dist/plugin/context.js +2 -0
- package/dist/plugin/context.js.map +1 -0
- package/dist/plugin/define.d.ts +208 -0
- package/dist/plugin/define.d.ts.map +1 -0
- package/dist/plugin/define.js +482 -0
- package/dist/plugin/define.js.map +1 -0
- package/dist/plugin/definition-error.d.ts +11 -0
- package/dist/plugin/definition-error.d.ts.map +1 -0
- package/dist/plugin/definition-error.js +17 -0
- package/dist/plugin/definition-error.js.map +1 -0
- package/dist/plugin/limits.d.ts +67 -0
- package/dist/plugin/limits.d.ts.map +1 -0
- package/dist/plugin/limits.js +70 -0
- package/dist/plugin/limits.js.map +1 -0
- package/dist/plugin/load-worker.d.ts +7 -0
- package/dist/plugin/load-worker.d.ts.map +1 -0
- package/dist/plugin/load-worker.js +41 -0
- package/dist/plugin/load-worker.js.map +1 -0
- package/dist/plugin/load.d.ts +18 -0
- package/dist/plugin/load.d.ts.map +1 -0
- package/dist/plugin/load.js +62 -0
- package/dist/plugin/load.js.map +1 -0
- package/dist/plugin/manifest.d.ts +237 -0
- package/dist/plugin/manifest.d.ts.map +1 -0
- package/dist/plugin/manifest.js +411 -0
- package/dist/plugin/manifest.js.map +1 -0
- package/dist/plugin/refusals.d.ts +49 -0
- package/dist/plugin/refusals.d.ts.map +1 -0
- package/dist/plugin/refusals.js +79 -0
- package/dist/plugin/refusals.js.map +1 -0
- package/dist/plugin/rest-schemas.d.ts +556 -0
- package/dist/plugin/rest-schemas.d.ts.map +1 -0
- package/dist/plugin/rest-schemas.js +262 -0
- package/dist/plugin/rest-schemas.js.map +1 -0
- package/dist/plugin/sandbox.d.ts +23 -0
- package/dist/plugin/sandbox.d.ts.map +1 -0
- package/dist/plugin/sandbox.js +99 -0
- package/dist/plugin/sandbox.js.map +1 -0
- package/dist/plugin/testing.d.ts +45 -0
- package/dist/plugin/testing.d.ts.map +1 -0
- package/dist/plugin/testing.js +420 -0
- package/dist/plugin/testing.js.map +1 -0
- package/dist/plugin/web-react.d.ts +11 -0
- package/dist/plugin/web-react.d.ts.map +1 -0
- package/dist/plugin/web-react.js +34 -0
- package/dist/plugin/web-react.js.map +1 -0
- package/dist/plugin/web.d.ts +95 -0
- package/dist/plugin/web.d.ts.map +1 -0
- package/dist/plugin/web.js +245 -0
- package/dist/plugin/web.js.map +1 -0
- package/dist/plugin-nav.d.ts +29 -0
- package/dist/plugin-nav.d.ts.map +1 -0
- package/dist/plugin-nav.js +92 -0
- package/dist/plugin-nav.js.map +1 -0
- package/dist/plugin-testing.d.ts +2 -0
- package/dist/plugin-testing.d.ts.map +1 -0
- package/dist/plugin-testing.js +4 -0
- package/dist/plugin-testing.js.map +1 -0
- package/dist/plugin-web-react.d.ts +3 -0
- package/dist/plugin-web-react.d.ts.map +1 -0
- package/dist/plugin-web-react.js +3 -0
- package/dist/plugin-web-react.js.map +1 -0
- package/dist/plugin-web.d.ts +4 -0
- package/dist/plugin-web.d.ts.map +1 -0
- package/dist/plugin-web.js +5 -0
- package/dist/plugin-web.js.map +1 -0
- package/dist/plugin.d.ts +11 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +15 -0
- package/dist/plugin.js.map +1 -0
- package/dist/router.d.ts +28 -0
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +47 -0
- package/dist/router.js.map +1 -1
- package/dist/routes.d.ts +4 -0
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +6 -0
- package/dist/routes.js.map +1 -1
- package/dist/schemas.d.ts +194 -9
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +98 -17
- package/dist/schemas.js.map +1 -1
- package/dist/tokens.d.ts +2 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +101 -0
- package/dist/tokens.js.map +1 -0
- package/dist/vocabulary.d.ts +11 -1
- package/dist/vocabulary.d.ts.map +1 -1
- package/dist/vocabulary.js +24 -0
- package/dist/vocabulary.js.map +1 -1
- package/dist/web.d.ts.map +1 -1
- package/dist/web.js +2 -0
- package/dist/web.js.map +1 -1
- package/docs/specs/cli.md +12 -5
- package/docs/specs/plugins.md +488 -0
- package/docs/specs/rest.md +11 -9
- package/package.json +26 -8
- package/skills/building-a-console/SKILL.md +25 -26
- package/skills/building-a-console/references/configuring.md +40 -0
- package/skills/building-a-console/references/the-default-console.md +1 -1
- package/skills/building-a-console/references/the-look-from-a-website.md +5 -5
- package/skills/building-a-plugin/SKILL.md +137 -0
- package/skills/deploying-a-console/SKILL.md +24 -26
- package/skills/deploying-a-console/references/access.md +13 -9
- package/skills/deploying-a-console/references/resources.md +25 -10
- package/skills/deploying-a-console/references/running-it-again.md +15 -0
- package/skills/deploying-a-console/references/sizing.md +2 -0
- package/skills/planning-the-board/SKILL.md +96 -0
- package/skills/planning-the-board/references/a-task.md +36 -0
- package/skills/planning-the-board/references/setting-up.md +44 -0
- package/skills/working-the-board/SKILL.md +43 -34
- package/skills/working-the-board/references/the-pack.md +19 -0
- package/src/api.ts +12 -0
- package/src/cli/cli.ts +737 -55
- package/src/cli/format.ts +368 -10
- package/src/cli/help.ts +50 -6
- package/src/cli/plugin-check.ts +497 -0
- package/src/cli/plugin-cli.ts +237 -0
- package/src/cli/plugin-init.ts +257 -0
- package/src/cli/plugin-main.ts +30 -0
- package/src/client.ts +322 -9
- package/src/compat.ts +2 -2
- package/src/components/board.tsx +62 -14
- package/src/components/comments.tsx +1 -0
- package/src/components/decision-form.tsx +92 -11
- package/src/components/decision-list.tsx +71 -2
- package/src/components/event-feed.tsx +42 -1
- package/src/components/my-decisions.tsx +4 -1
- package/src/components/plugin-frame.tsx +437 -0
- package/src/components/plugin-settings.tsx +1111 -0
- package/src/components/shell.tsx +82 -14
- package/src/components/task-view.tsx +2 -1
- package/src/components/workspace.tsx +18 -0
- package/src/console.tsx +304 -31
- package/src/data.ts +59 -11
- package/src/i18n/en.ts +175 -0
- package/src/i18n/ko.ts +155 -0
- package/src/index.ts +12 -0
- package/src/limits.ts +2 -0
- package/src/plugin/args.ts +526 -0
- package/src/plugin/bridge.ts +314 -0
- package/src/plugin/capabilities.ts +150 -0
- package/src/plugin/context.ts +421 -0
- package/src/plugin/define.ts +792 -0
- package/src/plugin/definition-error.ts +19 -0
- package/src/plugin/limits.ts +70 -0
- package/src/plugin/load-worker.ts +50 -0
- package/src/plugin/load.ts +82 -0
- package/src/plugin/manifest.ts +561 -0
- package/src/plugin/refusals.ts +94 -0
- package/src/plugin/rest-schemas.ts +354 -0
- package/src/plugin/sandbox.ts +123 -0
- package/src/plugin/testing.ts +612 -0
- package/src/plugin/web-react.ts +45 -0
- package/src/plugin/web.ts +403 -0
- package/src/plugin-nav.ts +132 -0
- package/src/plugin-testing.ts +10 -0
- package/src/plugin-web-react.ts +4 -0
- package/src/plugin-web.ts +35 -0
- package/src/plugin.ts +126 -0
- package/src/router.ts +73 -0
- package/src/routes.ts +7 -0
- package/src/schemas.ts +115 -18
- package/src/styles/console.css +330 -1
- package/src/tokens.ts +101 -0
- package/src/vocabulary.ts +30 -0
- package/src/web.ts +2 -0
- package/template/plugin/.gitignore +2 -0
- package/template/plugin/README.md +26 -0
- package/template/plugin/SKILLCDN.md +13 -0
- package/template/plugin/build.mjs +40 -0
- package/template/plugin/console-plugin.json +50 -0
- package/template/plugin/package.json +27 -0
- package/template/plugin/skills/__key__/SKILL.md +23 -0
- package/template/plugin/src/check.test.ts +34 -0
- package/template/plugin/src/server/index.test.ts +41 -0
- package/template/plugin/src/server/index.ts +72 -0
- package/template/plugin/src/web/index.css +51 -0
- package/template/plugin/src/web/index.ts +115 -0
- package/template/plugin/tsconfig.json +17 -0
- package/skills/working-the-board/references/setting-up.md +0 -3
- /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
|
@@ -35,8 +35,15 @@ export const REST_ROUTES = {
|
|
|
35
35
|
decisions: "/api/v1/decisions",
|
|
36
36
|
/** The rules of the board (ADR-0023): the console's own until an administrator writes the organization's. */
|
|
37
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",
|
|
38
40
|
} as const;
|
|
39
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
|
+
|
|
40
47
|
/** The REST path of the workspace's rules put away, or of their versions. */
|
|
41
48
|
export function rulesPath(part?: "archive" | "versions"): string {
|
|
42
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,
|
|
@@ -283,6 +284,13 @@ export const restMeSchema = z.object({
|
|
|
283
284
|
* built on this package still reads an older console's answer, and says it is older.
|
|
284
285
|
*/
|
|
285
286
|
console: z.optional(z.object({ version: z.string(), clientRange: z.string() })),
|
|
287
|
+
/**
|
|
288
|
+
* How many decisions wait for the person's answer across the projects they may see
|
|
289
|
+
* (ADR-0042), for the pages to say beside My decisions; `null` for nobody. Answered from
|
|
290
|
+
* 0.4.3 and read as optional, so that a console built on this package still reads an older
|
|
291
|
+
* console's answer.
|
|
292
|
+
*/
|
|
293
|
+
decisions: z.optional(z.nullable(z.object({ waiting: count }))),
|
|
286
294
|
});
|
|
287
295
|
export type RestMe = z.infer<typeof restMeSchema>;
|
|
288
296
|
|
|
@@ -495,6 +503,8 @@ export const restTaskSchema = z.object({
|
|
|
495
503
|
priority: z.enum(TASK_PRIORITIES),
|
|
496
504
|
/** Whose task it is: one person, whoever wrote it. */
|
|
497
505
|
owner: restPersonSchema,
|
|
506
|
+
/** The plugin that made it, by key (ADR-0052), or `null`; left out by a console older than the plugins. */
|
|
507
|
+
plugin: z.optional(z.nullable(z.string())),
|
|
498
508
|
/** The people at work on it (ADR-0037), in the order they came to it; `[]` while nobody is. */
|
|
499
509
|
workers: z.array(restPersonSchema),
|
|
500
510
|
/** The task this one is part of, or `null`. */
|
|
@@ -640,10 +650,50 @@ export const restGoalPatchSchema = z.object({
|
|
|
640
650
|
});
|
|
641
651
|
export type RestGoalPatch = z.infer<typeof restGoalPatchSchema>;
|
|
642
652
|
|
|
653
|
+
/** A file a run handed in, as the console keeps it; its bytes are at `projectPath(key, "files", <artifact id>)`. */
|
|
654
|
+
export const restFileSchema = z.object({
|
|
655
|
+
/** What the agent called it: one line, without a path. */
|
|
656
|
+
name: z.string(),
|
|
657
|
+
/** In bytes. */
|
|
658
|
+
size: count,
|
|
659
|
+
/** The media type the agent said, or `application/octet-stream`. */
|
|
660
|
+
contentType: z.string(),
|
|
661
|
+
/** The SHA-256 of the bytes, in hex: what the console keeps them under. */
|
|
662
|
+
sha256: z.string(),
|
|
663
|
+
});
|
|
664
|
+
export type RestFile = z.infer<typeof restFileSchema>;
|
|
665
|
+
|
|
666
|
+
/** A file put on a decision when it was raised (ADR-0055), kept as a run's file is; its bytes are at `projectPath(key, "files", <id>)`. */
|
|
667
|
+
export const restDecisionFileSchema = z.object({
|
|
668
|
+
id: uuid,
|
|
669
|
+
file: restFileSchema,
|
|
670
|
+
});
|
|
671
|
+
export type RestDecisionFile = z.infer<typeof restDecisionFileSchema>;
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* The key a raiser may give an option, for a program to read the answer by instead of
|
|
675
|
+
* comparing labels: spelled as a plugin's key is.
|
|
676
|
+
*/
|
|
677
|
+
export const OPTION_KEY_PATTERN = /^[a-z][a-z0-9-]{1,31}$/;
|
|
678
|
+
const optionKey = z
|
|
679
|
+
.string()
|
|
680
|
+
.check(
|
|
681
|
+
z.regex(
|
|
682
|
+
OPTION_KEY_PATTERN,
|
|
683
|
+
"must be a key: a lowercase letter, then lowercase letters, digits and hyphens, 2 to 32 long",
|
|
684
|
+
),
|
|
685
|
+
);
|
|
686
|
+
|
|
643
687
|
export const restDecisionOptionSchema = z.object({
|
|
644
688
|
/** What an answer names: stable once given. */
|
|
645
689
|
id: z.string(),
|
|
646
690
|
label: z.string(),
|
|
691
|
+
/**
|
|
692
|
+
* The key the raiser gave the option, for a program to read the answer by (`optionKey` on the
|
|
693
|
+
* `decision.answered` event) without comparing labels; none on an option given without one,
|
|
694
|
+
* and none on the person's own answer.
|
|
695
|
+
*/
|
|
696
|
+
key: z.optional(z.string()),
|
|
647
697
|
/**
|
|
648
698
|
* On the one option a person's own answer became, when they answered in their own words
|
|
649
699
|
* instead of choosing (`POST .../answer` with `own`): added then, after the options given,
|
|
@@ -668,6 +718,8 @@ export const restDecisionSchema = z.object({
|
|
|
668
718
|
decider: restPersonSchema,
|
|
669
719
|
/** The run that raised it, as the agent asked, or `null` when a person did. */
|
|
670
720
|
run: z.nullable(z.object({ id: uuid, agent: z.string() })),
|
|
721
|
+
/** The plugin that raised it, by key (ADR-0052), or `null`; left out by a console older than the plugins. */
|
|
722
|
+
plugin: z.optional(z.nullable(z.string())),
|
|
671
723
|
/** The answer, with who gave it and when; `null` while the decision waits. */
|
|
672
724
|
answer: z.nullable(
|
|
673
725
|
z.object({
|
|
@@ -681,6 +733,13 @@ export const restDecisionSchema = z.object({
|
|
|
681
733
|
),
|
|
682
734
|
/** What followed the decision, in Markdown, written afterwards; `null` until someone does. */
|
|
683
735
|
outcome: z.nullable(z.string()),
|
|
736
|
+
/**
|
|
737
|
+
* The files put on it when it was raised (ADR-0055), in the order they came; a picture among
|
|
738
|
+
* them is shown where the context names it as ``, else after it. Answered
|
|
739
|
+
* from 0.4.3 and read as optional, so that a console built on this package still reads an
|
|
740
|
+
* older console's decisions.
|
|
741
|
+
*/
|
|
742
|
+
files: z.optional(z.array(restDecisionFileSchema)),
|
|
684
743
|
createdAt: instant,
|
|
685
744
|
updatedAt: instant,
|
|
686
745
|
});
|
|
@@ -737,13 +796,25 @@ export const restPersonWorkSchema = z.object({
|
|
|
737
796
|
});
|
|
738
797
|
export type RestPersonWork = z.infer<typeof restPersonWorkSchema>;
|
|
739
798
|
|
|
740
|
-
/**
|
|
799
|
+
/**
|
|
800
|
+
* What `POST /api/v1/projects/<key>/decisions` is sent: the question, its context, and the
|
|
801
|
+
* options. As JSON; or, with files put on the decision (ADR-0055), as the part `decision` of a
|
|
802
|
+
* form, with a part `file` for each file.
|
|
803
|
+
*/
|
|
741
804
|
export const restDecisionInputSchema = z.object({
|
|
742
805
|
question: line(MAX_QUESTION_LENGTH),
|
|
743
806
|
body: z.optional(body),
|
|
807
|
+
/** Each a label, and optionally a key a program reads the answer by, each key once. */
|
|
744
808
|
options: z
|
|
745
|
-
.array(z.object({ label: line(MAX_OPTION_LABEL_LENGTH) }))
|
|
746
|
-
.check(
|
|
809
|
+
.array(z.object({ label: line(MAX_OPTION_LABEL_LENGTH), key: z.optional(optionKey) }))
|
|
810
|
+
.check(
|
|
811
|
+
z.minLength(MIN_OPTIONS),
|
|
812
|
+
z.maxLength(MAX_OPTIONS),
|
|
813
|
+
z.refine((options) => {
|
|
814
|
+
const keys = options.flatMap((option) => (option.key === undefined ? [] : [option.key]));
|
|
815
|
+
return new Set(keys).size === keys.length;
|
|
816
|
+
}, "each key once"),
|
|
817
|
+
),
|
|
747
818
|
taskId: z.optional(z.nullable(uuid)),
|
|
748
819
|
/** The run that asks, when an agent does: the decision is about its task, and it waits for the answer. */
|
|
749
820
|
runId: z.optional(z.nullable(uuid)),
|
|
@@ -796,8 +867,9 @@ export const restEventDataSchema = z.object({
|
|
|
796
867
|
from: z.optional(z.enum(TASK_STATES)),
|
|
797
868
|
to: z.optional(z.enum(TASK_STATES)),
|
|
798
869
|
question: z.optional(z.string()),
|
|
799
|
-
/** For `decision.answered`: the label of the chosen option. */
|
|
870
|
+
/** For `decision.answered`: the label of the chosen option, and its key where the raiser gave one. */
|
|
800
871
|
option: z.optional(z.string()),
|
|
872
|
+
optionKey: z.optional(z.string()),
|
|
801
873
|
/** For `person.role_changed` and the events about a project's members: whose role, and what it became. */
|
|
802
874
|
login: z.optional(z.string()),
|
|
803
875
|
role: z.optional(z.string()),
|
|
@@ -813,8 +885,20 @@ export const restEventDataSchema = z.object({
|
|
|
813
885
|
label: z.optional(z.string()),
|
|
814
886
|
/** For `run.reported` and `task.commented`: the first words of what was written. */
|
|
815
887
|
excerpt: z.optional(z.string()),
|
|
816
|
-
/** For `task.commented
|
|
888
|
+
/** For `task.commented`, and for `decision.raised` when any came: how many files came with it. */
|
|
817
889
|
files: z.optional(z.int()),
|
|
890
|
+
/** 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]`. */
|
|
891
|
+
command: z.optional(z.string()),
|
|
892
|
+
outcome: z.optional(z.enum(PLUGIN_COMMAND_OUTCOMES)),
|
|
893
|
+
code: z.optional(z.string()),
|
|
894
|
+
durationMs: z.optional(z.int()),
|
|
895
|
+
args: z.optional(z.record(z.string(), z.unknown())),
|
|
896
|
+
/** For `plugin.enabled` and `plugin.configured`: the capabilities consented to. */
|
|
897
|
+
capabilities: z.optional(z.array(z.string())),
|
|
898
|
+
/** For `plugin.granted` and `plugin.revoked`: whether the role went to everyone. */
|
|
899
|
+
everyone: z.optional(z.boolean()),
|
|
900
|
+
/** For `plugin.failed`: what went wrong, in words for a person. */
|
|
901
|
+
problem: z.optional(z.string()),
|
|
818
902
|
});
|
|
819
903
|
export type RestEventData = z.infer<typeof restEventDataSchema>;
|
|
820
904
|
|
|
@@ -835,6 +919,8 @@ export const restEventSchema = z.object({
|
|
|
835
919
|
documentId: z.nullable(uuid),
|
|
836
920
|
/** The goal it is about, or `null`. */
|
|
837
921
|
goalId: z.nullable(uuid),
|
|
922
|
+
/** The plugin that caused it, by key, or `null` (ADR-0052). */
|
|
923
|
+
plugin: z.nullable(z.string()),
|
|
838
924
|
data: restEventDataSchema,
|
|
839
925
|
createdAt: instant,
|
|
840
926
|
});
|
|
@@ -848,19 +934,6 @@ export const restReportSchema = z.object({
|
|
|
848
934
|
});
|
|
849
935
|
export type RestReport = z.infer<typeof restReportSchema>;
|
|
850
936
|
|
|
851
|
-
/** A file a run handed in, as the console keeps it; its bytes are at `projectPath(key, "files", <artifact id>)`. */
|
|
852
|
-
export const restFileSchema = z.object({
|
|
853
|
-
/** What the agent called it: one line, without a path. */
|
|
854
|
-
name: z.string(),
|
|
855
|
-
/** In bytes. */
|
|
856
|
-
size: count,
|
|
857
|
-
/** The media type the agent said, or `application/octet-stream`. */
|
|
858
|
-
contentType: z.string(),
|
|
859
|
-
/** The SHA-256 of the bytes, in hex: what the console keeps them under. */
|
|
860
|
-
sha256: z.string(),
|
|
861
|
-
});
|
|
862
|
-
export type RestFile = z.infer<typeof restFileSchema>;
|
|
863
|
-
|
|
864
937
|
/** What a run handed in: a link to a branch, a pull request, a page; or a file the console keeps. */
|
|
865
938
|
export const restArtifactSchema = z.object({
|
|
866
939
|
id: uuid,
|
|
@@ -1193,6 +1266,8 @@ export const restDocumentSummarySchema = z.object({
|
|
|
1193
1266
|
/** Who wrote the latest version, and the agent they wrote it through, or `null`. */
|
|
1194
1267
|
updatedBy: restPersonSchema,
|
|
1195
1268
|
agent: z.nullable(z.string()),
|
|
1269
|
+
/** The plugin that wrote it, by key (ADR-0052), or `null`; left out by a console older than the plugins. */
|
|
1270
|
+
plugin: z.optional(z.nullable(z.string())),
|
|
1196
1271
|
/** When the document was archived, or `null` while it is current. */
|
|
1197
1272
|
archivedAt: z.nullable(instant),
|
|
1198
1273
|
createdAt: instant,
|
|
@@ -1265,6 +1340,21 @@ export const restDocumentInputSchema = z.object({
|
|
|
1265
1340
|
});
|
|
1266
1341
|
export type RestDocumentInput = z.infer<typeof restDocumentInputSchema>;
|
|
1267
1342
|
|
|
1343
|
+
/**
|
|
1344
|
+
* A plugin named after the rules (docs/specs/plugins.md, "The command"): one the asker may use,
|
|
1345
|
+
* bound to the project where the rules are a project's; what agents are told of it, in the
|
|
1346
|
+
* manifest's languages, and the asker's roles in it.
|
|
1347
|
+
*/
|
|
1348
|
+
export const restRulesPluginSchema = z.object({
|
|
1349
|
+
key: z.string(),
|
|
1350
|
+
name: z.record(z.string(), z.string()),
|
|
1351
|
+
/** The sentence agents read, by language; `null` for the description. */
|
|
1352
|
+
agentNote: z.nullable(z.record(z.string(), z.string())),
|
|
1353
|
+
description: z.record(z.string(), z.string()),
|
|
1354
|
+
roles: z.array(z.string()),
|
|
1355
|
+
});
|
|
1356
|
+
export type RestRulesPlugin = z.infer<typeof restRulesPluginSchema>;
|
|
1357
|
+
|
|
1268
1358
|
/**
|
|
1269
1359
|
* `GET /api/v1/rules`, and each half of a project's (ADR-0023): the rules that hold, and where
|
|
1270
1360
|
* they come from. `reference`: the console's own, since the organization wrote none;
|
|
@@ -1276,6 +1366,8 @@ export const restRulesSchema = z.object({
|
|
|
1276
1366
|
body: z.nullable(z.string()),
|
|
1277
1367
|
/** The page they are written on, or `null` for the console's own and for none. */
|
|
1278
1368
|
page: z.nullable(restDocumentSummarySchema),
|
|
1369
|
+
/** At the workspace: every plugin the asker may use, by key; left out in the halves of a project's answer. */
|
|
1370
|
+
plugins: z.optional(z.array(restRulesPluginSchema)),
|
|
1279
1371
|
});
|
|
1280
1372
|
export type RestRules = z.infer<typeof restRulesSchema>;
|
|
1281
1373
|
|
|
@@ -1283,6 +1375,8 @@ export type RestRules = z.infer<typeof restRulesSchema>;
|
|
|
1283
1375
|
export const restProjectRulesSchema = z.object({
|
|
1284
1376
|
workspace: restRulesSchema,
|
|
1285
1377
|
project: restRulesSchema,
|
|
1378
|
+
/** The plugins bound to the project, as its board project or on it, that the asker holds a role in. */
|
|
1379
|
+
plugins: z.optional(z.array(restRulesPluginSchema)),
|
|
1286
1380
|
});
|
|
1287
1381
|
export type RestProjectRules = z.infer<typeof restProjectRulesSchema>;
|
|
1288
1382
|
|
|
@@ -1390,3 +1484,6 @@ export const restRunEndInputSchema = z.object({
|
|
|
1390
1484
|
summary: z.optional(summary),
|
|
1391
1485
|
});
|
|
1392
1486
|
export type RestRunEndInput = z.infer<typeof restRunEndInputSchema>;
|
|
1487
|
+
|
|
1488
|
+
// The plugins' routes (docs/specs/plugins.md, "REST"), beside the board's.
|
|
1489
|
+
export * from "./plugin/rest-schemas.js";
|