@skillcdn/console 0.1.24 → 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 +64 -65
- 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 -261
- package/dist/cli/format.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +6 -6
- 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/console.css +112 -5
- package/dist/console.d.ts.map +1 -1
- package/dist/console.js +2 -2
- 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/schemas.d.ts +321 -159
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +61 -154
- package/dist/schemas.js.map +1 -1
- package/docs/specs/cli.md +3 -3
- package/docs/specs/rest.md +5 -13
- package/package.json +2 -1
- package/skills/deploying-a-console/SKILL.md +2 -2
- package/skills/working-the-board/SKILL.md +3 -3
- package/src/api.ts +2 -7
- package/src/cli/cli.ts +92 -76
- package/src/cli/format.ts +10 -328
- package/src/cli/help.ts +7 -6
- 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/console.tsx +3 -0
- 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/schemas.ts +76 -180
- package/src/styles/console.css +112 -5
package/src/data.ts
CHANGED
|
@@ -245,6 +245,28 @@ async function readTasks(
|
|
|
245
245
|
return { items };
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
+
/** How many pages of the decisions are read before the record is shown as it stands. */
|
|
249
|
+
const DECISIONS_MAX_PAGES = 20;
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* The decisions of a project, whole: page after page while the server says there is more, so
|
|
253
|
+
* that the record is read to its end and the pages turn it without asking again.
|
|
254
|
+
*/
|
|
255
|
+
async function readDecisions(
|
|
256
|
+
scope: ProjectClient,
|
|
257
|
+
signal: AbortSignal | undefined,
|
|
258
|
+
): Promise<{ readonly items: RestDecision[] }> {
|
|
259
|
+
const items: RestDecision[] = [];
|
|
260
|
+
for (let page = 0; page < DECISIONS_MAX_PAGES; page += 1) {
|
|
261
|
+
const result = await scope.decisions({ limit: LIST_LIMIT, offset: page * LIST_LIMIT }, signal);
|
|
262
|
+
items.push(...result.items);
|
|
263
|
+
if (!result.more) {
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return { items };
|
|
268
|
+
}
|
|
269
|
+
|
|
248
270
|
const wordsOf = (failure: unknown, fallback: string): string =>
|
|
249
271
|
failure instanceof ApiError ? failure.message : fallback;
|
|
250
272
|
|
|
@@ -310,7 +332,7 @@ export function useConsoleData(client: ConsoleClient, projectKey: string | undef
|
|
|
310
332
|
await Promise.all([
|
|
311
333
|
scope.get(signal),
|
|
312
334
|
readTasks(scope, signal),
|
|
313
|
-
scope
|
|
335
|
+
readDecisions(scope, signal),
|
|
314
336
|
scope.goals({}, signal),
|
|
315
337
|
scope.runs(undefined, signal),
|
|
316
338
|
scope.members(signal),
|
|
@@ -427,7 +449,15 @@ export function useConsoleData(client: ConsoleClient, projectKey: string | undef
|
|
|
427
449
|
// No answer at all is said on the page as the deployment being out of reach,
|
|
428
450
|
// rather than waited for.
|
|
429
451
|
if (!signal.aborted) {
|
|
430
|
-
setSkills({
|
|
452
|
+
setSkills({
|
|
453
|
+
address: null,
|
|
454
|
+
source: "",
|
|
455
|
+
page: null,
|
|
456
|
+
status: "unavailable",
|
|
457
|
+
refusal: null,
|
|
458
|
+
items: [],
|
|
459
|
+
mount: null,
|
|
460
|
+
});
|
|
431
461
|
}
|
|
432
462
|
});
|
|
433
463
|
if (typeof EventSource === "undefined") {
|
package/src/i18n/en.ts
CHANGED
|
@@ -9,6 +9,7 @@ import type {
|
|
|
9
9
|
ProjectVisibility,
|
|
10
10
|
ProviderKey,
|
|
11
11
|
RunStatus,
|
|
12
|
+
SkillsStatus,
|
|
12
13
|
TaskPriority,
|
|
13
14
|
TaskState,
|
|
14
15
|
} from "../vocabulary.js";
|
|
@@ -102,6 +103,12 @@ export const en = {
|
|
|
102
103
|
copy: "Copy",
|
|
103
104
|
copied: "Copied",
|
|
104
105
|
showMore: (n: number, of: number) => `Show ${n} more of ${of}`,
|
|
106
|
+
pager: {
|
|
107
|
+
label: "Pages",
|
|
108
|
+
previous: "Previous page",
|
|
109
|
+
next: "Next page",
|
|
110
|
+
range: (from: number, to: number, of: number) => `${from}-${to} of ${of}`,
|
|
111
|
+
},
|
|
105
112
|
},
|
|
106
113
|
|
|
107
114
|
nav: {
|
|
@@ -325,6 +332,9 @@ export const en = {
|
|
|
325
332
|
waitingForPerson: "Waiting for a person.",
|
|
326
333
|
options: "Options",
|
|
327
334
|
notePlaceholder: "A word about it, if any",
|
|
335
|
+
own: "Something else",
|
|
336
|
+
ownPlaceholder: "Your answer, in a line",
|
|
337
|
+
ownAnswer: "in their own words",
|
|
328
338
|
answer: "Answer",
|
|
329
339
|
asked: "asked",
|
|
330
340
|
askedThrough: (agent: string) => `asked through ${agent}`,
|
|
@@ -662,6 +672,14 @@ export const en = {
|
|
|
662
672
|
connect:
|
|
663
673
|
"An agent reads these with the console command (console skill <path>), or through its own MCP connection to this address, which a person makes once:",
|
|
664
674
|
connectLink: "how, on the address's page at SkillCDN",
|
|
675
|
+
fromMachine: "Read from a directory on the console's machine, at",
|
|
676
|
+
connectLocal:
|
|
677
|
+
"An agent reads these with the console command (console skill <path>); the pack is on the console's machine and nowhere else.",
|
|
678
|
+
localStatus: {
|
|
679
|
+
not_found:
|
|
680
|
+
"No pack is served from the console's machine at this address: whoever runs the console puts it in the packs directory, as <owner>/<name>.",
|
|
681
|
+
unavailable: "The pack could not be read from the console's machine. Look again later.",
|
|
682
|
+
} as Partial<Record<SkillsStatus, string>>,
|
|
665
683
|
status: {
|
|
666
684
|
indexing: "SkillCDN is still indexing the repository. Look again in a moment.",
|
|
667
685
|
failed: "SkillCDN could not index the repository. What it found is on the address's page.",
|
package/src/i18n/ko.ts
CHANGED
|
@@ -72,6 +72,12 @@ export const ko: Messages = {
|
|
|
72
72
|
copy: "복사",
|
|
73
73
|
copied: "복사됨",
|
|
74
74
|
showMore: (n, of) => `${of}개 중 ${n}개 더 보기`,
|
|
75
|
+
pager: {
|
|
76
|
+
label: "페이지",
|
|
77
|
+
previous: "이전",
|
|
78
|
+
next: "다음",
|
|
79
|
+
range: (from, to, of) => `${of}건 중 ${from}-${to}`,
|
|
80
|
+
},
|
|
75
81
|
},
|
|
76
82
|
|
|
77
83
|
nav: {
|
|
@@ -294,6 +300,9 @@ export const ko: Messages = {
|
|
|
294
300
|
waitingForPerson: "사람을 기다리는 중입니다.",
|
|
295
301
|
options: "선택지",
|
|
296
302
|
notePlaceholder: "덧붙일 말이 있다면",
|
|
303
|
+
own: "직접 입력",
|
|
304
|
+
ownPlaceholder: "원하는 답을 한 줄로",
|
|
305
|
+
ownAnswer: "직접 입력",
|
|
297
306
|
answer: "답변",
|
|
298
307
|
asked: "질문",
|
|
299
308
|
askedThrough: (agent) => `${agent}을(를) 통해 질문`,
|
|
@@ -626,6 +635,14 @@ export const ko: Messages = {
|
|
|
626
635
|
connect:
|
|
627
636
|
"에이전트는 콘솔 명령(console skill <경로>)으로, 또는 이 주소에 자기 MCP 연결로 스킬을 받습니다. MCP 연결은 사람이 한 번 해 줍니다:",
|
|
628
637
|
connectLink: "SkillCDN 페이지의 연결 안내",
|
|
638
|
+
fromMachine: "콘솔 기계의 디렉터리에서 읽음, 주소:",
|
|
639
|
+
connectLocal:
|
|
640
|
+
"에이전트는 콘솔 명령(console skill <경로>)으로 읽습니다. 이 팩은 콘솔 기계에만 있습니다.",
|
|
641
|
+
localStatus: {
|
|
642
|
+
not_found:
|
|
643
|
+
"이 주소로 콘솔 기계에서 제공되는 팩이 없습니다. 콘솔 운영자가 팩 디렉터리에 <owner>/<name>으로 넣습니다.",
|
|
644
|
+
unavailable: "콘솔 기계에서 팩을 읽지 못했습니다. 나중에 다시 보세요.",
|
|
645
|
+
},
|
|
629
646
|
status: {
|
|
630
647
|
indexing: "SkillCDN이 아직 저장소를 색인하고 있습니다. 잠시 후 다시 보세요.",
|
|
631
648
|
failed: "SkillCDN이 저장소를 색인하지 못했습니다. 찾은 내용은 주소의 페이지에 있습니다.",
|
package/src/index.ts
CHANGED
|
@@ -82,7 +82,14 @@ export {
|
|
|
82
82
|
goalMonth,
|
|
83
83
|
} from "./components/goals.js";
|
|
84
84
|
export { Markdown, type MarkdownProps } from "./components/markdown.js";
|
|
85
|
-
export {
|
|
85
|
+
export {
|
|
86
|
+
PAGE_SIZE,
|
|
87
|
+
Pager,
|
|
88
|
+
pageOf,
|
|
89
|
+
RECORD_PAGE_SIZE,
|
|
90
|
+
ShowMore,
|
|
91
|
+
usePaged,
|
|
92
|
+
} from "./components/paged.js";
|
|
86
93
|
export {
|
|
87
94
|
ListingForm,
|
|
88
95
|
type ListingFormProps,
|
|
@@ -246,6 +253,7 @@ export {
|
|
|
246
253
|
customPageHref,
|
|
247
254
|
type DocsView,
|
|
248
255
|
decisionHref,
|
|
256
|
+
decisionsHref,
|
|
249
257
|
docHref,
|
|
250
258
|
GOAL_TASK_VIEWS,
|
|
251
259
|
type GoalPageOptions,
|
package/src/router.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { isDay, isMonth } from "./dates.js";
|
|
|
5
5
|
// route, and the hrefs below are its inverse. A project's pages live under `/projects/<key>`,
|
|
6
6
|
// the word the REST API uses; an address names what it shows (a task by its number, a decision
|
|
7
7
|
// by its id, a document by its path, a goal by its id), every form has one, and the query says
|
|
8
|
-
// how a page is shown (`?edit`, `?ask`, `?new`, `?version=`, `?q=`, `?month=`, `?week=`, and the
|
|
8
|
+
// how a page is shown (`?edit`, `?ask`, `?new`, `?version=`, `?q=`, `?month=`, `?week=`, `?page=`, and the
|
|
9
9
|
// board's filters). The old addresses are taken to the new.
|
|
10
10
|
|
|
11
11
|
/** How a task's page is shown: as it is, or with one of its forms open. */
|
|
@@ -49,7 +49,8 @@ export type Route =
|
|
|
49
49
|
readonly path: string;
|
|
50
50
|
readonly view: DocsView;
|
|
51
51
|
}
|
|
52
|
-
|
|
52
|
+
/** The decisions of a project: the waiting ones, and the record on one of its pages, the first when the address names none. */
|
|
53
|
+
| { readonly name: "decisions"; readonly project: string; readonly page: number | undefined }
|
|
53
54
|
| { readonly name: "new-decision"; readonly project: string }
|
|
54
55
|
| { readonly name: "decision"; readonly project: string; readonly id: string }
|
|
55
56
|
/** The calendar of a project: the month shown, or this one when the address names none, narrowed as the board is. */
|
|
@@ -155,13 +156,10 @@ const NUMBER = /^[1-9][0-9]{0,8}$/;
|
|
|
155
156
|
/** A code as it may be typed into an address: checked for what it is by the page. */
|
|
156
157
|
const CODE_TEXT = /^[A-Za-z0-9-]{1,16}$/;
|
|
157
158
|
/** The pages of a project that take nothing after their name. */
|
|
158
|
-
const PLAIN_PAGES: readonly Exclude<
|
|
159
|
-
|
|
160
|
-
"
|
|
161
|
-
|
|
162
|
-
"skills",
|
|
163
|
-
"members",
|
|
164
|
-
];
|
|
159
|
+
const PLAIN_PAGES: readonly Exclude<
|
|
160
|
+
ProjectPage,
|
|
161
|
+
"docs" | "decisions" | "calendar" | "roadmap" | "settings"
|
|
162
|
+
>[] = ["archive", "feed", "skills", "members"];
|
|
165
163
|
const NOT_FOUND: Route = { name: "not-found" };
|
|
166
164
|
|
|
167
165
|
/** Where an address of the 0.1 line before this one leads now, or nothing for a current one. */
|
|
@@ -386,6 +384,13 @@ export function matchRoute(pathname: string, search = ""): Route {
|
|
|
386
384
|
: undefined,
|
|
387
385
|
};
|
|
388
386
|
}
|
|
387
|
+
if (page === "decisions") {
|
|
388
|
+
const turned = params.get("page");
|
|
389
|
+
if (turned !== null && !NUMBER.test(turned)) {
|
|
390
|
+
return NOT_FOUND;
|
|
391
|
+
}
|
|
392
|
+
return { name: "decisions", project, page: turned === null ? undefined : Number(turned) };
|
|
393
|
+
}
|
|
389
394
|
const found = PLAIN_PAGES.find((candidate) => candidate === page);
|
|
390
395
|
return found === undefined ? NOT_FOUND : { name: found, project };
|
|
391
396
|
}
|
|
@@ -469,6 +474,12 @@ export function decisionHref(key: string, id: string): string {
|
|
|
469
474
|
return `${PATHS.project}/${key}/decisions/${id}`;
|
|
470
475
|
}
|
|
471
476
|
|
|
477
|
+
/** Where a project's decisions are: the waiting ones and the record, on one of its pages, or on the first when none is named. */
|
|
478
|
+
export function decisionsHref(key: string, page?: number): string {
|
|
479
|
+
const base = projectHref(key, "decisions");
|
|
480
|
+
return page === undefined || page <= 1 ? base : `${base}?page=${page}`;
|
|
481
|
+
}
|
|
482
|
+
|
|
472
483
|
/** Where the person's own work is, with the week of a day at the top, or this week's when none is named. */
|
|
473
484
|
export function workHref(week?: string): string {
|
|
474
485
|
return week === undefined ? PATHS.work : `${PATHS.work}?week=${week}`;
|
package/src/schemas.ts
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
// most of what a page downloads. The server validates what it is sent with the input schemas
|
|
3
3
|
// and builds the output shapes; the pages and a custom console parse answers with the rest.
|
|
4
4
|
// Absent values are `null` on the wire, never missing keys. Changes within a version are additive.
|
|
5
|
+
import {
|
|
6
|
+
restBrowseSchema as packBrowseSchema,
|
|
7
|
+
restFileSchema as packFileSchema,
|
|
8
|
+
restFindSchema as packFindSchema,
|
|
9
|
+
restMountSchema as packMountSchema,
|
|
10
|
+
restSkillSchema as packSkillSchema,
|
|
11
|
+
} from "@skillcdn/core";
|
|
5
12
|
import * as z from "zod/mini";
|
|
6
13
|
import { isDocumentPath } from "./documents.js";
|
|
7
14
|
import {
|
|
@@ -548,9 +555,15 @@ export const restGoalPatchSchema = z.object({
|
|
|
548
555
|
export type RestGoalPatch = z.infer<typeof restGoalPatchSchema>;
|
|
549
556
|
|
|
550
557
|
export const restDecisionOptionSchema = z.object({
|
|
551
|
-
/** What an answer names: stable
|
|
558
|
+
/** What an answer names: stable once given. */
|
|
552
559
|
id: z.string(),
|
|
553
560
|
label: z.string(),
|
|
561
|
+
/**
|
|
562
|
+
* On the one option a person's own answer became, when they answered in their own words
|
|
563
|
+
* instead of choosing (`POST .../answer` with `own`): added then, after the options given,
|
|
564
|
+
* which carry no `own`.
|
|
565
|
+
*/
|
|
566
|
+
own: z.optional(z.literal(true)),
|
|
554
567
|
});
|
|
555
568
|
export type RestDecisionOption = z.infer<typeof restDecisionOptionSchema>;
|
|
556
569
|
|
|
@@ -646,11 +659,24 @@ export const restDecisionPatchSchema = z.object({
|
|
|
646
659
|
});
|
|
647
660
|
export type RestDecisionPatch = z.infer<typeof restDecisionPatchSchema>;
|
|
648
661
|
|
|
649
|
-
/**
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
662
|
+
/**
|
|
663
|
+
* What `POST .../decisions/<id>/answer` is sent: one of the options by its id, or the person's
|
|
664
|
+
* own answer in a line, one of the two; and a word about either.
|
|
665
|
+
*/
|
|
666
|
+
export const restAnswerInputSchema = z
|
|
667
|
+
.object({
|
|
668
|
+
/** The id of the chosen option. */
|
|
669
|
+
option: z.optional(z.string().check(z.minLength(1), z.maxLength(64))),
|
|
670
|
+
/** The person's own answer, when none of the options is it: one line, worded as an option is. */
|
|
671
|
+
own: z.optional(line(MAX_OPTION_LABEL_LENGTH)),
|
|
672
|
+
note: z.optional(paragraphs(MAX_NOTE_LENGTH)),
|
|
673
|
+
})
|
|
674
|
+
.check(
|
|
675
|
+
z.refine(
|
|
676
|
+
(input) => (input.option === undefined) !== (input.own === undefined),
|
|
677
|
+
"must name an option or give an answer of its own, one of the two",
|
|
678
|
+
),
|
|
679
|
+
);
|
|
654
680
|
export type RestAnswerInput = z.infer<typeof restAnswerInputSchema>;
|
|
655
681
|
|
|
656
682
|
/**
|
|
@@ -894,15 +920,39 @@ export const restClaimSchema = z.union([
|
|
|
894
920
|
]);
|
|
895
921
|
export type RestClaim = z.infer<typeof restClaimSchema>;
|
|
896
922
|
|
|
897
|
-
/**
|
|
923
|
+
/** Why a pack did not answer a read: the code and the words the deployment, or the console reading a directory, gave, as the main repository's API spells them. */
|
|
924
|
+
export const restPackRefusalSchema = z.object({
|
|
925
|
+
code: z.string(),
|
|
926
|
+
message: z.string(),
|
|
927
|
+
/** With a file the pack will not carry: where it is at its source, or `null`. */
|
|
928
|
+
sourceUrl: z.nullable(z.string()),
|
|
929
|
+
/** With `skill.ambiguous`: the directories to choose from. */
|
|
930
|
+
directories: z.array(z.string()),
|
|
931
|
+
});
|
|
932
|
+
export type RestPackRefusal = z.infer<typeof restPackRefusalSchema>;
|
|
933
|
+
|
|
934
|
+
/** What every answer about a pack says first: its address, where it is read, and how the read went. */
|
|
935
|
+
const packEnvelope = {
|
|
936
|
+
/** The address, canonical, or `null` when neither the project nor the console names one. */
|
|
937
|
+
address: z.nullable(z.string()),
|
|
938
|
+
/** The origin of the SkillCDN deployment the pack is read at; `null` for a pack read from a directory on the console's machine (ADR-0031). */
|
|
939
|
+
source: z.nullable(z.string()),
|
|
940
|
+
/** Where a person browses the address at the deployment, or `null` without one. */
|
|
941
|
+
page: z.nullable(z.string()),
|
|
942
|
+
status: z.enum(SKILLS_STATUSES),
|
|
943
|
+
/** Why the read did not happen, in the pack's own words, when `status` says it did not; `null` otherwise. */
|
|
944
|
+
refusal: z.nullable(restPackRefusalSchema),
|
|
945
|
+
};
|
|
946
|
+
|
|
947
|
+
/** One of the project's skills, as the pack lists it: what the repository says of it, where a person reads it, what an agent loads it by. */
|
|
898
948
|
export const restSkillSchema = z.object({
|
|
899
949
|
name: z.string(),
|
|
900
950
|
description: z.string(),
|
|
901
951
|
/** The skill's folder in the repository (`""` for the root), and the path of its `SKILL.md`. */
|
|
902
952
|
directory: z.string(),
|
|
903
953
|
path: z.string(),
|
|
904
|
-
/** Where a person reads the skill: its page at the deployment. */
|
|
905
|
-
page: z.string(),
|
|
954
|
+
/** Where a person reads the skill: its page at the deployment, or `null` for a pack read from a directory. */
|
|
955
|
+
page: z.nullable(z.string()),
|
|
906
956
|
/** What an agent loads the skill by, through its own SkillCDN connection; `null` when the path is not one. */
|
|
907
957
|
uri: z.nullable(z.string()),
|
|
908
958
|
/** The title and the description in other languages, by language tag, as the repository gives them. */
|
|
@@ -913,15 +963,9 @@ export const restSkillSchema = z.object({
|
|
|
913
963
|
});
|
|
914
964
|
export type RestSkill = z.infer<typeof restSkillSchema>;
|
|
915
965
|
|
|
916
|
-
/** `GET /api/v1/projects/<key>/skills`: the project's
|
|
966
|
+
/** `GET /api/v1/projects/<key>/skills`: the project's pack, read by address (ADR-0028, ADR-0031). */
|
|
917
967
|
export const restSkillsSchema = z.object({
|
|
918
|
-
|
|
919
|
-
address: z.nullable(z.string()),
|
|
920
|
-
/** The origin of the SkillCDN deployment the skills are read through. */
|
|
921
|
-
source: z.string(),
|
|
922
|
-
/** Where a person browses the address, or `null` without one. */
|
|
923
|
-
page: z.nullable(z.string()),
|
|
924
|
-
status: z.enum(SKILLS_STATUSES),
|
|
968
|
+
...packEnvelope,
|
|
925
969
|
/** The pack as its manifest or its README names it, when `ready`: what it is called, what it is for, the language it is written in. */
|
|
926
970
|
pack: z.optional(
|
|
927
971
|
z.object({
|
|
@@ -930,10 +974,12 @@ export const restSkillsSchema = z.object({
|
|
|
930
974
|
language: z.nullable(z.string()),
|
|
931
975
|
}),
|
|
932
976
|
),
|
|
933
|
-
/** How many skills and documents the
|
|
977
|
+
/** How many skills and documents the index found at the address, when `ready`. */
|
|
934
978
|
counts: z.optional(z.object({ skills: count, documents: count })),
|
|
935
979
|
/** The skills, when `ready`; empty otherwise. */
|
|
936
980
|
items: z.array(restSkillSchema),
|
|
981
|
+
/** What the address serves, as the main repository's REST API answers it (`RestMount` of `@skillcdn/core`), for a program that renders what a model is given; `null` when nothing was answered. */
|
|
982
|
+
mount: z.nullable(packMountSchema),
|
|
937
983
|
});
|
|
938
984
|
export type RestSkills = z.infer<typeof restSkillsSchema>;
|
|
939
985
|
|
|
@@ -945,181 +991,31 @@ export const restPackTokenInputSchema = z.object({
|
|
|
945
991
|
});
|
|
946
992
|
export type RestPackTokenInput = z.infer<typeof restPackTokenInputSchema>;
|
|
947
993
|
|
|
948
|
-
/**
|
|
949
|
-
export const restSkillTextSchema = z.object({
|
|
950
|
-
path: z.string(),
|
|
951
|
-
body: z.string(),
|
|
952
|
-
truncated: z.boolean(),
|
|
953
|
-
});
|
|
954
|
-
/** A skill as the deployment serves it, on one page of its context: what `load_skill` gives a model, in the console's shape. */
|
|
955
|
-
export const restSkillPageSchema = z.object({
|
|
956
|
-
path: z.string(),
|
|
957
|
-
directory: z.string(),
|
|
958
|
-
name: z.string(),
|
|
959
|
-
description: z.string(),
|
|
960
|
-
/** The rules that hold for the skill, from the repository's root to the nearest manifest. */
|
|
961
|
-
rules: z.array(restSkillTextSchema),
|
|
962
|
-
body: z.string(),
|
|
963
|
-
/** The files the skill includes with its body. */
|
|
964
|
-
included: z.array(restSkillTextSchema),
|
|
965
|
-
/** The paths of the skill's own files, read with the file route. */
|
|
966
|
-
files: z.array(z.string()),
|
|
967
|
-
references: z.array(
|
|
968
|
-
z.object({
|
|
969
|
-
path: z.string(),
|
|
970
|
-
status: z.enum(["available", "blocked", "missing", "outside_mount"]),
|
|
971
|
-
}),
|
|
972
|
-
),
|
|
973
|
-
/** Whether this page completes the skill; else the cursor of the next. */
|
|
974
|
-
complete: z.boolean(),
|
|
975
|
-
nextCursor: z.nullable(z.string()),
|
|
976
|
-
/** How the skill is served: whole, or described only, with its license and where it is read at its host. */
|
|
977
|
-
serving: z.object({
|
|
978
|
-
full: z.boolean(),
|
|
979
|
-
license: z.nullable(z.string()),
|
|
980
|
-
sourceUrl: z.nullable(z.string()),
|
|
981
|
-
}),
|
|
982
|
-
warnings: z.array(z.string()),
|
|
983
|
-
});
|
|
984
|
-
export type RestSkillPage = z.infer<typeof restSkillPageSchema>;
|
|
985
|
-
|
|
986
|
-
/** `GET .../skills/one?path=&cursor=`: one skill of the pack, a page of it; `skill` is `null` unless `ready`. */
|
|
994
|
+
/** `GET .../skills/one?path=&cursor=`: a page of a skill's context, as the pack answers `load_skill` (`RestSkill` of `@skillcdn/core`); `read` is `null` unless `ready`. */
|
|
987
995
|
export const restSkillLoadSchema = z.object({
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
page: z.nullable(z.string()),
|
|
991
|
-
status: z.enum(SKILLS_STATUSES),
|
|
992
|
-
skill: z.nullable(restSkillPageSchema),
|
|
996
|
+
...packEnvelope,
|
|
997
|
+
read: z.nullable(packSkillSchema),
|
|
993
998
|
});
|
|
994
999
|
export type RestSkillLoad = z.infer<typeof restSkillLoadSchema>;
|
|
995
1000
|
|
|
996
|
-
/** `GET .../skills/file?path=&offset=&limit=`: a page of a file
|
|
1001
|
+
/** `GET .../skills/file?path=&offset=&limit=`: a page of a file, or what a folder holds, as the pack answers `read_repo_file` (`RestFile` of `@skillcdn/core`); `read` is `null` unless `ready`. */
|
|
997
1002
|
export const restSkillFileSchema = z.object({
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
status: z.enum(SKILLS_STATUSES),
|
|
1001
|
-
file: z.nullable(
|
|
1002
|
-
z.object({
|
|
1003
|
-
path: z.string(),
|
|
1004
|
-
content: z.string(),
|
|
1005
|
-
offset: count,
|
|
1006
|
-
nextOffset: z.nullable(count),
|
|
1007
|
-
totalLength: count,
|
|
1008
|
-
}),
|
|
1009
|
-
),
|
|
1010
|
-
folder: z.nullable(
|
|
1011
|
-
z.object({
|
|
1012
|
-
path: z.string(),
|
|
1013
|
-
entries: z.array(
|
|
1014
|
-
z.object({
|
|
1015
|
-
path: z.string(),
|
|
1016
|
-
kind: z.enum(["directory", "file"]),
|
|
1017
|
-
size: z.nullable(count),
|
|
1018
|
-
}),
|
|
1019
|
-
),
|
|
1020
|
-
truncated: z.boolean(),
|
|
1021
|
-
}),
|
|
1022
|
-
),
|
|
1003
|
+
...packEnvelope,
|
|
1004
|
+
read: z.nullable(packFileSchema),
|
|
1023
1005
|
});
|
|
1024
1006
|
export type RestSkillFile = z.infer<typeof restSkillFileSchema>;
|
|
1025
1007
|
|
|
1026
|
-
/**
|
|
1027
|
-
export const restSkillBrowseEntrySchema = z.object({
|
|
1028
|
-
kind: z.enum(["skill", "directory", "file"]),
|
|
1029
|
-
/** The path from the repository's root: of the `SKILL.md` for a skill, of the folder, of the file. */
|
|
1030
|
-
path: z.string(),
|
|
1031
|
-
name: z.nullable(z.string()),
|
|
1032
|
-
description: z.nullable(z.string()),
|
|
1033
|
-
/** For a folder: the skills and the documents under it. */
|
|
1034
|
-
skillCount: count,
|
|
1035
|
-
documentCount: count,
|
|
1036
|
-
/** For a file: its size in bytes. */
|
|
1037
|
-
size: z.nullable(count),
|
|
1038
|
-
/** For a folder: the README that introduces it, read with the file route. */
|
|
1039
|
-
overviewPath: z.nullable(z.string()),
|
|
1040
|
-
/** For a skill: its license, and whether the address only describes it. */
|
|
1041
|
-
license: z.nullable(z.string()),
|
|
1042
|
-
describedOnly: z.boolean(),
|
|
1043
|
-
});
|
|
1044
|
-
export type RestSkillBrowseEntry = z.infer<typeof restSkillBrowseEntrySchema>;
|
|
1045
|
-
|
|
1046
|
-
/** `GET .../skills/browse?path=&cursor=&limit=`: what a folder of the pack holds, a page of it (`browse_repo`); `folder` is `null` unless `ready`. */
|
|
1008
|
+
/** `GET .../skills/browse?path=&cursor=&limit=`: what a folder holds, a page of it, as the pack answers `browse_repo` (`RestBrowse` of `@skillcdn/core`); `read` is `null` unless `ready`. */
|
|
1047
1009
|
export const restSkillBrowseSchema = z.object({
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
page: z.nullable(z.string()),
|
|
1051
|
-
status: z.enum(SKILLS_STATUSES),
|
|
1052
|
-
folder: z.nullable(
|
|
1053
|
-
z.object({
|
|
1054
|
-
path: z.string(),
|
|
1055
|
-
/** The README that introduces the folder, or `null`. */
|
|
1056
|
-
overview: z.nullable(
|
|
1057
|
-
z.object({
|
|
1058
|
-
path: z.string(),
|
|
1059
|
-
title: z.nullable(z.string()),
|
|
1060
|
-
description: z.nullable(z.string()),
|
|
1061
|
-
}),
|
|
1062
|
-
),
|
|
1063
|
-
entries: z.array(restSkillBrowseEntrySchema),
|
|
1064
|
-
/** Where the listing goes on, or `null` at its end. */
|
|
1065
|
-
nextCursor: z.nullable(z.string()),
|
|
1066
|
-
}),
|
|
1067
|
-
),
|
|
1010
|
+
...packEnvelope,
|
|
1011
|
+
read: z.nullable(packBrowseSchema),
|
|
1068
1012
|
});
|
|
1069
1013
|
export type RestSkillBrowse = z.infer<typeof restSkillBrowseSchema>;
|
|
1070
1014
|
|
|
1071
|
-
/**
|
|
1072
|
-
export const restSkillFindItemSchema = z.discriminatedUnion("kind", [
|
|
1073
|
-
z.object({
|
|
1074
|
-
kind: z.literal("skill"),
|
|
1075
|
-
name: z.string(),
|
|
1076
|
-
description: z.string(),
|
|
1077
|
-
directory: z.string(),
|
|
1078
|
-
path: z.string(),
|
|
1079
|
-
page: z.string(),
|
|
1080
|
-
uri: z.nullable(z.string()),
|
|
1081
|
-
translations: z.record(
|
|
1082
|
-
z.string(),
|
|
1083
|
-
z.object({ title: z.nullable(z.string()), description: z.nullable(z.string()) }),
|
|
1084
|
-
),
|
|
1085
|
-
/** The files of the skill that matched, a few, and how many more did. */
|
|
1086
|
-
files: z.array(
|
|
1087
|
-
z.object({
|
|
1088
|
-
path: z.string(),
|
|
1089
|
-
title: z.nullable(z.string()),
|
|
1090
|
-
summary: z.nullable(z.string()),
|
|
1091
|
-
}),
|
|
1092
|
-
),
|
|
1093
|
-
moreFiles: count,
|
|
1094
|
-
license: z.nullable(z.string()),
|
|
1095
|
-
describedOnly: z.boolean(),
|
|
1096
|
-
}),
|
|
1097
|
-
z.object({
|
|
1098
|
-
kind: z.literal("document"),
|
|
1099
|
-
path: z.string(),
|
|
1100
|
-
title: z.nullable(z.string()),
|
|
1101
|
-
summary: z.nullable(z.string()),
|
|
1102
|
-
/** The folder of the skill the document belongs to, or `null` for one on its own. */
|
|
1103
|
-
skillDirectory: z.nullable(z.string()),
|
|
1104
|
-
}),
|
|
1105
|
-
]);
|
|
1106
|
-
export type RestSkillFindItem = z.infer<typeof restSkillFindItemSchema>;
|
|
1107
|
-
|
|
1108
|
-
/** `GET .../skills/find?query=&path=&cursor=&limit=`: what words find in the pack, a page of it in relevance order (`search_repo`); `found` is `null` unless `ready`. */
|
|
1015
|
+
/** `GET .../skills/find?query=&path=&cursor=&limit=`: what words find, a page of it in relevance order, as the pack answers `search_repo` (`RestFind` of `@skillcdn/core`); `read` is `null` unless `ready`. */
|
|
1109
1016
|
export const restSkillFindSchema = z.object({
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
page: z.nullable(z.string()),
|
|
1113
|
-
status: z.enum(SKILLS_STATUSES),
|
|
1114
|
-
found: z.nullable(
|
|
1115
|
-
z.object({
|
|
1116
|
-
query: z.string(),
|
|
1117
|
-
/** The folder the search was kept to, or `null` for the whole pack. */
|
|
1118
|
-
path: z.nullable(z.string()),
|
|
1119
|
-
items: z.array(restSkillFindItemSchema),
|
|
1120
|
-
nextCursor: z.nullable(z.string()),
|
|
1121
|
-
}),
|
|
1122
|
-
),
|
|
1017
|
+
...packEnvelope,
|
|
1018
|
+
read: z.nullable(packFindSchema),
|
|
1123
1019
|
});
|
|
1124
1020
|
export type RestSkillFind = z.infer<typeof restSkillFindSchema>;
|
|
1125
1021
|
|