@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/cli/format.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { argUsage } from "../plugin/args.js";
|
|
1
2
|
import type {
|
|
2
3
|
RestArtifact,
|
|
3
4
|
RestCategory,
|
|
@@ -11,9 +12,22 @@ import type {
|
|
|
11
12
|
RestMember,
|
|
12
13
|
RestPerson,
|
|
13
14
|
RestPersonWork,
|
|
15
|
+
RestPlugin,
|
|
16
|
+
RestPluginArg,
|
|
17
|
+
RestPluginDetail,
|
|
18
|
+
RestPluginGrant,
|
|
19
|
+
RestPluginInvocation,
|
|
20
|
+
RestPluginOperation,
|
|
21
|
+
RestPluginRecord,
|
|
22
|
+
RestPluginRecordPage,
|
|
23
|
+
RestPluginRecordRead,
|
|
24
|
+
RestPluginRecordVersions,
|
|
25
|
+
RestPluginSetting,
|
|
26
|
+
RestPlugins,
|
|
14
27
|
RestProject,
|
|
15
28
|
RestProjectRules,
|
|
16
29
|
RestRules,
|
|
30
|
+
RestRulesPlugin,
|
|
17
31
|
RestRun,
|
|
18
32
|
RestTask,
|
|
19
33
|
RestVersion,
|
|
@@ -320,16 +334,26 @@ function formatRulesHalf(where: "the workspace" | "this project", rules: RestRul
|
|
|
320
334
|
return `${head}\n\n${rules.body.trimEnd()}`;
|
|
321
335
|
}
|
|
322
336
|
|
|
323
|
-
/**
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
337
|
+
/**
|
|
338
|
+
* The rules that hold: the workspace's, and what the project adds when the command works in one;
|
|
339
|
+
* then the plugins the console names after them, a line each, where there are any.
|
|
340
|
+
*/
|
|
341
|
+
export function formatRules(
|
|
342
|
+
rules: RestProjectRules | RestRules,
|
|
343
|
+
language?: string | null | undefined,
|
|
344
|
+
): string {
|
|
345
|
+
const parts =
|
|
346
|
+
"workspace" in rules
|
|
347
|
+
? [
|
|
348
|
+
formatRulesHalf("the workspace", rules.workspace),
|
|
349
|
+
"",
|
|
350
|
+
formatRulesHalf("this project", rules.project),
|
|
351
|
+
]
|
|
352
|
+
: [formatRulesHalf("the workspace", rules)];
|
|
353
|
+
if (rules.plugins !== undefined && rules.plugins.length > 0) {
|
|
354
|
+
parts.push("", formatRulesPlugins(rules.plugins, language));
|
|
331
355
|
}
|
|
332
|
-
return
|
|
356
|
+
return parts.join("\n");
|
|
333
357
|
}
|
|
334
358
|
|
|
335
359
|
/** How far a goal is, from its tasks: the done, the at work, and the rest, in one phrase. */
|
|
@@ -421,7 +445,7 @@ export function formatOptions(decision: RestDecision): string {
|
|
|
421
445
|
return decision.options
|
|
422
446
|
.map(
|
|
423
447
|
(option) =>
|
|
424
|
-
` ${option.id}) ${option.label}${option.own === true ? " (the person's own answer, not one given)" : ""}`,
|
|
448
|
+
` ${option.id}) ${option.label}${option.key === undefined ? "" : ` [${option.key}]`}${option.own === true ? " (the person's own answer, not one given)" : ""}`,
|
|
425
449
|
)
|
|
426
450
|
.join("\n");
|
|
427
451
|
}
|
|
@@ -450,6 +474,17 @@ export function formatDecision(decision: RestDecision): string {
|
|
|
450
474
|
if (decision.body.trim().length > 0) {
|
|
451
475
|
lines.push("", decision.body.trimEnd());
|
|
452
476
|
}
|
|
477
|
+
// The files put on it (ADR-0055), each with the command that reads it.
|
|
478
|
+
const files = decision.files ?? [];
|
|
479
|
+
if (files.length > 0) {
|
|
480
|
+
lines.push(
|
|
481
|
+
"",
|
|
482
|
+
...files.map(
|
|
483
|
+
(attached) =>
|
|
484
|
+
`file: ${attached.file.name} (${attached.file.size} bytes, ${attached.file.contentType}): console file ${attached.id}`,
|
|
485
|
+
),
|
|
486
|
+
);
|
|
487
|
+
}
|
|
453
488
|
lines.push("", "options:", formatOptions(decision), "", formatAnswer(decision));
|
|
454
489
|
if (decision.outcome !== null && decision.outcome.trim().length > 0) {
|
|
455
490
|
lines.push("", "what followed:", indent(decision.outcome));
|
|
@@ -536,3 +571,326 @@ export function formatVersion(path: string, version: RestVersion): string {
|
|
|
536
571
|
}
|
|
537
572
|
|
|
538
573
|
/** The text of one path across the pages a skill came in: the fragments joined in order. */
|
|
574
|
+
|
|
575
|
+
// ---- The plugins (docs/specs/plugins.md, "The command") ----
|
|
576
|
+
|
|
577
|
+
/** A text in the person's language, else in English, else the first the manifest has; nothing for none. */
|
|
578
|
+
export function localized(
|
|
579
|
+
texts: Readonly<Record<string, string>> | null | undefined,
|
|
580
|
+
language: string | null | undefined,
|
|
581
|
+
): string {
|
|
582
|
+
if (texts === null || texts === undefined) {
|
|
583
|
+
return "";
|
|
584
|
+
}
|
|
585
|
+
const tag = language ?? "en";
|
|
586
|
+
return texts[tag] ?? texts[tag.split("-")[0] ?? tag] ?? texts.en ?? Object.values(texts)[0] ?? "";
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/** One plugin in a line: its key, its name and version, its state, the roles held in it, its problems. */
|
|
590
|
+
export function formatPluginLine(plugin: RestPlugin, language: string | null | undefined): string {
|
|
591
|
+
const notes = [
|
|
592
|
+
plugin.roles.length === 0 ? undefined : `roles: ${plugin.roles.join(", ")}`,
|
|
593
|
+
plugin.problems.length === 0 ? undefined : `problems: ${plugin.problems.join("; ")}`,
|
|
594
|
+
].filter((note): note is string => note !== undefined);
|
|
595
|
+
return `${plugin.key} ${localized(plugin.name, language)} ${plugin.version} ${plugin.state}${notes.length === 0 ? "" : ` ${notes.join(" ")}`}`;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/** The plugins one may use, a line each, and how to go on. */
|
|
599
|
+
export function formatPlugins(plugins: RestPlugins, language: string | null | undefined): string {
|
|
600
|
+
if (plugins.items.length === 0) {
|
|
601
|
+
return "This console has no plugins you may use.";
|
|
602
|
+
}
|
|
603
|
+
return [
|
|
604
|
+
...plugins.items.map((plugin) => formatPluginLine(plugin, language)),
|
|
605
|
+
"",
|
|
606
|
+
"One plugin, with its commands: console plugin <key>. One command in full: console plugin <key> help <command>.",
|
|
607
|
+
].join("\n");
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/** How a command or a query of a plugin is given, as help prints it: the positionals, then the flags. */
|
|
611
|
+
export function formatOperationUsage(key: string, operation: RestPluginOperation): string {
|
|
612
|
+
const entries = Object.entries(operation.args);
|
|
613
|
+
const usage = [
|
|
614
|
+
...entries.filter(([, arg]) => arg.positional).map(([name, arg]) => argUsage(name, arg)),
|
|
615
|
+
...entries.filter(([, arg]) => !arg.positional).map(([name, arg]) => argUsage(name, arg)),
|
|
616
|
+
];
|
|
617
|
+
return `console plugin ${key} ${operation.name}${usage.map((part) => ` ${part}`).join("")}`;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/** What an argument takes, in a line: its form, its type with its bounds, and what it is for. */
|
|
621
|
+
function formatArgLine(name: string, arg: RestPluginArg): string {
|
|
622
|
+
const kind = (description: RestPluginArg): string => {
|
|
623
|
+
switch (description.type) {
|
|
624
|
+
case "text":
|
|
625
|
+
case "markdown":
|
|
626
|
+
return `${description.type}${description.max === undefined ? "" : `, up to ${description.max} characters`}${description.secret === true ? ", hidden in the event" : ""}`;
|
|
627
|
+
case "number": {
|
|
628
|
+
const bounds = [
|
|
629
|
+
description.integer === true ? "whole" : undefined,
|
|
630
|
+
description.min === undefined ? undefined : `from ${description.min}`,
|
|
631
|
+
description.max === undefined ? undefined : `to ${description.max}`,
|
|
632
|
+
].filter((bound): bound is string => bound !== undefined);
|
|
633
|
+
return `number${bounds.length === 0 ? "" : ` (${bounds.join(", ")})`}`;
|
|
634
|
+
}
|
|
635
|
+
case "boolean":
|
|
636
|
+
return "true or false; the flag alone is true";
|
|
637
|
+
case "enum":
|
|
638
|
+
return `one of ${(description.options ?? []).join(", ")}`;
|
|
639
|
+
case "day":
|
|
640
|
+
return "a day as YYYY-MM-DD";
|
|
641
|
+
case "person":
|
|
642
|
+
return "a login, or me";
|
|
643
|
+
case "project":
|
|
644
|
+
return "a project's key";
|
|
645
|
+
case "record":
|
|
646
|
+
return `the id of a record of ${description.collection ?? "a collection"}`;
|
|
647
|
+
case "file":
|
|
648
|
+
return "a file: --file <path>, or - for standard input";
|
|
649
|
+
case "list":
|
|
650
|
+
return `a list of ${description.of === undefined ? "items" : kind(description.of)}${description.max === undefined ? "" : `, up to ${description.max}`}; the flag given again, or commas between`;
|
|
651
|
+
default:
|
|
652
|
+
return description.type;
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
const about = arg.about === undefined ? "" : `: ${arg.about}`;
|
|
656
|
+
return ` ${argUsage(name, arg)} ${kind(arg)}${arg.optional ? ", optional" : ""}${about}`;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/** The refusals a plugin's command or query may meet, as `console help` words them. */
|
|
660
|
+
const PLUGIN_COMMAND_REFUSALS = [
|
|
661
|
+
"plugin.invalid_args: a word does not fit the definition; the message names the first at fault",
|
|
662
|
+
"plugin.forbidden: the command needs a role you do not hold in the plugin",
|
|
663
|
+
"plugin.disabled, plugin.unavailable: the plugin is not enabled, or cannot run right now",
|
|
664
|
+
"plugin.timeout: the plugin ran past its time",
|
|
665
|
+
"plugin.<key>.<code>: the plugin's own refusal, in its own words",
|
|
666
|
+
];
|
|
667
|
+
|
|
668
|
+
/** One command or query of a plugin in full, as `console help <command>` prints one; or every one in a line. */
|
|
669
|
+
export function formatPluginHelp(detail: RestPluginDetail, name: string | undefined): string {
|
|
670
|
+
if (name === undefined) {
|
|
671
|
+
if (detail.operations.length === 0) {
|
|
672
|
+
return `${detail.key} has no command or query you may run.`;
|
|
673
|
+
}
|
|
674
|
+
return [
|
|
675
|
+
...detail.operations.flatMap((operation) => [
|
|
676
|
+
formatOperationUsage(detail.key, operation),
|
|
677
|
+
` ${operation.kind === "query" ? "[query] " : ""}${operation.about}`,
|
|
678
|
+
]),
|
|
679
|
+
"",
|
|
680
|
+
`One in full: console plugin ${detail.key} help <command>.`,
|
|
681
|
+
].join("\n");
|
|
682
|
+
}
|
|
683
|
+
const operation = detail.operations.find((candidate) => candidate.name === name);
|
|
684
|
+
if (operation === undefined) {
|
|
685
|
+
return `${detail.key} has no command or query ${name} you may run.`;
|
|
686
|
+
}
|
|
687
|
+
const args = Object.entries(operation.args);
|
|
688
|
+
const parts = [
|
|
689
|
+
formatOperationUsage(detail.key, operation),
|
|
690
|
+
"",
|
|
691
|
+
`${operation.kind === "query" ? "A query: reads only, and answers JSON. " : "A command. "}${operation.about}`,
|
|
692
|
+
];
|
|
693
|
+
if (args.length > 0) {
|
|
694
|
+
parts.push(
|
|
695
|
+
"",
|
|
696
|
+
"Arguments (a positional one by its place, the others as --<name> <value> or --<name>=<value>):",
|
|
697
|
+
...args.map(([argName, arg]) => formatArgLine(argName, arg)),
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
if (operation.roles !== null) {
|
|
701
|
+
parts.push("", `Roles: ${operation.roles.join(", ")}`);
|
|
702
|
+
}
|
|
703
|
+
parts.push(
|
|
704
|
+
"",
|
|
705
|
+
operation.kind === "query"
|
|
706
|
+
? "Prints the answer as JSON; a query that answers a file saves it under its name."
|
|
707
|
+
: "Prints what the command says; --json prints its data. A command that raised a decision prints its id and exits with 3: console decision <id> --wait 100 waits for the answer.",
|
|
708
|
+
"",
|
|
709
|
+
"Refusals:",
|
|
710
|
+
...PLUGIN_COMMAND_REFUSALS.map((refusal) => ` ${refusal}`),
|
|
711
|
+
);
|
|
712
|
+
return parts.join("\n");
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
/** A setting in a line: its key and type, what it holds or whether it is set, and its name. */
|
|
716
|
+
export function formatPluginSettingLine(
|
|
717
|
+
setting: RestPluginSetting,
|
|
718
|
+
language: string | null | undefined,
|
|
719
|
+
): string {
|
|
720
|
+
const holds =
|
|
721
|
+
setting.type === "secret"
|
|
722
|
+
? setting.set
|
|
723
|
+
? `set${setting.setAt === null ? "" : ` ${moment(setting.setAt)}`}`
|
|
724
|
+
: "not set"
|
|
725
|
+
: setting.set
|
|
726
|
+
? setting.value === null
|
|
727
|
+
? "set"
|
|
728
|
+
: JSON.stringify(setting.value)
|
|
729
|
+
: setting.default === null
|
|
730
|
+
? "not set"
|
|
731
|
+
: `default ${JSON.stringify(setting.default)}`;
|
|
732
|
+
return ` ${setting.key} (${setting.type}${setting.required ? ", required" : ""}): ${holds} ${localized(setting.name, language)}`;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/** A grant in a line: its id, the role, whom it is to, since when. */
|
|
736
|
+
export function formatPluginGrantLine(grant: RestPluginGrant): string {
|
|
737
|
+
const whom =
|
|
738
|
+
grant.person !== null
|
|
739
|
+
? `person ${grant.person.login}`
|
|
740
|
+
: grant.project !== null
|
|
741
|
+
? `the members of ${grant.project.key}`
|
|
742
|
+
: "everyone";
|
|
743
|
+
return `${grant.id} ${grant.role} to ${whom} since ${moment(grant.createdAt)}`;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
/** One plugin in full: what it is, how it stands, what one may run, its skills and its settings. */
|
|
747
|
+
export function formatPlugin(
|
|
748
|
+
detail: RestPluginDetail,
|
|
749
|
+
language: string | null | undefined,
|
|
750
|
+
): string {
|
|
751
|
+
const name = localized(detail.name, language);
|
|
752
|
+
const lines = [`${detail.key}: ${name} ${detail.version}, ${detail.state}`];
|
|
753
|
+
const description = localized(detail.description, language);
|
|
754
|
+
if (description.length > 0) {
|
|
755
|
+
lines.push(description);
|
|
756
|
+
}
|
|
757
|
+
const note = localized(detail.agentNote, language);
|
|
758
|
+
if (note.length > 0) {
|
|
759
|
+
lines.push(`For agents: ${note}`);
|
|
760
|
+
}
|
|
761
|
+
if (detail.problems.length > 0) {
|
|
762
|
+
lines.push(`problems: ${detail.problems.join("; ")}`);
|
|
763
|
+
}
|
|
764
|
+
lines.push(
|
|
765
|
+
detail.roles.length === 0
|
|
766
|
+
? "You hold no role in it."
|
|
767
|
+
: `Your roles in it: ${detail.roles.join(", ")}.`,
|
|
768
|
+
);
|
|
769
|
+
if (detail.board !== null) {
|
|
770
|
+
lines.push(`Board project: ${detail.board.key} (${detail.board.name}).`);
|
|
771
|
+
} else if (detail.boardNeeds !== "none") {
|
|
772
|
+
lines.push("Board project: none yet.");
|
|
773
|
+
}
|
|
774
|
+
lines.push("");
|
|
775
|
+
if (detail.operations.length === 0) {
|
|
776
|
+
lines.push("No command or query you may run.");
|
|
777
|
+
} else {
|
|
778
|
+
lines.push("Commands and queries:");
|
|
779
|
+
for (const operation of detail.operations) {
|
|
780
|
+
lines.push(
|
|
781
|
+
` ${formatOperationUsage(detail.key, operation)}`,
|
|
782
|
+
` ${operation.kind === "query" ? "[query] " : ""}${operation.about}`,
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
lines.push(`One in full: console plugin ${detail.key} help <command>.`);
|
|
786
|
+
}
|
|
787
|
+
if (detail.skills !== null) {
|
|
788
|
+
lines.push(
|
|
789
|
+
"",
|
|
790
|
+
`Skills: console plugin ${detail.key} skills lists them; console plugin ${detail.key} skill <path> reads one. Read the one that fits before the first command.`,
|
|
791
|
+
);
|
|
792
|
+
}
|
|
793
|
+
if (detail.settings.length > 0) {
|
|
794
|
+
lines.push(
|
|
795
|
+
"",
|
|
796
|
+
"Settings:",
|
|
797
|
+
...detail.settings.map((setting) => formatPluginSettingLine(setting, language)),
|
|
798
|
+
);
|
|
799
|
+
}
|
|
800
|
+
if (detail.grants !== null) {
|
|
801
|
+
lines.push(
|
|
802
|
+
"",
|
|
803
|
+
detail.grants.length === 0
|
|
804
|
+
? "Grants: none; the default role, where the manifest names one, is everyone's."
|
|
805
|
+
: "Grants:",
|
|
806
|
+
...detail.grants.map((grant) => ` ${formatPluginGrantLine(grant)}`),
|
|
807
|
+
);
|
|
808
|
+
}
|
|
809
|
+
return lines.join("\n");
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
/** What a command or a query answered, as the command prints it. */
|
|
813
|
+
export function formatInvocation(result: RestPluginInvocation): string {
|
|
814
|
+
if (result.kind === "query") {
|
|
815
|
+
return result.data === undefined ? "null" : JSON.stringify(result.data, null, 2);
|
|
816
|
+
}
|
|
817
|
+
const text = result.text.length === 0 ? "Done." : result.text;
|
|
818
|
+
return result.waiting === null
|
|
819
|
+
? text
|
|
820
|
+
: `${text}\ndecision id: ${result.waiting}\nThe decision waits for a person: console decision ${result.waiting} --wait 100`;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
/** A record's data on one line, cut where it runs long. */
|
|
824
|
+
function compactData(data: Readonly<Record<string, unknown>>): string {
|
|
825
|
+
const text = JSON.stringify(data);
|
|
826
|
+
return text.length > 200 ? `${text.slice(0, 197)}...` : text;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
/** A record in a line: its id, its version, when it last changed, whether it is put away, its data. */
|
|
830
|
+
export function formatPluginRecordLine(record: RestPluginRecord): string {
|
|
831
|
+
return `${record.id} v${record.version} ${moment(record.updatedAt)}${record.archivedAt === null ? "" : " archived"} ${compactData(record.data)}`;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
/** A page of records, and how the next is asked for. */
|
|
835
|
+
export function formatPluginRecords(page: RestPluginRecordPage): string {
|
|
836
|
+
if (page.items.length === 0) {
|
|
837
|
+
return "No records.";
|
|
838
|
+
}
|
|
839
|
+
const lines = page.items.map(formatPluginRecordLine);
|
|
840
|
+
if (page.after !== null) {
|
|
841
|
+
lines.push(`More: --after ${page.after}`);
|
|
842
|
+
}
|
|
843
|
+
return lines.join("\n");
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
/** One record in full, or one version of it as it was. */
|
|
847
|
+
export function formatPluginRecord(record: RestPluginRecordRead): string {
|
|
848
|
+
if (!("id" in record)) {
|
|
849
|
+
return [
|
|
850
|
+
`version ${record.version}, ${moment(record.at)}, by ${record.by ?? "the console"}`,
|
|
851
|
+
JSON.stringify(record.data, null, 2),
|
|
852
|
+
].join("\n");
|
|
853
|
+
}
|
|
854
|
+
const facts = [
|
|
855
|
+
`id: ${record.id} collection: ${record.collection} version: ${record.version}`,
|
|
856
|
+
`created: ${moment(record.createdAt)} by ${record.createdBy ?? "the console"} updated: ${moment(record.updatedAt)} by ${record.updatedBy ?? "the console"}`,
|
|
857
|
+
];
|
|
858
|
+
if (record.project !== null) {
|
|
859
|
+
facts.push(`project: ${record.project}`);
|
|
860
|
+
}
|
|
861
|
+
if (record.owner !== null) {
|
|
862
|
+
facts.push(`owner: ${record.owner}`);
|
|
863
|
+
}
|
|
864
|
+
if (record.archivedAt !== null) {
|
|
865
|
+
facts.push(`archived: ${moment(record.archivedAt)}`);
|
|
866
|
+
}
|
|
867
|
+
return [...facts, JSON.stringify(record.data, null, 2)].join("\n");
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
/** The versions of a record, newest first, a line each. */
|
|
871
|
+
export function formatPluginRecordVersions(versions: RestPluginRecordVersions): string {
|
|
872
|
+
if (versions.items.length === 0) {
|
|
873
|
+
return "No versions.";
|
|
874
|
+
}
|
|
875
|
+
return versions.items
|
|
876
|
+
.map(
|
|
877
|
+
(version) =>
|
|
878
|
+
`v${version.version} ${moment(version.at)} by ${version.by ?? "the console"} ${compactData(version.data)}`,
|
|
879
|
+
)
|
|
880
|
+
.join("\n");
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
/** The plugins named after the rules: a line each, with the sentence for agents and where to start. */
|
|
884
|
+
export function formatRulesPlugins(
|
|
885
|
+
plugins: readonly RestRulesPlugin[],
|
|
886
|
+
language: string | null | undefined,
|
|
887
|
+
): string {
|
|
888
|
+
return [
|
|
889
|
+
"## Plugins",
|
|
890
|
+
"",
|
|
891
|
+
...plugins.map((plugin) => {
|
|
892
|
+
const note = localized(plugin.agentNote, language) || localized(plugin.description, language);
|
|
893
|
+
return `- ${plugin.key} (${localized(plugin.name, language)}): ${note} Start with console plugin ${plugin.key}.`;
|
|
894
|
+
}),
|
|
895
|
+
].join("\n");
|
|
896
|
+
}
|
package/src/cli/help.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
MAX_DOCUMENTS_PER_PROJECT,
|
|
14
14
|
MAX_FILE_BYTES,
|
|
15
15
|
MAX_FILES_PER_COMMENT,
|
|
16
|
+
MAX_FILES_PER_DECISION,
|
|
16
17
|
MAX_FILES_PER_DOCUMENT,
|
|
17
18
|
MAX_GOALS_PER_PROJECT,
|
|
18
19
|
MAX_LINK_LABEL_LENGTH,
|
|
@@ -360,7 +361,7 @@ export const COMMAND_HELP: Readonly<Record<string, CommandHelp>> = {
|
|
|
360
361
|
synopsis:
|
|
361
362
|
"What this organization and this project ask of agents; rules write writes them, for an owner or an administrator.",
|
|
362
363
|
about:
|
|
363
|
-
"What this organization asks of agents (ADR-0023): the workspace's rules, the console's own until an administrator writes the organization's, and this project's own when it has them. rules write writes this project's rules, for an owner, or with --workspace the workspace's, for an administrator; none puts the written rules away, so that the console's own hold again, or the project adds none. Without a project named, rules shows the workspace's alone.",
|
|
364
|
+
"What this organization asks of agents (ADR-0023): the workspace's rules, the console's own until an administrator writes the organization's, and this project's own when it has them. rules write writes this project's rules, for an owner, or with --workspace the workspace's, for an administrator; none puts the written rules away, so that the console's own hold again, or the project adds none. Without a project named, rules shows the workspace's alone. After the rules, a section Plugins names the plugins bound to the project that you hold a role in, or at the workspace every plugin you may use, a line each with the sentence its manifest gives agents and where to start: console plugin <key>.",
|
|
364
365
|
limits: [
|
|
365
366
|
`body: Markdown, up to ${MAX_RULES_LENGTH} characters; the console's own rules, written as they are, write nothing`,
|
|
366
367
|
],
|
|
@@ -369,11 +370,45 @@ export const COMMAND_HELP: Readonly<Record<string, CommandHelp>> = {
|
|
|
369
370
|
"document.conflict: the rules have moved on since --base; read them again",
|
|
370
371
|
],
|
|
371
372
|
},
|
|
373
|
+
plugins: {
|
|
374
|
+
usage: "plugins",
|
|
375
|
+
synopsis: "The plugins of this console you may use: key, name, version, state, your roles.",
|
|
376
|
+
about:
|
|
377
|
+
"The plugins of this console (docs/specs/plugins.md), one a line: the enabled ones a member may use, every one with its state for an administrator; the key, the name, the version, the state, the roles you hold in it. A plugin is worked through console plugin <key>, and the rules of a board name the plugins to use there under Plugins, a sentence each. Needs no project.",
|
|
378
|
+
},
|
|
379
|
+
plugin: {
|
|
380
|
+
usage:
|
|
381
|
+
"plugin <key> | plugin <key> help [<command>] | plugin <key> <command> [<args>] [--<name> <value>]... [--file <path> | -] [--run <id>] | plugin <key> records <collection> [<id>] [--where <field>=<value>]... [--search <words>] [--project <key>] [--order <field>[:desc]] [--limit <n>] [--after <cursor>] [--archived] [--versions] | plugin <key> skills [<folder>|<file>] [--search <words> [--limit <n>] [--cursor <cursor>]] | plugin <key> skill <path> | plugin <key> skill --file <path> [--offset <n>] [--limit <n>] | plugin <key> enable --consent <capability>,... [--board new|<key>] [--projects all|<key>,...] [--set <key>=<value>]... | plugin <key> disable | plugin <key> settings [--set <key>=<value>]... | plugin <key> secret <name> [--remove] | plugin <key> grant <role> --person <login>|--project <key>|--everyone | plugin <key> revoke <grant id>",
|
|
382
|
+
overview:
|
|
383
|
+
"plugin <key> [help [<command>] | <command> [<args>] | records <collection> | skills | skill <path> | enable | disable | settings | secret | grant | revoke]",
|
|
384
|
+
synopsis:
|
|
385
|
+
"One plugin: what it is for and its commands; a command run as you; its records, its skills; its settings, for an administrator.",
|
|
386
|
+
about:
|
|
387
|
+
"One plugin of this console, by its key. Alone: what it is, the sentence for agents, its state, the roles you hold in it, its board project, then one line per command and query you may run, with its usage, where its skills are, and its settings. help [<command>]: one command or query in full, as console help prints one: its arguments, their types and bounds, and the refusals; every argument is given by its place when positional, else as --<name> <value> or --<name>=<value>; a boolean as --<name> alone; a list as the flag given again, or with commas between; a day as YYYY-MM-DD; a person by login, or me; a project by key; a file by --file <path>, or - for standard input, which the command uploads first, with the plugin's files capability. <command> [<args>]: runs the command or the query as the person whose token you hold; the console parses the words against the definition and refuses the first that does not fit; prints what the command says, or a query's answer as JSON, a file a query answers saved under its name; --json prints the whole answer. A command that raised a decision prints its id and exits with 3: console decision <id> --wait 100 waits for the answer. The event the command leaves names your open run in the plugin's board project, --run <id> saying which when several are open; an argument marked secret is hidden in it. records <collection>: the records you may read, one a line, newest first; --where <field>=<value>, given again for several, narrows by a field the collection indexes (id, owner and project always; a number, true, false and null are read as such); --search <words> by words; --project <key> to those linked to a project; --order <field>, with :desc for the newest first; a page of --limit with --after <cursor> as the last page printed; --archived the ones put away; <id> reads one record whole, --versions its versions. skills and skill: the plugin's own skills, a pack read from its package, exactly as console skills and console skill read a project's pack. enable, disable, settings, secret, grant and revoke are an administrator's. enable prints what each capability the plugin asks opens and what a malicious plugin would reach through it, and refuses unless --consent names every capability again; --board new makes the board project the manifest proposes, --board <key> chooses one, left out where the plugin needs none; --projects all, or the keys of the projects the plugin is on; --set a setting's value, which settings changes afterwards too, an empty value clearing one, a number or true and false read as such. secret <name> reads the value from standard input, seals it and shows it never; --remove takes it away. grant gives a role to a person by login, to the members of a project by key, or to everyone, and revoke takes a grant back by its id, which console plugin <key> lists to an administrator.",
|
|
388
|
+
limits: [
|
|
389
|
+
"a command line: up to 200 words of up to 50,000 characters each; one file, up to the file bound (console help hand-in), with the plugin's files capability",
|
|
390
|
+
"records: a page of up to 200; where: a field the collection indexes",
|
|
391
|
+
"enable: consent names every capability the manifest asks; settings and secrets as the manifest bounds them",
|
|
392
|
+
],
|
|
393
|
+
refusals: [
|
|
394
|
+
"plugin.not_found: no plugin has that key, or you may not know of it; or the plugin has no such command or query",
|
|
395
|
+
"plugin.disabled: the plugin is installed and not enabled",
|
|
396
|
+
"plugin.unavailable: the plugin failed to load, its host is away, or this deployment lacks what it needs",
|
|
397
|
+
"plugin.forbidden: the command, the record or the file needs a role you do not hold in the plugin, or the plugin lacks the capability",
|
|
398
|
+
"plugin.invalid_args: a word does not fit the definition; the message names the first at fault",
|
|
399
|
+
"plugin.timeout: the plugin's code ran past its time",
|
|
400
|
+
"plugin.too_many: a quota of the plugin is reached",
|
|
401
|
+
"plugin.needs_consent, plugin.requires, plugin.required_by: enabling without consent to every capability; a plugin this one requires is not enabled or not in range; another enabled plugin requires this one",
|
|
402
|
+
"plugin.failed: the plugin's code failed; the console's log says what it said, the answer does not",
|
|
403
|
+
"plugin.<key>.<code>: the plugin's own refusal, in its own words",
|
|
404
|
+
"auth.forbidden: enable, disable, settings, secret, grant and revoke are an administrator's",
|
|
405
|
+
],
|
|
406
|
+
},
|
|
372
407
|
take: {
|
|
373
408
|
usage: "take <number|id> [--agent <name>]",
|
|
374
409
|
synopsis: "Takes a task: a run begins, and the task is in progress and the person's.",
|
|
375
410
|
about:
|
|
376
|
-
"Takes a task: a run begins, and the task is in progress and the person's; the run's id and the task's id are printed on a line of their own, then the task, then the rules of the board. A run still open on the task is taken over, since the board cannot know whether its agent still runs: it ends as abandoned, the feed says who took over, and that agent is refused on its next command; console task <number> shows the runs on a task, with when each was last heard from, before it is taken. --agent is what people see at work; left out, it is what the person called the token.",
|
|
411
|
+
"Takes a task: a run begins, and the task is in progress and the person's; the run's id and the task's id are printed on a line of their own, then the task, then the rules of the board, with a section Plugins after them where plugins are bound to the project: a line per plugin you may use there, which console plugin <key> then says how to use. A run still open on the task is taken over, since the board cannot know whether its agent still runs: it ends as abandoned, the feed says who took over, and that agent is refused on its next command; console task <number> shows the runs on a task, with when each was last heard from, before it is taken. --agent is what people see at work; left out, it is what the person called the token.",
|
|
377
412
|
limits: [
|
|
378
413
|
`agent: one line, up to ${MAX_AGENT_LENGTH} characters`,
|
|
379
414
|
`at most ${MAX_RUNS_PER_TASK} runs on one task`,
|
|
@@ -416,16 +451,18 @@ export const COMMAND_HELP: Readonly<Record<string, CommandHelp>> = {
|
|
|
416
451
|
},
|
|
417
452
|
ask: {
|
|
418
453
|
usage:
|
|
419
|
-
'ask "<question>" --option "<label>" --option "<label>" [...] [--body <markdown>|--file <path>] [--to <login|me>] [--wait <seconds>] [--run <id>]',
|
|
454
|
+
'ask "<question>" --option "<label>" --option "<label>" [...] [--body <markdown>|--file <path>] [--attach <path>]... [--to <login|me>] [--wait <seconds>] [--run <id>]',
|
|
420
455
|
overview:
|
|
421
|
-
'ask "<question>" --option "<label>" --option "<label>" [...] [--body <markdown>|--file <path>] [--to <login|me>] [--wait <seconds>]',
|
|
456
|
+
'ask "<question>" --option "<label>" --option "<label>" [...] [--body <markdown>|--file <path>] [--attach <path>]... [--to <login|me>] [--wait <seconds>]',
|
|
422
457
|
synopsis:
|
|
423
458
|
"Raises a decision a person must make, with options, and waits a while for the answer.",
|
|
424
|
-
about: `Raises a decision a person must make: the question, the options to choose from, and what they need to know. It is for the person you work for unless --to names another of the project, who then finds it among their decisions (ADR-0042); anyone of the project may still answer. The run waits for the answer. The command waits 60 seconds for it unless --wait says otherwise, and exits with 3 if it is still to come: keep waiting with \`console decision <id> --wait 100\`, within what your shell gives one command. The decision's id is printed as soon as it is raised. The person chooses one of the options, or answers in their own words: the answer then names one more option, their words, marked own; act on it as given. ${ON_THE_RUN}`,
|
|
459
|
+
about: `Raises a decision a person must make: the question, the options to choose from, and what they need to know. --attach puts a file on the decision, in the one request: a picture of what is to be chosen between, a screenshot of what was made; a picture the body names as  is shown there, the rest after the body, and the person reads each back with \`console file <id>\` (ADR-0055). It is for the person you work for unless --to names another of the project, who then finds it among their decisions (ADR-0042); anyone of the project may still answer. The run waits for the answer. The command waits 60 seconds for it unless --wait says otherwise, and exits with 3 if it is still to come: keep waiting with \`console decision <id> --wait 100\`, within what your shell gives one command. The decision's id is printed as soon as it is raised. The person chooses one of the options, or answers in their own words: the answer then names one more option, their words, marked own; act on it as given. ${ON_THE_RUN}`,
|
|
425
460
|
limits: [
|
|
426
461
|
`question: one line, up to ${MAX_QUESTION_LENGTH} characters`,
|
|
427
462
|
`options: ${MIN_OPTIONS} to ${MAX_OPTIONS}, each one line up to ${MAX_OPTION_LABEL_LENGTH} characters`,
|
|
428
463
|
`body: ${MARKDOWN}`,
|
|
464
|
+
`attach: a file: up to ${MAX_FILE_BYTES} bytes, not empty; called by its name, without the path; a picture is placed in the body as `,
|
|
465
|
+
`at most ${MAX_FILES_PER_DECISION} files on one decision, together up to ${MAX_FILE_BYTES} bytes`,
|
|
429
466
|
"to: a login of the project, or me",
|
|
430
467
|
`at most ${MAX_DECISIONS_PER_PROJECT} decisions in one project`,
|
|
431
468
|
],
|
|
@@ -434,6 +471,8 @@ export const COMMAND_HELP: Readonly<Record<string, CommandHelp>> = {
|
|
|
434
471
|
"decision.invalid_run: the run is not yours, or is over",
|
|
435
472
|
"decision.invalid_decider: the person named may not work in the project",
|
|
436
473
|
"decision.too_many: the project holds as many decisions as one may",
|
|
474
|
+
"decision.too_many_files: more files than one decision carries",
|
|
475
|
+
"request.too_large: a file, or the files together, over the bound",
|
|
437
476
|
],
|
|
438
477
|
},
|
|
439
478
|
answer: {
|
|
@@ -524,7 +563,7 @@ export const COMMAND_HELP: Readonly<Record<string, CommandHelp>> = {
|
|
|
524
563
|
usage: "file <id> [--out <path>]",
|
|
525
564
|
synopsis: "Reads a file of the project to this machine, by its id.",
|
|
526
565
|
about:
|
|
527
|
-
"Reads a file of the project from the console and writes it on this machine: one a run handed in, one put in a comment, or one attached to a page, by the id the task, the run or the page shows. Written under its own name in the working directory, at --out <path>, or into --out <directory>. Then look at it with your own tools.",
|
|
566
|
+
"Reads a file of the project from the console and writes it on this machine: one a run handed in, one put in a comment or on a decision, or one attached to a page, by the id the task, the run, the decision or the page shows. Written under its own name in the working directory, at --out <path>, or into --out <directory>. Then look at it with your own tools.",
|
|
528
567
|
refusals: ["file.not_found: no file of this project has that id"],
|
|
529
568
|
},
|
|
530
569
|
docs: {
|
|
@@ -668,6 +707,11 @@ const SECTIONS: readonly { readonly title: string; readonly commands: readonly s
|
|
|
668
707
|
"rules",
|
|
669
708
|
],
|
|
670
709
|
},
|
|
710
|
+
{
|
|
711
|
+
title:
|
|
712
|
+
"The plugins of this console, if it has any: a feature added to the board, worked through one command",
|
|
713
|
+
commands: ["plugins", "plugin"],
|
|
714
|
+
},
|
|
671
715
|
{
|
|
672
716
|
title: "Working",
|
|
673
717
|
commands: [
|