@skillcdn/console 0.1.23 → 0.3.0
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 +6 -5
- package/dist/api.d.ts +1 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +1 -1
- package/dist/api.js.map +1 -1
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +80 -54
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/format.d.ts +4 -28
- package/dist/cli/format.d.ts.map +1 -1
- package/dist/cli/format.js +7 -260
- package/dist/cli/format.js.map +1 -1
- package/dist/cli/help.d.ts +6 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +47 -24
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/pack.d.ts +46 -0
- package/dist/cli/pack.d.ts.map +1 -0
- package/dist/cli/pack.js +250 -0
- package/dist/cli/pack.js.map +1 -0
- package/dist/compat.d.ts +1 -1
- package/dist/compat.js +1 -1
- package/dist/components/decision-list.d.ts +13 -1
- package/dist/components/decision-list.d.ts.map +1 -1
- package/dist/components/decision-list.js +74 -29
- package/dist/components/decision-list.js.map +1 -1
- package/dist/components/paged.d.ts +24 -0
- package/dist/components/paged.d.ts.map +1 -1
- package/dist/components/paged.js +40 -4
- package/dist/components/paged.js.map +1 -1
- package/dist/components/skills.d.ts.map +1 -1
- package/dist/components/skills.js +8 -4
- package/dist/components/skills.js.map +1 -1
- package/dist/components/ui.d.ts +2 -0
- package/dist/components/ui.d.ts.map +1 -1
- package/dist/components/ui.js +7 -2
- package/dist/components/ui.js.map +1 -1
- package/dist/components/work.d.ts +2 -0
- package/dist/components/work.d.ts.map +1 -1
- package/dist/components/work.js +3 -2
- package/dist/components/work.js.map +1 -1
- package/dist/console.css +112 -5
- package/dist/console.d.ts.map +1 -1
- package/dist/console.js +5 -3
- package/dist/console.js.map +1 -1
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +27 -2
- package/dist/data.js.map +1 -1
- package/dist/i18n/en.d.ts +13 -0
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +15 -0
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/ko.d.ts.map +1 -1
- package/dist/i18n/ko.js +15 -0
- package/dist/i18n/ko.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/router.d.ts +6 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +13 -7
- package/dist/router.js.map +1 -1
- package/dist/rules.js +3 -3
- package/dist/rules.js.map +1 -1
- package/dist/schemas.d.ts +557 -162
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +72 -158
- package/dist/schemas.js.map +1 -1
- package/docs/specs/cli.md +12 -12
- package/docs/specs/rest.md +7 -15
- package/package.json +2 -1
- package/skills/deploying-a-console/SKILL.md +2 -2
- package/skills/working-the-board/SKILL.md +9 -14
- package/skills/working-the-board/references/setting-up.md +3 -0
- package/skills/working-the-board/references/terms.md +9 -0
- package/skills/working-the-board/references/the-sentence.md +5 -0
- package/src/api.ts +2 -7
- package/src/cli/cli.ts +113 -62
- package/src/cli/format.ts +10 -324
- package/src/cli/help.ts +53 -27
- package/src/cli/pack.ts +356 -0
- package/src/compat.ts +1 -1
- package/src/components/decision-list.tsx +227 -94
- package/src/components/paged.tsx +72 -3
- package/src/components/skills.tsx +51 -33
- package/src/components/ui.tsx +16 -3
- package/src/components/work.tsx +9 -5
- package/src/console.tsx +8 -2
- package/src/data.ts +32 -2
- package/src/i18n/en.ts +18 -0
- package/src/i18n/ko.ts +17 -0
- package/src/index.ts +9 -1
- package/src/router.ts +20 -9
- package/src/rules.ts +3 -3
- package/src/schemas.ts +87 -184
- package/src/styles/console.css +112 -5
package/src/cli/cli.ts
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
type RestSkillBrowse,
|
|
21
21
|
type RestSkillFile,
|
|
22
22
|
type RestSkillLoad,
|
|
23
|
-
type
|
|
23
|
+
type RestSkills,
|
|
24
24
|
type RestTaskPatch,
|
|
25
25
|
} from "../schemas.js";
|
|
26
26
|
import {
|
|
@@ -75,20 +75,31 @@ import {
|
|
|
75
75
|
formatRules,
|
|
76
76
|
formatRun,
|
|
77
77
|
formatRunLine,
|
|
78
|
-
formatSkillBrowse,
|
|
79
|
-
formatSkillFile,
|
|
80
|
-
formatSkillFind,
|
|
81
|
-
formatSkillLoad,
|
|
82
|
-
formatSkills,
|
|
83
78
|
formatTask,
|
|
84
79
|
formatTaskLine,
|
|
85
80
|
formatVersion,
|
|
86
81
|
formatVersionLine,
|
|
87
82
|
formatWork,
|
|
88
83
|
} from "./format.js";
|
|
89
|
-
import { COMMAND_HELP, helpFor, usage } from "./help.js";
|
|
84
|
+
import { COMMAND_HELP, helpFor, ownSkillPath, usage } from "./help.js";
|
|
90
85
|
import { describeInstall, type Install, updateCommandFor } from "./install.js";
|
|
91
86
|
import type { NoticeStore } from "./notices.js";
|
|
87
|
+
import {
|
|
88
|
+
bodyOfFile,
|
|
89
|
+
bodyOfFolder,
|
|
90
|
+
bodyOfSkill,
|
|
91
|
+
formatSkillBrowse,
|
|
92
|
+
formatSkillFile,
|
|
93
|
+
formatSkillFind,
|
|
94
|
+
formatSkillLoad,
|
|
95
|
+
formatSkills,
|
|
96
|
+
joinFile,
|
|
97
|
+
joinFolder,
|
|
98
|
+
joinSkill,
|
|
99
|
+
type PackSummary,
|
|
100
|
+
skillPathIn,
|
|
101
|
+
summaryOf,
|
|
102
|
+
} from "./pack.js";
|
|
92
103
|
import { createServeHandler, DEFAULT_SERVE_PORT, type Listen } from "./serve.js";
|
|
93
104
|
|
|
94
105
|
// The `console` command (docs/specs/cli.md): the agent's side of the console. A thin client of
|
|
@@ -339,11 +350,11 @@ async function currentRun(project: ProjectClient, values: Values): Promise<strin
|
|
|
339
350
|
}
|
|
340
351
|
if (items.length === 0) {
|
|
341
352
|
throw failed(
|
|
342
|
-
"
|
|
353
|
+
"run.none: no run of yours is open in this project. Take a task first: console take <number>; or name a run: --run <id>",
|
|
343
354
|
);
|
|
344
355
|
}
|
|
345
356
|
throw failed(
|
|
346
|
-
`
|
|
357
|
+
`run.ambiguous: several runs of yours are open in this project; say which with --run <id>:\n${items.map((run) => ` ${formatRunLine(run)}`).join("\n")}`,
|
|
347
358
|
);
|
|
348
359
|
}
|
|
349
360
|
|
|
@@ -851,14 +862,14 @@ const whoami: Command = async (args, io) => {
|
|
|
851
862
|
...(key === undefined
|
|
852
863
|
? []
|
|
853
864
|
: [
|
|
854
|
-
|
|
865
|
+
`What this organization asks of agents: console rules. How the board is worked: the skill working-the-board, shipped with this command${io.skillsDir === undefined ? " (console skills says where it is)." : `: ${ownSkillPath(io.skillsDir)}`}`,
|
|
855
866
|
]),
|
|
856
867
|
`This command is ${io.version ?? "of a version it does not know"}${io.install === undefined ? "" : `, ${describeInstall(io.install)}`}; ${consoleWords}.`,
|
|
857
868
|
...(verdict === "behind"
|
|
858
869
|
? [`A newer command exists. Update it: ${updateWords(io, me.console?.version)}`]
|
|
859
870
|
: verdict === "ahead"
|
|
860
871
|
? [
|
|
861
|
-
`This command is newer than the console: what the console has not got yet is refused as not found. To match the console: ${updateWords(io, me.console?.version)}`,
|
|
872
|
+
`This command is newer than the console: it works, and what the console has not got yet is refused as not found; nothing to do until then. To match the console then: ${updateWords(io, me.console?.version)}`,
|
|
862
873
|
]
|
|
863
874
|
: []),
|
|
864
875
|
].join("\n"),
|
|
@@ -1003,10 +1014,19 @@ const MAX_SKILL_PAGES = 64;
|
|
|
1003
1014
|
/** How many results a search answers at most: what the deployment allows on one page. */
|
|
1004
1015
|
const MAX_FIND_LIMIT = 25;
|
|
1005
1016
|
|
|
1017
|
+
/** The pack of the project as the console lists it, and what its reads are rendered at; none when the pack did not answer. */
|
|
1018
|
+
async function packOf(
|
|
1019
|
+
project: ProjectClient,
|
|
1020
|
+
): Promise<{ readonly listing: RestSkills; readonly summary: PackSummary | undefined }> {
|
|
1021
|
+
const listing = await project.skills();
|
|
1022
|
+
return { listing, summary: summaryOf(listing) };
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1006
1025
|
const skills: Command = async (args, io) => {
|
|
1007
1026
|
const { values, positionals } = parse(args, {
|
|
1008
1027
|
search: { type: "string" },
|
|
1009
1028
|
limit: { type: "string" },
|
|
1029
|
+
cursor: { type: "string" },
|
|
1010
1030
|
});
|
|
1011
1031
|
if (positionals.length > 1) {
|
|
1012
1032
|
throw misuse("Say one folder: console skills [<folder>] [--search <words>]");
|
|
@@ -1016,8 +1036,11 @@ const skills: Command = async (args, io) => {
|
|
|
1016
1036
|
const folder = given === undefined || given === "/" || given === "." ? undefined : given;
|
|
1017
1037
|
const words = text(values, "search");
|
|
1018
1038
|
const limit = text(values, "limit");
|
|
1019
|
-
|
|
1020
|
-
|
|
1039
|
+
const cursor = text(values, "cursor");
|
|
1040
|
+
if (words === undefined && (limit !== undefined || cursor !== undefined)) {
|
|
1041
|
+
throw misuse(
|
|
1042
|
+
"--limit and --cursor go with --search: console skills --search <words> [--limit <n>] [--cursor <cursor>]",
|
|
1043
|
+
);
|
|
1021
1044
|
}
|
|
1022
1045
|
const atMost = limit === undefined ? undefined : Number(limit);
|
|
1023
1046
|
if (
|
|
@@ -1028,37 +1051,41 @@ const skills: Command = async (args, io) => {
|
|
|
1028
1051
|
}
|
|
1029
1052
|
const session = await open(io, values);
|
|
1030
1053
|
const project = await session.project();
|
|
1054
|
+
const { listing, summary } = await packOf(project);
|
|
1055
|
+
// The pack as it stands; or why it does not answer, which a folder or a search would meet too.
|
|
1056
|
+
if (summary === undefined || (words === undefined && given === undefined)) {
|
|
1057
|
+
answer(io, session, listing, () => formatSkills(listing, io.skillsDir));
|
|
1058
|
+
return EXIT.ok;
|
|
1059
|
+
}
|
|
1031
1060
|
if (words !== undefined) {
|
|
1032
|
-
// One page of what the words find; more is said, and
|
|
1033
|
-
const found = await project.skillFind(words, { path: folder, limit: atMost });
|
|
1034
|
-
answer(io, session, found, () => formatSkillFind(found));
|
|
1061
|
+
// One page of what the words find; more is said, and asked for with --cursor.
|
|
1062
|
+
const found = await project.skillFind(words, { path: folder, limit: atMost, cursor });
|
|
1063
|
+
answer(io, session, found, () => formatSkillFind(found, summary));
|
|
1035
1064
|
return EXIT.ok;
|
|
1036
1065
|
}
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
break;
|
|
1046
|
-
}
|
|
1047
|
-
folders.push(last.folder);
|
|
1048
|
-
if (last.folder.nextCursor === null) {
|
|
1049
|
-
break;
|
|
1050
|
-
}
|
|
1051
|
-
cursor = last.folder.nextCursor;
|
|
1066
|
+
// The folder whole: its pages until the end, as the pack lists them.
|
|
1067
|
+
const pages: RestSkillBrowse[] = [];
|
|
1068
|
+
let next: string | undefined;
|
|
1069
|
+
let last: RestSkillBrowse | undefined;
|
|
1070
|
+
for (let n = 0; n < MAX_SKILL_PAGES; n += 1) {
|
|
1071
|
+
last = await project.skillBrowse({ path: folder, cursor: next });
|
|
1072
|
+
if (last.read?.status !== "ready") {
|
|
1073
|
+
break;
|
|
1052
1074
|
}
|
|
1053
|
-
|
|
1054
|
-
|
|
1075
|
+
pages.push(last);
|
|
1076
|
+
next = last.read.nextCursor ?? undefined;
|
|
1077
|
+
if (next === undefined) {
|
|
1078
|
+
break;
|
|
1055
1079
|
}
|
|
1056
|
-
const browsed = last;
|
|
1057
|
-
answer(io, session, { ...browsed, folders }, () => formatSkillBrowse(browsed, folders));
|
|
1058
|
-
return EXIT.ok;
|
|
1059
1080
|
}
|
|
1060
|
-
|
|
1061
|
-
|
|
1081
|
+
if (last === undefined) {
|
|
1082
|
+
throw failed("The folder could not be read.");
|
|
1083
|
+
}
|
|
1084
|
+
const browsed = last;
|
|
1085
|
+
const whole = joinFolder(pages, summary);
|
|
1086
|
+
answer(io, session, { ...browsed, read: whole === undefined ? null : bodyOfFolder(whole) }, () =>
|
|
1087
|
+
formatSkillBrowse(browsed, whole),
|
|
1088
|
+
);
|
|
1062
1089
|
return EXIT.ok;
|
|
1063
1090
|
};
|
|
1064
1091
|
|
|
@@ -1074,54 +1101,70 @@ const skill: Command = async (args, io) => {
|
|
|
1074
1101
|
}
|
|
1075
1102
|
const session = await open(io, values);
|
|
1076
1103
|
const project = await session.project();
|
|
1104
|
+
const { listing, summary } = await packOf(project);
|
|
1105
|
+
if (summary === undefined) {
|
|
1106
|
+
answer(io, session, listing, () => formatSkills(listing, io.skillsDir));
|
|
1107
|
+
return EXIT.ok;
|
|
1108
|
+
}
|
|
1077
1109
|
if (file !== undefined) {
|
|
1078
|
-
// The file whole, page after page, as the console reads it from the
|
|
1079
|
-
const
|
|
1110
|
+
// The file whole, page after page, as the console reads it from the pack.
|
|
1111
|
+
const pages: RestSkillFile[] = [];
|
|
1080
1112
|
let offset: number | undefined;
|
|
1081
1113
|
let last: RestSkillFile | undefined;
|
|
1082
|
-
for (let
|
|
1114
|
+
for (let n = 0; n < MAX_SKILL_PAGES; n += 1) {
|
|
1083
1115
|
last = await project.skillFile(file, offset === undefined ? {} : { offset });
|
|
1084
|
-
if (last.
|
|
1116
|
+
if (last.read === null) {
|
|
1085
1117
|
break;
|
|
1086
1118
|
}
|
|
1087
|
-
|
|
1088
|
-
if (last.file.nextOffset === null) {
|
|
1119
|
+
pages.push(last);
|
|
1120
|
+
if (last.read.kind !== "file" || last.read.nextOffset === null) {
|
|
1089
1121
|
break;
|
|
1090
1122
|
}
|
|
1091
|
-
offset = last.
|
|
1123
|
+
offset = last.read.nextOffset;
|
|
1092
1124
|
}
|
|
1093
1125
|
if (last === undefined) {
|
|
1094
1126
|
throw failed("The file could not be read.");
|
|
1095
1127
|
}
|
|
1096
|
-
const
|
|
1097
|
-
const
|
|
1098
|
-
answer(io, session, { ...
|
|
1128
|
+
const fileRead = last;
|
|
1129
|
+
const whole = joinFile(pages, summary);
|
|
1130
|
+
answer(io, session, { ...fileRead, read: whole === undefined ? null : bodyOfFile(whole) }, () =>
|
|
1131
|
+
formatSkillFile(fileRead, whole),
|
|
1132
|
+
);
|
|
1099
1133
|
return EXIT.ok;
|
|
1100
1134
|
}
|
|
1101
|
-
const
|
|
1102
|
-
|
|
1103
|
-
|
|
1135
|
+
const wanted = skillPathIn(
|
|
1136
|
+
theOne(
|
|
1137
|
+
positionals,
|
|
1138
|
+
"Say which skill: console skill <path of its SKILL.md>, or console skill --file <path> for a file of the pack",
|
|
1139
|
+
),
|
|
1140
|
+
listing.address,
|
|
1104
1141
|
);
|
|
1142
|
+
if ("error" in wanted) {
|
|
1143
|
+
throw misuse(wanted.error);
|
|
1144
|
+
}
|
|
1105
1145
|
// The skill whole: its pages until complete, the rules first, as load_skill lays them out.
|
|
1106
|
-
const pages:
|
|
1146
|
+
const pages: RestSkillLoad[] = [];
|
|
1107
1147
|
let cursor: string | undefined;
|
|
1108
1148
|
let last: RestSkillLoad | undefined;
|
|
1109
1149
|
for (let n = 0; n < MAX_SKILL_PAGES; n += 1) {
|
|
1110
|
-
last = await project.skill(path, cursor);
|
|
1111
|
-
if (last.status !== "ready"
|
|
1150
|
+
last = await project.skill(wanted.path, cursor);
|
|
1151
|
+
if (last.read?.status !== "ready") {
|
|
1112
1152
|
break;
|
|
1113
1153
|
}
|
|
1114
|
-
pages.push(last
|
|
1115
|
-
|
|
1154
|
+
pages.push(last);
|
|
1155
|
+
cursor = last.read.skill.nextCursor ?? undefined;
|
|
1156
|
+
if (last.read.skill.complete === true || cursor === undefined) {
|
|
1116
1157
|
break;
|
|
1117
1158
|
}
|
|
1118
|
-
cursor = last.skill.nextCursor;
|
|
1119
1159
|
}
|
|
1120
1160
|
if (last === undefined) {
|
|
1121
1161
|
throw failed("The skill could not be read.");
|
|
1122
1162
|
}
|
|
1123
1163
|
const loaded = last;
|
|
1124
|
-
|
|
1164
|
+
const whole = joinSkill(pages, summary);
|
|
1165
|
+
answer(io, session, { ...loaded, read: whole === undefined ? null : bodyOfSkill(whole) }, () =>
|
|
1166
|
+
formatSkillLoad(loaded, whole),
|
|
1167
|
+
);
|
|
1125
1168
|
return EXIT.ok;
|
|
1126
1169
|
};
|
|
1127
1170
|
|
|
@@ -1487,24 +1530,32 @@ const take: Command = async (args, io) => {
|
|
|
1487
1530
|
});
|
|
1488
1531
|
// The rules come with the run, as they read for the person: everything from here acts
|
|
1489
1532
|
// within them (ADR-0023); the task is read again, as it stands now that it is taken.
|
|
1490
|
-
const [ruling, me, taken, comments] = await Promise.all([
|
|
1533
|
+
const [ruling, me, taken, comments, openRuns] = await Promise.all([
|
|
1491
1534
|
project.rules(),
|
|
1492
1535
|
session.client.me(),
|
|
1493
1536
|
project.task(ref),
|
|
1494
1537
|
project.comments(found.id),
|
|
1538
|
+
project.runs({ open: true, mine: true }),
|
|
1495
1539
|
]);
|
|
1496
1540
|
// Taking a task with a run open on it ends that run (ADR-0020): said when it happened.
|
|
1497
1541
|
const tookOver =
|
|
1498
1542
|
found.openRuns > 0
|
|
1499
1543
|
? " A run that was open on it is over now: the board cannot know whether its agent still ran, so taking it was deciding."
|
|
1500
1544
|
: "";
|
|
1545
|
+
// Another run of this token open in the project makes every command on a run ask which
|
|
1546
|
+
// (currentRun): said here, with the id to say, before the first report runs into it.
|
|
1547
|
+
const others = openRuns.items.filter((item) => item.id !== run.id);
|
|
1548
|
+
const elsewhere =
|
|
1549
|
+
others.length === 0
|
|
1550
|
+
? ""
|
|
1551
|
+
: `\nOther runs of yours are open in this project (${others.map((item) => `#${item.taskNumber}`).join(", ")}): say which run on report, hand-in, ask, finish and fail, --run ${run.id} for this one.`;
|
|
1501
1552
|
const rules = {
|
|
1502
1553
|
workspace: forPerson(ruling.workspace, me.language),
|
|
1503
1554
|
project: forPerson(ruling.project, me.language),
|
|
1504
1555
|
};
|
|
1505
1556
|
answer(io, session, { run, task: taken, comments: comments.items, rules }, () =>
|
|
1506
1557
|
[
|
|
1507
|
-
`Run ${run.id} began on #${found.number} ${found.title}, as "${run.agent}" for ${run.person.login}. The task is in progress and theirs.${tookOver}`,
|
|
1558
|
+
`Run ${run.id} began on #${found.number} ${found.title}, as "${run.agent}" for ${run.person.login}. The task is in progress and theirs.${tookOver}${elsewhere}`,
|
|
1508
1559
|
"",
|
|
1509
1560
|
formatTask(taken, undefined, undefined, comments.items),
|
|
1510
1561
|
"",
|
|
@@ -2540,7 +2591,7 @@ const COMMANDS: Readonly<Record<string, Command>> = {
|
|
|
2540
2591
|
|
|
2541
2592
|
function help(io: CliIo, name: string | undefined): number {
|
|
2542
2593
|
if (name === undefined) {
|
|
2543
|
-
io.stdout(usage(io.version));
|
|
2594
|
+
io.stdout(usage(io.version, io.skillsDir));
|
|
2544
2595
|
return EXIT.ok;
|
|
2545
2596
|
}
|
|
2546
2597
|
const found = helpFor(name);
|
|
@@ -2614,7 +2665,7 @@ async function noticeVersions(io: CliIo, seen: ConsoleSeen): Promise<void> {
|
|
|
2614
2665
|
io.stderr(
|
|
2615
2666
|
verdict === "behind"
|
|
2616
2667
|
? `A newer command exists: the console runs ${seen.version}, this command is ${io.version}. Update it: ${updateWords(io, seen.version)}\n`
|
|
2617
|
-
: `This command (${io.version}) is newer than the console (${seen.version}, which takes ${seen.range ?? "an older line"}): what the console has not got yet is refused as not found. The console's operator updates it; to match the console meanwhile: ${updateWords(io, seen.version)}\n`,
|
|
2668
|
+
: `This command (${io.version}) is newer than the console (${seen.version}, which takes ${seen.range ?? "an older line"}): it works, and what the console has not got yet is refused as not found; nothing to do until then. The console's operator updates it; to match the console meanwhile: ${updateWords(io, seen.version)}\n`,
|
|
2618
2669
|
);
|
|
2619
2670
|
await io.notices?.save({
|
|
2620
2671
|
command: io.version,
|