@skillcdn/console 0.1.17 → 0.1.19
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 +4 -4
- package/SKILLCDN.md +1 -1
- package/dist/api.d.ts +3 -2
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +2 -1
- package/dist/api.js.map +1 -1
- package/dist/cli/cli.d.ts +11 -1
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +496 -51
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/credentials.d.ts +102 -3
- package/dist/cli/credentials.d.ts.map +1 -1
- package/dist/cli/credentials.js +177 -8
- package/dist/cli/credentials.js.map +1 -1
- package/dist/cli/directory.d.ts +6 -0
- package/dist/cli/directory.d.ts.map +1 -1
- package/dist/cli/directory.js +37 -6
- package/dist/cli/directory.js.map +1 -1
- package/dist/cli/format.d.ts +11 -2
- package/dist/cli/format.d.ts.map +1 -1
- package/dist/cli/format.js +114 -5
- package/dist/cli/format.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +49 -25
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/install.d.ts +21 -0
- package/dist/cli/install.d.ts.map +1 -0
- package/dist/cli/install.js +87 -0
- package/dist/cli/install.js.map +1 -0
- package/dist/cli/main.js +22 -3
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/notices.d.ts +13 -0
- package/dist/cli/notices.d.ts.map +1 -0
- package/dist/cli/notices.js +31 -0
- package/dist/cli/notices.js.map +1 -0
- package/dist/client.d.ts +36 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +22 -4
- package/dist/client.js.map +1 -1
- package/dist/compat.d.ts +66 -0
- package/dist/compat.d.ts.map +1 -0
- package/dist/compat.js +115 -0
- package/dist/compat.js.map +1 -0
- package/dist/components/board.d.ts +9 -1
- package/dist/components/board.d.ts.map +1 -1
- package/dist/components/board.js +82 -5
- package/dist/components/board.js.map +1 -1
- package/dist/components/calendar.d.ts +3 -1
- package/dist/components/calendar.d.ts.map +1 -1
- package/dist/components/calendar.js +21 -2
- package/dist/components/calendar.js.map +1 -1
- package/dist/components/comments.d.ts.map +1 -1
- package/dist/components/comments.js +12 -4
- package/dist/components/comments.js.map +1 -1
- package/dist/components/event-feed.d.ts.map +1 -1
- package/dist/components/event-feed.js +4 -0
- package/dist/components/event-feed.js.map +1 -1
- package/dist/components/goals.d.ts +20 -2
- package/dist/components/goals.d.ts.map +1 -1
- package/dist/components/goals.js +50 -13
- package/dist/components/goals.js.map +1 -1
- package/dist/components/markdown.d.ts +6 -0
- package/dist/components/markdown.d.ts.map +1 -1
- package/dist/components/markdown.js +7 -0
- package/dist/components/markdown.js.map +1 -1
- package/dist/components/pictures.d.ts +68 -0
- package/dist/components/pictures.d.ts.map +1 -0
- package/dist/components/pictures.js +213 -0
- package/dist/components/pictures.js.map +1 -0
- package/dist/components/projects.d.ts +12 -0
- package/dist/components/projects.d.ts.map +1 -1
- package/dist/components/projects.js +15 -0
- package/dist/components/projects.js.map +1 -1
- package/dist/components/roadmap.d.ts +37 -0
- package/dist/components/roadmap.d.ts.map +1 -0
- package/dist/components/roadmap.js +76 -0
- package/dist/components/roadmap.js.map +1 -0
- package/dist/components/task-view.d.ts +3 -0
- package/dist/components/task-view.d.ts.map +1 -1
- package/dist/components/task-view.js +6 -4
- package/dist/components/task-view.js.map +1 -1
- package/dist/components/tokens.d.ts +2 -0
- package/dist/components/tokens.d.ts.map +1 -1
- package/dist/components/tokens.js +13 -3
- package/dist/components/tokens.js.map +1 -1
- package/dist/console.css +486 -3
- package/dist/console.d.ts.map +1 -1
- package/dist/console.js +132 -17
- package/dist/console.js.map +1 -1
- package/dist/data.d.ts +16 -1
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +48 -3
- package/dist/data.js.map +1 -1
- package/dist/i18n/en.d.ts +76 -0
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +74 -2
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/ko.d.ts.map +1 -1
- package/dist/i18n/ko.js +74 -2
- package/dist/i18n/ko.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/router.d.ts +31 -7
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +48 -8
- package/dist/router.js.map +1 -1
- package/dist/rules.js +5 -5
- package/dist/rules.js.map +1 -1
- package/dist/schemas.d.ts +200 -0
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +96 -0
- package/dist/schemas.js.map +1 -1
- package/dist/vocabulary.d.ts +2 -2
- package/dist/vocabulary.d.ts.map +1 -1
- package/dist/vocabulary.js +3 -0
- package/dist/vocabulary.js.map +1 -1
- package/docs/specs/cli.md +26 -15
- package/docs/specs/rest.md +31 -9
- package/package.json +3 -2
- package/skills/working-the-board/SKILL.md +11 -4
- package/src/api.ts +36 -0
- package/src/cli/cli.ts +616 -54
- package/src/cli/credentials.ts +276 -14
- package/src/cli/directory.ts +43 -6
- package/src/cli/format.ts +146 -5
- package/src/cli/help.ts +51 -25
- package/src/cli/install.ts +111 -0
- package/src/cli/main.ts +23 -3
- package/src/cli/notices.ts +48 -0
- package/src/client.ts +91 -6
- package/src/compat.ts +173 -0
- package/src/components/board.tsx +154 -8
- package/src/components/calendar.tsx +41 -1
- package/src/components/comments.tsx +20 -10
- package/src/components/event-feed.tsx +4 -0
- package/src/components/goals.tsx +234 -88
- package/src/components/markdown.tsx +19 -0
- package/src/components/pictures.tsx +389 -0
- package/src/components/projects.tsx +68 -0
- package/src/components/roadmap.tsx +242 -0
- package/src/components/task-view.tsx +43 -2
- package/src/components/tokens.tsx +38 -1
- package/src/console.tsx +278 -4
- package/src/data.ts +73 -2
- package/src/i18n/en.ts +77 -2
- package/src/i18n/ko.ts +77 -2
- package/src/index.ts +35 -0
- package/src/router.ts +70 -11
- package/src/rules.ts +5 -5
- package/src/schemas.ts +117 -0
- package/src/styles/console.css +486 -3
- package/src/vocabulary.ts +3 -0
package/src/cli/help.ts
CHANGED
|
@@ -84,23 +84,28 @@ const TASK_FIELD_REFUSALS = [
|
|
|
84
84
|
|
|
85
85
|
export const COMMAND_HELP: Readonly<Record<string, CommandHelp>> = {
|
|
86
86
|
login: {
|
|
87
|
-
usage: "login --url <origin> [--agent <name>] [--token-stdin]",
|
|
87
|
+
usage: "login --url <origin> [--agent <name>] [--token-stdin] [--default]",
|
|
88
88
|
about:
|
|
89
|
-
"Connects this agent to the console: shows an address and a code, which a person opens signed in, names the agent and approves; the command then receives a token of its own and keeps it, with the console's address, in your home directory, never showing it. An agent running the command relays the address and the code to its person and waits. --agent says what the agent calls itself; left out, the command names the agent it runs under where its environment says so (Claude Code, Codex), else An agent; the machine's name follows, and the pages show the name before 'on' with the whole on hover. --token-stdin reads a token made by hand from standard input instead, for a script or a job.",
|
|
89
|
+
"Connects this agent to the console: shows an address and a code, which a person opens signed in, names the agent and approves; the command then receives a token of its own and keeps it, with the console's address and the account, in your home directory, never showing it. One login per console and account: a second console adds a login beside the first, the first is the default console a directory that names none works at, and --default makes this one that. A login repeated for the same console and account replaces its token, which is given up at the console. An agent running the command relays the address and the code to its person and waits. --agent says what the agent calls itself; left out, the command names the agent it runs under where its environment says so (Claude Code, Codex), else An agent; the machine's name follows, and the pages show the name before 'on' with the whole on hover. --token-stdin reads a token made by hand from standard input instead, for a script or a job.",
|
|
90
90
|
refusals: [
|
|
91
91
|
"connect.not_found: the code was not approved in time, or the person said it was not theirs; run login again",
|
|
92
92
|
"the console does not know the token given: make one on the Agents page and try again",
|
|
93
93
|
],
|
|
94
94
|
},
|
|
95
|
+
logins: {
|
|
96
|
+
usage: "logins",
|
|
97
|
+
about:
|
|
98
|
+
"The consoles this machine is signed in to, each with the account, what the token is called there, since when, and which is the default; never a token.",
|
|
99
|
+
},
|
|
95
100
|
logout: {
|
|
96
|
-
usage: "logout",
|
|
101
|
+
usage: "logout [--url <origin>] [--account <login>]",
|
|
97
102
|
about:
|
|
98
|
-
"Signs this agent out: gives the token up
|
|
103
|
+
"Signs this agent out of one console: gives the token up there, so that it is good for nothing from now on, and forgets it here. Which console: --url, else the one this directory is bound to, else the default, else the one console signed in to; --account says which account where the console has several. A console out of reach leaves the token to the Agents page.",
|
|
99
104
|
},
|
|
100
105
|
whoami: {
|
|
101
106
|
usage: "whoami",
|
|
102
107
|
about:
|
|
103
|
-
"Who the token acts as, which console
|
|
108
|
+
"Who the token acts as, which console the command talks to from here and as which account, and which project this directory works in.",
|
|
104
109
|
},
|
|
105
110
|
projects: {
|
|
106
111
|
usage: "projects",
|
|
@@ -108,9 +113,9 @@ export const COMMAND_HELP: Readonly<Record<string, CommandHelp>> = {
|
|
|
108
113
|
"The projects you may work in: each with its key, its name, what you are in it, and what waits in it. Every command on the board works in one project.",
|
|
109
114
|
},
|
|
110
115
|
use: {
|
|
111
|
-
usage: "use <key>",
|
|
116
|
+
usage: "use <key> [--url <origin>] [--account <login>]",
|
|
112
117
|
about:
|
|
113
|
-
"Says which project this directory works in: writes .skillcdn-console.json here, which the commands read from this directory or one above it, and which is meant to be committed. --project <key> on any command, or CONSOLE_PROJECT in the environment, wins over it.",
|
|
118
|
+
"Says which project this directory works in: writes .skillcdn-console.json here, which the commands read from this directory or one above it, and which is meant to be committed in a private repository and left out of a public one. The file names the project; and the console, where that is not the default login here or --url says so; and the account, where the console has several logins or --account says so. Never a token. --project <key> on any command, or CONSOLE_PROJECT in the environment, wins over the project it names.",
|
|
114
119
|
refusals: ["project.not_found: no project has the key, or it is not yours to see"],
|
|
115
120
|
},
|
|
116
121
|
work: {
|
|
@@ -120,37 +125,43 @@ export const COMMAND_HELP: Readonly<Record<string, CommandHelp>> = {
|
|
|
120
125
|
},
|
|
121
126
|
tasks: {
|
|
122
127
|
usage:
|
|
123
|
-
"tasks [--state <state>] [--open] [--mine] [--category <key>] [--goal <id>] [--due <day|today|week|overdue>] [--limit <n>] [--offset <n>]",
|
|
124
|
-
about: `The tasks on the board, newest first: number, state, priority, title, who owns and works on each, its category and its due day, and what waits on it. --open keeps the ones not done or dropped, --mine those assigned to you, --category and --goal those sorted into one, --due those due by a day: today, within the week, or overdue (the open ones past their day). A page at a time: ${DEFAULT_PAGE_LIMIT} unless --limit says otherwise, from --offset on; a last line says when there is more. States: idea, ready, in_progress, in_review, done, dropped.`,
|
|
128
|
+
"tasks [--state <state>] [--open] [--mine] [--category <key>] [--goal <id>] [--due <day|today|week|overdue>] [--unassigned] [--archived] [--limit <n>] [--offset <n>]",
|
|
129
|
+
about: `The tasks on the board, newest first: number, state, priority, title, who owns and works on each, its category and its due day, and what waits on it. --open keeps the ones not done or dropped, --mine those assigned to you, --unassigned those assigned to nobody (not with --mine), --category and --goal those sorted into one, --due those due by a day: today, within the week, or overdue (the open ones past their day). The tasks put away (ADR-0029) are left out unless --archived asks for them alone. A page at a time: ${DEFAULT_PAGE_LIMIT} unless --limit says otherwise, from --offset on; a last line says when there is more. States: idea, ready, in_progress, in_review, done, dropped.`,
|
|
125
130
|
},
|
|
126
131
|
task: {
|
|
127
|
-
usage: `task <number|id> | task new <title> [--body <markdown>|--file <path>] ${TASK_FIELD_FLAGS} | task edit <number|id> [--title <title>] [--body <markdown>|--file <path>] ${TASK_FIELD_FLAGS}
|
|
132
|
+
usage: `task <number|id> | task new <title> [--body <markdown>|--file <path>] ${TASK_FIELD_FLAGS} | task edit <number|id> [--title <title>] [--body <markdown>|--file <path>] ${TASK_FIELD_FLAGS} | task archive <number|id> | task archive --goal <id> | task restore <number|id>`,
|
|
128
133
|
about:
|
|
129
|
-
"One task in full, with its plan (category, goal, start and due days), what happened to it (when it was started and done, which the board keeps itself), the decisions about it, the runs on it and the discussion on it, each comment whole with its files; or a new task written down; or a task changed, only in what the flags say, where none clears a field (priorities: low, normal, high, urgent).",
|
|
134
|
+
"One task in full, with its plan (category, goal, start and due days), what happened to it (when it was started and done, which the board keeps itself, and when it was put away), the decisions about it, the runs on it and the discussion on it, each comment whole with its files; or a new task written down; or a task changed, only in what the flags say, where none clears a field (priorities: low, normal, high, urgent). archive puts a done or dropped task away (ADR-0029): out of the listings, the board and the calendar, open by its number still; with --goal, every done or dropped task of the goal at once, for an owner. restore brings one back.",
|
|
130
135
|
limits: [
|
|
131
136
|
`title: one line, up to ${MAX_TITLE_LENGTH} characters, saying what is to be done on its own; what it refers to goes in the body`,
|
|
132
137
|
`body: ${MARKDOWN}`,
|
|
133
138
|
...TASK_FIELD_LIMITS,
|
|
134
139
|
],
|
|
135
|
-
refusals: [
|
|
140
|
+
refusals: [
|
|
141
|
+
"task.not_found: no task has that number or id",
|
|
142
|
+
"task.open: an open task is not put away; one done or dropped is",
|
|
143
|
+
...TASK_FIELD_REFUSALS,
|
|
144
|
+
],
|
|
136
145
|
},
|
|
137
146
|
goals: {
|
|
138
|
-
usage: "goals",
|
|
147
|
+
usage: "goals [--category <key>] [--state <state>]",
|
|
139
148
|
about:
|
|
140
|
-
"The roadmap of the project: its goals, the active first, each with its id, its state (planned, active, done, dropped), its
|
|
149
|
+
"The roadmap of the project: its goals, the active first, each with its id, its state (planned, active, done, dropped), its category, the days it starts and is meant to be reached by, and how far it is, counted from the tasks that work towards it. --category keeps those sorted into one, --state those in one state.",
|
|
141
150
|
},
|
|
142
151
|
goal: {
|
|
143
152
|
usage:
|
|
144
|
-
'goal <id> | goal new "<title>" [--body <markdown>|--file <path>] [--state <state>] [--due <day>] | goal edit <id> [--title <title>] [--body <markdown>|--file <path>] [--state <state>] [--due <day|none>]',
|
|
153
|
+
'goal <id> | goal new "<title>" [--body <markdown>|--file <path>] [--state <state>] [--category <key>] [--starts <day>] [--due <day>] | goal edit <id> [--title <title>] [--body <markdown>|--file <path>] [--state <state>] [--category <key|none>] [--starts <day|none>] [--due <day|none>]',
|
|
145
154
|
about:
|
|
146
|
-
"One goal in full, with the tasks that work towards it; or a goal set on the roadmap, for an owner of the project; or one changed, only in what the flags say. A task works towards a goal through its --goal.",
|
|
155
|
+
"One goal in full, with the tasks that work towards it; or a goal set on the roadmap, for an owner of the project; or one changed, only in what the flags say, where none clears a category or a day. A goal is planned in days as a task is, a start and a target, and sorted into a category of the workspace (console categories). A task works towards a goal through its --goal.",
|
|
147
156
|
limits: [
|
|
148
157
|
`title: one line, up to ${MAX_TITLE_LENGTH} characters`,
|
|
149
158
|
`body: ${MARKDOWN}`,
|
|
150
|
-
`due: ${DAY}`,
|
|
159
|
+
`starts, due: ${DAY}`,
|
|
151
160
|
],
|
|
152
161
|
refusals: [
|
|
153
162
|
"goal.not_found: no goal of this project has that id",
|
|
163
|
+
"goal.invalid_category: no category of the workspace has that key",
|
|
164
|
+
"goal.invalid_dates: the target day is before the start",
|
|
154
165
|
"auth.forbidden: only an owner of the project sets its roadmap",
|
|
155
166
|
],
|
|
156
167
|
},
|
|
@@ -179,9 +190,9 @@ export const COMMAND_HELP: Readonly<Record<string, CommandHelp>> = {
|
|
|
179
190
|
},
|
|
180
191
|
project: {
|
|
181
192
|
usage:
|
|
182
|
-
'project <key> | project new <key> "<name>" [--description <markdown>|--file <path>] [--visibility workspace|private] [--skills <address>|none] [--color <name>] [--symbol <text>] | project edit <key> [--name "<name>"] [the same flags; none clears] | project icon <key> <file> | project icon <key> --remove',
|
|
193
|
+
'project <key> | project new <key> "<name>" [--description <markdown>|--file <path>] [--visibility workspace|private] [--skills <address>|none] [--color <name>] [--symbol <text>] | project edit <key> [--name "<name>"] [the same flags; none clears] | project icon <key> <file> | project icon <key> --remove | project pack-token <key> --stdin | project pack-token <key> --remove',
|
|
183
194
|
about:
|
|
184
|
-
"One project in full; or a project made, with you as its owner, private unless --visibility workspace says everyone of the workspace works in it; or one changed, only in what the flags say, for an owner; or its image for its mark, set from a file of this machine or taken away. The organization's skills are the project's unless --skills names an address of its own.",
|
|
195
|
+
"One project in full; or a project made, with you as its owner, private unless --visibility workspace says everyone of the workspace works in it; or one changed, only in what the flags say, for an owner; or its image for its mark, set from a file of this machine or taken away; or its pack token (ADR-0028), the token a person made at SkillCDN for a private pack, read from standard input and never an argument, which the console keeps sealed to read the pack with, or taken away. The organization's skills are the project's unless --skills names an address of its own.",
|
|
185
196
|
limits: [
|
|
186
197
|
`key: ${KEY}, up to ${MAX_PROJECT_KEY_LENGTH} characters; it does not change once made`,
|
|
187
198
|
`name: one line, up to ${MAX_PROJECT_NAME_LENGTH} characters; description: up to ${MAX_PROJECT_DESCRIPTION_LENGTH}`,
|
|
@@ -204,9 +215,9 @@ export const COMMAND_HELP: Readonly<Record<string, CommandHelp>> = {
|
|
|
204
215
|
},
|
|
205
216
|
member: {
|
|
206
217
|
usage:
|
|
207
|
-
"member add <login> [--role owner|member] | member role <login> <owner|member> | member remove <login>",
|
|
218
|
+
"member add <login> [--role owner|member] [--project <key>[,<key>...]] | member role <login> <owner|member> | member remove <login>",
|
|
208
219
|
about:
|
|
209
|
-
"Lists a person of the workspace in the project, as a member unless --role says owner; changes what they are in it; or takes them off the list. For an owner of the project.",
|
|
220
|
+
"Lists a person of the workspace in the project, as a member unless --role says owner; changes what they are in it; or takes them off the list. For an owner of the project. With --project naming several keys with commas, member add lists the person in each of them in turn, one line per project; one listed already is said so, and the rest go on.",
|
|
210
221
|
refusals: [
|
|
211
222
|
"auth.forbidden: only an owner of the project lists its members",
|
|
212
223
|
"member.invalid_person: the person is not of the workspace",
|
|
@@ -235,7 +246,17 @@ export const COMMAND_HELP: Readonly<Record<string, CommandHelp>> = {
|
|
|
235
246
|
skills: {
|
|
236
247
|
usage: "skills",
|
|
237
248
|
about:
|
|
238
|
-
"The
|
|
249
|
+
"The skills of the project's pack, as SkillCDN serves them at the project's address: each with its description, the path of its SKILL.md, which console skill reads it by, and the URI you load it by through your own SkillCDN connection where your host has one; and where the console's own skills are on this machine. A private pack is read with the pack token the project holds (ADR-0028). --json adds the page of each, for a person.",
|
|
250
|
+
},
|
|
251
|
+
skill: {
|
|
252
|
+
usage: "skill <path> [--file <path>]",
|
|
253
|
+
about:
|
|
254
|
+
"One skill of the project's pack, whole, as load_skill lays it out for you: the rules of the repository from its root to the nearest manifest, the skill's body, the files it includes, each under a line that names its path; then the files it has and what it refers to. Read by the console from the SkillCDN deployment, with the pack token the project holds where the pack is private, so you need no connection of your own. <path> is the path of the SKILL.md from the repository's root, as console skills lists it. --file <path> reads a file of the pack instead, whole, or what a folder holds. What you read is the pack's, under its license: what a private pack says stays in your work and is not copied into reports or pages beyond what the work needs.",
|
|
255
|
+
refusals: [
|
|
256
|
+
"status not_found: the pack is not served to the console; private, with no pack token on the project",
|
|
257
|
+
"status token_invalid: the pack token the project holds no longer works; an owner sets a new one",
|
|
258
|
+
"status failed, for a file: SkillCDN will not carry it, too large or not text",
|
|
259
|
+
],
|
|
239
260
|
},
|
|
240
261
|
rules: {
|
|
241
262
|
usage:
|
|
@@ -447,14 +468,18 @@ Exit codes: 0 done; 1 the console refused, or could not be reached (the reason i
|
|
|
447
468
|
What the console refuses is printed as its code and its words. Everywhere:
|
|
448
469
|
${COMMON_REFUSALS.map((refusal) => ` ${refusal}`).join("\n")}
|
|
449
470
|
|
|
450
|
-
|
|
451
|
-
|
|
471
|
+
Which console a command talks to: --url, else CONSOLE_URL in the environment, else the console
|
|
472
|
+
.skillcdn-console.json binds this directory to, else the default login. The token is then the one
|
|
473
|
+
kept for that console alone (CONSOLE_TOKEN only together with CONSOLE_URL, for a hook or a job), in
|
|
474
|
+
$XDG_CONFIG_HOME/skillcdn-console/credentials.json (~/.config when XDG_CONFIG_HOME is unset);
|
|
475
|
+
a console nobody is signed in to here gets no request. --account <login> says which account where
|
|
476
|
+
a console has several. console logins lists them.
|
|
452
477
|
`;
|
|
453
478
|
|
|
454
479
|
const SECTIONS: readonly { readonly title: string; readonly commands: readonly string[] }[] = [
|
|
455
480
|
{
|
|
456
481
|
title: "Signing in, once, as a person, and the project to work in",
|
|
457
|
-
commands: ["login", "logout", "whoami", "projects", "use"],
|
|
482
|
+
commands: ["login", "logins", "logout", "whoami", "projects", "use"],
|
|
458
483
|
},
|
|
459
484
|
{
|
|
460
485
|
title: "The board",
|
|
@@ -470,6 +495,7 @@ const SECTIONS: readonly { readonly title: string; readonly commands: readonly s
|
|
|
470
495
|
"runs",
|
|
471
496
|
"run",
|
|
472
497
|
"skills",
|
|
498
|
+
"skill",
|
|
473
499
|
"rules",
|
|
474
500
|
],
|
|
475
501
|
},
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// Where the command runs from, so that the update it is told to make is the one that takes
|
|
2
|
+
// effect: installed for the machine, in a project, run once from a cache, or a checkout of the
|
|
3
|
+
// repository. Read from the package's own path and the working directory; nothing is asked of
|
|
4
|
+
// the system, so that a notice about versions costs a command nothing.
|
|
5
|
+
|
|
6
|
+
export type InstallKind = "global" | "project" | "temporary" | "checkout";
|
|
7
|
+
export type PackageManager = "npm" | "pnpm" | "yarn" | "bun";
|
|
8
|
+
|
|
9
|
+
export interface Install {
|
|
10
|
+
readonly kind: InstallKind;
|
|
11
|
+
readonly manager: PackageManager;
|
|
12
|
+
/** The directory the package is installed in: a project's root, the machine's global one, a cache's; the checkout itself. */
|
|
13
|
+
readonly root: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface InstallClues {
|
|
17
|
+
/** The package's own directory, where its manifest is. */
|
|
18
|
+
readonly packageDir: string;
|
|
19
|
+
readonly cwd: string;
|
|
20
|
+
readonly env: Readonly<Record<string, string | undefined>>;
|
|
21
|
+
readonly exists: (path: string) => boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const PACKAGE = "@skillcdn/console";
|
|
25
|
+
|
|
26
|
+
const slashes = (path: string): string => path.replaceAll("\\", "/").replace(/\/+$/, "");
|
|
27
|
+
|
|
28
|
+
/** The package manager that ran this command, when one did: `pnpm exec`, `npx` and their kind say so. */
|
|
29
|
+
function managerRunning(env: InstallClues["env"]): PackageManager | undefined {
|
|
30
|
+
const agent = env.npm_config_user_agent ?? "";
|
|
31
|
+
for (const manager of ["pnpm", "yarn", "bun", "npm"] as const) {
|
|
32
|
+
if (agent.startsWith(`${manager}/`)) {
|
|
33
|
+
return manager;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function detectInstall(clues: InstallClues): Install {
|
|
40
|
+
const dir = slashes(clues.packageDir);
|
|
41
|
+
const cwd = slashes(clues.cwd);
|
|
42
|
+
const at = dir.indexOf("/node_modules/");
|
|
43
|
+
if (at < 0) {
|
|
44
|
+
return { kind: "checkout", manager: "pnpm", root: dir };
|
|
45
|
+
}
|
|
46
|
+
const root = dir.slice(0, at);
|
|
47
|
+
const lower = dir.toLowerCase();
|
|
48
|
+
const running = managerRunning(clues.env);
|
|
49
|
+
// What `npx`, `pnpm dlx`, `yarn dlx` and `bunx` fetch into a cache lives only for the run.
|
|
50
|
+
if (/\/(_npx|dlx|dlx-[^/]*)\//.test(lower) || lower.includes("/.bun/install/cache/")) {
|
|
51
|
+
const manager =
|
|
52
|
+
running ??
|
|
53
|
+
(lower.includes("/_npx/") ? "npm" : lower.includes("/.bun/install/cache/") ? "bun" : "pnpm");
|
|
54
|
+
return { kind: "temporary", manager, root };
|
|
55
|
+
}
|
|
56
|
+
if (cwd === root || cwd.startsWith(`${root}/`)) {
|
|
57
|
+
const manager: PackageManager = clues.exists(`${root}/pnpm-lock.yaml`)
|
|
58
|
+
? "pnpm"
|
|
59
|
+
: clues.exists(`${root}/yarn.lock`)
|
|
60
|
+
? "yarn"
|
|
61
|
+
: clues.exists(`${root}/bun.lock`) || clues.exists(`${root}/bun.lockb`)
|
|
62
|
+
? "bun"
|
|
63
|
+
: (running ?? "npm");
|
|
64
|
+
return { kind: "project", manager, root };
|
|
65
|
+
}
|
|
66
|
+
const manager: PackageManager = /\/pnpm\/global\/|\/\.pnpm-global\//.test(lower)
|
|
67
|
+
? "pnpm"
|
|
68
|
+
: lower.includes("/yarn/global/")
|
|
69
|
+
? "yarn"
|
|
70
|
+
: lower.includes("/.bun/install/global/")
|
|
71
|
+
? "bun"
|
|
72
|
+
: "npm";
|
|
73
|
+
return { kind: "global", manager, root };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** The command that puts the version named where this command is installed. */
|
|
77
|
+
export function updateCommandFor(install: Install, version: string): string {
|
|
78
|
+
const spec = `${PACKAGE}@${version}`;
|
|
79
|
+
switch (install.kind) {
|
|
80
|
+
case "global":
|
|
81
|
+
return install.manager === "npm"
|
|
82
|
+
? `npm install -g ${spec}`
|
|
83
|
+
: install.manager === "yarn"
|
|
84
|
+
? `yarn global add ${spec}`
|
|
85
|
+
: `${install.manager} add -g ${spec}`;
|
|
86
|
+
case "project":
|
|
87
|
+
return `${install.manager === "npm" ? "npm install" : `${install.manager} add`} ${spec}`;
|
|
88
|
+
case "temporary":
|
|
89
|
+
return install.manager === "npm"
|
|
90
|
+
? `npx ${spec}`
|
|
91
|
+
: install.manager === "bun"
|
|
92
|
+
? `bunx ${spec}`
|
|
93
|
+
: `${install.manager} dlx ${spec}`;
|
|
94
|
+
case "checkout":
|
|
95
|
+
return "git pull && pnpm install && pnpm build";
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** Where the command is installed, in words: what `whoami` and `--version` say. */
|
|
100
|
+
export function describeInstall(install: Install): string {
|
|
101
|
+
switch (install.kind) {
|
|
102
|
+
case "global":
|
|
103
|
+
return `installed for the machine with ${install.manager} in ${install.root}`;
|
|
104
|
+
case "project":
|
|
105
|
+
return `installed in the project at ${install.root} with ${install.manager}`;
|
|
106
|
+
case "temporary":
|
|
107
|
+
return `fetched for this run by ${install.manager}`;
|
|
108
|
+
case "checkout":
|
|
109
|
+
return `built from the checkout at ${install.root}`;
|
|
110
|
+
}
|
|
111
|
+
}
|
package/src/cli/main.ts
CHANGED
|
@@ -5,21 +5,28 @@ import { hostname } from "node:os";
|
|
|
5
5
|
import process from "node:process";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import * as z from "zod/mini";
|
|
8
|
+
import { userAgentOf } from "../compat.js";
|
|
8
9
|
import { runCli } from "./cli.js";
|
|
9
10
|
import { createFileStore, defaultConfigDir } from "./credentials.js";
|
|
10
11
|
import { createDirectoryStore } from "./directory.js";
|
|
12
|
+
import { detectInstall } from "./install.js";
|
|
13
|
+
import { createNoticeStore } from "./notices.js";
|
|
11
14
|
import { listenOn } from "./serve.js";
|
|
12
15
|
import { readBytesAt, readFileAt, readStdin, writeBytesAt } from "./terminal.js";
|
|
13
16
|
|
|
14
17
|
// The `console` command: the only place the command reads the process. Everything it does is in
|
|
15
18
|
// cli.ts, which takes what it needs and is what the tests run.
|
|
16
19
|
|
|
17
|
-
/** The
|
|
20
|
+
/** The package's own directory, two levels above dist/cli: where its manifest and its skills are. */
|
|
21
|
+
const packageDir = fileURLToPath(new URL("../../", import.meta.url));
|
|
22
|
+
/** The version of the package this file runs from: its own manifest. */
|
|
18
23
|
const manifest = z
|
|
19
24
|
.object({ version: z.string() })
|
|
20
25
|
.safeParse(createRequire(import.meta.url)("../../package.json"));
|
|
26
|
+
const version = manifest.success ? manifest.data.version : undefined;
|
|
21
27
|
/** The console's own skills, shipped with the package beside dist/ (ADR-0015); not there in a checkout before packing. */
|
|
22
28
|
const skillsDir = fileURLToPath(new URL("../../skills/", import.meta.url));
|
|
29
|
+
const configDir = defaultConfigDir(process.env);
|
|
23
30
|
|
|
24
31
|
process.exitCode = await runCli(process.argv.slice(2), {
|
|
25
32
|
env: process.env,
|
|
@@ -35,11 +42,24 @@ process.exitCode = await runCli(process.argv.slice(2), {
|
|
|
35
42
|
readFile: readFileAt,
|
|
36
43
|
readBytes: readBytesAt,
|
|
37
44
|
writeBytes: writeBytesAt,
|
|
38
|
-
store: createFileStore(
|
|
45
|
+
store: createFileStore(configDir),
|
|
39
46
|
directory: createDirectoryStore(process.cwd()),
|
|
40
47
|
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
41
48
|
now: () => Date.now(),
|
|
42
|
-
version
|
|
49
|
+
version,
|
|
50
|
+
// The command names itself on every request, and where it runs, so that the console holds it
|
|
51
|
+
// to the versions it takes and the access log says which commands are about (ADR-0025).
|
|
52
|
+
userAgent:
|
|
53
|
+
version === undefined
|
|
54
|
+
? undefined
|
|
55
|
+
: userAgentOf(version, `cli; node ${process.versions.node}; ${process.platform}`),
|
|
56
|
+
install: detectInstall({
|
|
57
|
+
packageDir,
|
|
58
|
+
cwd: process.cwd(),
|
|
59
|
+
env: process.env,
|
|
60
|
+
exists: existsSync,
|
|
61
|
+
}),
|
|
62
|
+
notices: createNoticeStore(configDir),
|
|
43
63
|
skillsDir: existsSync(skillsDir) ? skillsDir : undefined,
|
|
44
64
|
listen: listenOn,
|
|
45
65
|
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import * as z from "zod/mini";
|
|
4
|
+
|
|
5
|
+
// What the command last said about the versions, kept beside the credentials, so that it says
|
|
6
|
+
// it once a day for one pair of versions and not on every command an agent runs. A notice is
|
|
7
|
+
// not worth failing a command for: a file that cannot be read or written is as good as none.
|
|
8
|
+
|
|
9
|
+
export interface VersionNotice {
|
|
10
|
+
/** The version of the command that noticed. */
|
|
11
|
+
readonly command: string;
|
|
12
|
+
/** The version of the console it noticed. */
|
|
13
|
+
readonly console: string;
|
|
14
|
+
readonly shownAt: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface NoticeStore {
|
|
18
|
+
load(): Promise<VersionNotice | undefined>;
|
|
19
|
+
save(notice: VersionNotice): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const noticesSchema = z.object({
|
|
23
|
+
versions: z.optional(z.object({ command: z.string(), console: z.string(), shownAt: z.string() })),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const FILE_NAME = "notices.json";
|
|
27
|
+
|
|
28
|
+
export function createNoticeStore(directory: string): NoticeStore {
|
|
29
|
+
const path = join(directory, FILE_NAME);
|
|
30
|
+
return {
|
|
31
|
+
async load() {
|
|
32
|
+
try {
|
|
33
|
+
const parsed = noticesSchema.safeParse(JSON.parse(await readFile(path, "utf8")));
|
|
34
|
+
return parsed.success ? parsed.data.versions : undefined;
|
|
35
|
+
} catch {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
async save(notice) {
|
|
40
|
+
try {
|
|
41
|
+
await mkdir(directory, { recursive: true, mode: 0o700 });
|
|
42
|
+
await writeFile(path, `${JSON.stringify({ versions: notice }, null, 2)}\n`);
|
|
43
|
+
} catch {
|
|
44
|
+
// Said this time; said again next time.
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
package/src/client.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
} from "./routes.js";
|
|
13
13
|
import {
|
|
14
14
|
type RestAnswerInput,
|
|
15
|
+
type RestArchivedTasks,
|
|
15
16
|
type RestArtifactInput,
|
|
16
17
|
type RestCategories,
|
|
17
18
|
type RestCategory,
|
|
@@ -43,6 +44,7 @@ import {
|
|
|
43
44
|
type RestMemberPatch,
|
|
44
45
|
type RestMembers,
|
|
45
46
|
type RestMePatch,
|
|
47
|
+
type RestPackTokenInput,
|
|
46
48
|
type RestPeople,
|
|
47
49
|
type RestPerson,
|
|
48
50
|
type RestPersonPatch,
|
|
@@ -59,6 +61,8 @@ import {
|
|
|
59
61
|
type RestRunEndInput,
|
|
60
62
|
type RestRunInput,
|
|
61
63
|
type RestRuns,
|
|
64
|
+
type RestSkillFile,
|
|
65
|
+
type RestSkillLoad,
|
|
62
66
|
type RestSkills,
|
|
63
67
|
type RestTask,
|
|
64
68
|
type RestTaskInput,
|
|
@@ -70,6 +74,7 @@ import {
|
|
|
70
74
|
type RestVersion,
|
|
71
75
|
type RestVersions,
|
|
72
76
|
type RestWork,
|
|
77
|
+
restArchivedTasksSchema,
|
|
73
78
|
restCategoriesSchema,
|
|
74
79
|
restCategorySchema,
|
|
75
80
|
restClaimSchema,
|
|
@@ -98,6 +103,8 @@ import {
|
|
|
98
103
|
restRulesSchema,
|
|
99
104
|
restRunSchema,
|
|
100
105
|
restRunsSchema,
|
|
106
|
+
restSkillFileSchema,
|
|
107
|
+
restSkillLoadSchema,
|
|
101
108
|
restSkillsSchema,
|
|
102
109
|
restTaskSchema,
|
|
103
110
|
restTasksSchema,
|
|
@@ -107,7 +114,7 @@ import {
|
|
|
107
114
|
restVersionsSchema,
|
|
108
115
|
restWorkSchema,
|
|
109
116
|
} from "./schemas.js";
|
|
110
|
-
import type { TaskState } from "./vocabulary.js";
|
|
117
|
+
import type { GoalState, TaskState } from "./vocabulary.js";
|
|
111
118
|
|
|
112
119
|
// The client of the console's REST API: what the default console and a custom one talk to the
|
|
113
120
|
// server with, and what the command line, a script or a console of a person's own talks to it
|
|
@@ -154,6 +161,12 @@ export interface ClientOptions {
|
|
|
154
161
|
* the page's own origin is what the console answers to.
|
|
155
162
|
*/
|
|
156
163
|
readonly token?: string;
|
|
164
|
+
/**
|
|
165
|
+
* What the client calls itself, sent as `user-agent` where the platform lets a client say
|
|
166
|
+
* (Node; a browser keeps its own): the command sends its product token, by which the console
|
|
167
|
+
* holds it to the versions it takes (ADR-0025).
|
|
168
|
+
*/
|
|
169
|
+
readonly userAgent?: string;
|
|
157
170
|
}
|
|
158
171
|
|
|
159
172
|
export class ApiError extends Error {
|
|
@@ -189,6 +202,13 @@ export interface Page {
|
|
|
189
202
|
}
|
|
190
203
|
|
|
191
204
|
/** What the board is narrowed to: one state, the open ones, a category, a goal, an assignee, or what is due by a day. */
|
|
205
|
+
/** What the roadmap is narrowed by: the goals in one state, or sorted into one category (ADR-0026). */
|
|
206
|
+
export interface GoalFilter {
|
|
207
|
+
readonly state?: GoalState | undefined;
|
|
208
|
+
/** The key of a category of the workspace. */
|
|
209
|
+
readonly category?: string | undefined;
|
|
210
|
+
}
|
|
211
|
+
|
|
192
212
|
export interface TaskFilter extends Page {
|
|
193
213
|
readonly state?: TaskState | undefined;
|
|
194
214
|
/** True for the tasks not done or dropped; false for the rest. */
|
|
@@ -199,8 +219,12 @@ export interface TaskFilter extends Page {
|
|
|
199
219
|
readonly goal?: string | undefined;
|
|
200
220
|
/** The id of the person the tasks are assigned to. */
|
|
201
221
|
readonly assignee?: string | undefined;
|
|
222
|
+
/** True for the tasks assigned to nobody. */
|
|
223
|
+
readonly unassigned?: boolean | undefined;
|
|
202
224
|
/** A day (`2026-10-20`): the tasks due on it or before it. */
|
|
203
225
|
readonly dueBy?: string | undefined;
|
|
226
|
+
/** True for the tasks put away alone (ADR-0029); false, or left out, for the current ones. */
|
|
227
|
+
readonly archived?: boolean | undefined;
|
|
204
228
|
}
|
|
205
229
|
|
|
206
230
|
/** What a folder's listing, or a search, of the documents is narrowed to. */
|
|
@@ -236,6 +260,11 @@ export interface ProjectClient {
|
|
|
236
260
|
task(ref: string, signal?: AbortSignal): Promise<RestTask>;
|
|
237
261
|
createTask(input: RestTaskInput): Promise<RestTask>;
|
|
238
262
|
updateTask(id: string, patch: RestTaskPatch): Promise<RestTask>;
|
|
263
|
+
/** Puts a done or dropped task away (ADR-0029), or brings one back. */
|
|
264
|
+
archiveTask(id: string): Promise<RestTask>;
|
|
265
|
+
restoreTask(id: string): Promise<RestTask>;
|
|
266
|
+
/** Puts every done or dropped task of a goal away at once; for an owner. Answers how many. */
|
|
267
|
+
archiveTasksOfGoal(goalId: string): Promise<RestArchivedTasks>;
|
|
239
268
|
/** The decisions, or only those that wait, or only those about one task; a page of them. */
|
|
240
269
|
decisions(
|
|
241
270
|
filter?: { readonly open?: boolean; readonly task?: string } & Page,
|
|
@@ -281,6 +310,18 @@ export interface ProjectClient {
|
|
|
281
310
|
eventStreamUrl(after: number): string;
|
|
282
311
|
/** The project's skills, as SkillCDN serves them at its address, or the organization's. */
|
|
283
312
|
skills(signal?: AbortSignal): Promise<RestSkills>;
|
|
313
|
+
/** One skill of the pack, a page of it (`load_skill`), read by the console with the pack token the project holds (ADR-0028). */
|
|
314
|
+
skill(path: string, cursor?: string, signal?: AbortSignal): Promise<RestSkillLoad>;
|
|
315
|
+
/** A file of the pack, a page of it, or what a folder holds (`read_repo_file`). */
|
|
316
|
+
skillFile(
|
|
317
|
+
path: string,
|
|
318
|
+
page?: { readonly offset?: number | undefined; readonly limit?: number | undefined },
|
|
319
|
+
signal?: AbortSignal,
|
|
320
|
+
): Promise<RestSkillFile>;
|
|
321
|
+
/** Sets the pack token the project reads a private pack with; for an owner. The token travels once and is answered never. */
|
|
322
|
+
setPackToken(input: RestPackTokenInput): Promise<RestProject>;
|
|
323
|
+
/** Takes the pack token away; for an owner. */
|
|
324
|
+
removePackToken(): Promise<RestProject>;
|
|
284
325
|
/** The rules that hold in the project (ADR-0023): the workspace's, and what the project adds. */
|
|
285
326
|
rules(signal?: AbortSignal): Promise<RestProjectRules>;
|
|
286
327
|
/** A folder's pages and folders, or the pages a search finds. */
|
|
@@ -302,7 +343,8 @@ export interface ProjectClient {
|
|
|
302
343
|
/** Where the bytes of a file attached to a document are read, by the file's id. */
|
|
303
344
|
documentFileUrl(path: string, fileId: string): string;
|
|
304
345
|
/** The roadmap (ADR-0019): the goals, the active first, each with its tasks counted by state. */
|
|
305
|
-
|
|
346
|
+
/** The roadmap, or what the filter keeps of it: the active goals first. */
|
|
347
|
+
goals(filter?: GoalFilter, signal?: AbortSignal): Promise<RestGoals>;
|
|
306
348
|
goal(id: string, signal?: AbortSignal): Promise<RestGoal>;
|
|
307
349
|
/** Sets a goal; for an owner, with a session or a token. */
|
|
308
350
|
createGoal(input: RestGoalInput): Promise<RestGoal>;
|
|
@@ -381,7 +423,8 @@ const INVALID = "The server answered unexpectedly.";
|
|
|
381
423
|
export function createClient(options: ClientOptions = {}): ConsoleClient {
|
|
382
424
|
const base = (options.baseUrl ?? "").replace(/\/+$/, "");
|
|
383
425
|
const send = options.fetch ?? ((input, init) => fetch(input, init));
|
|
384
|
-
const { token } = options;
|
|
426
|
+
const { token, userAgent } = options;
|
|
427
|
+
const named: Record<string, string> = userAgent === undefined ? {} : { "user-agent": userAgent };
|
|
385
428
|
|
|
386
429
|
const withQuery = (path: string, params: Record<string, string | undefined>): string => {
|
|
387
430
|
const query = new URLSearchParams();
|
|
@@ -423,6 +466,7 @@ export function createClient(options: ClientOptions = {}): ConsoleClient {
|
|
|
423
466
|
// A form names its own type, boundary included; everything else is JSON.
|
|
424
467
|
...(body === undefined || form ? {} : { "content-type": "application/json" }),
|
|
425
468
|
...(token === undefined ? {} : { authorization: `Bearer ${token}` }),
|
|
469
|
+
...named,
|
|
426
470
|
},
|
|
427
471
|
...(body === undefined ? {} : { body: form ? body : JSON.stringify(body) }),
|
|
428
472
|
});
|
|
@@ -457,7 +501,10 @@ export function createClient(options: ClientOptions = {}): ConsoleClient {
|
|
|
457
501
|
method: "GET",
|
|
458
502
|
...(signal === undefined ? {} : { signal }),
|
|
459
503
|
credentials: token === undefined ? "same-origin" : "omit",
|
|
460
|
-
headers:
|
|
504
|
+
headers: {
|
|
505
|
+
...(token === undefined ? {} : { authorization: `Bearer ${token}` }),
|
|
506
|
+
...named,
|
|
507
|
+
},
|
|
461
508
|
});
|
|
462
509
|
} catch (error) {
|
|
463
510
|
if (signal?.aborted === true) {
|
|
@@ -534,10 +581,12 @@ export function createClient(options: ClientOptions = {}): ConsoleClient {
|
|
|
534
581
|
"GET",
|
|
535
582
|
withQuery(at("tasks"), {
|
|
536
583
|
state: filter.state,
|
|
584
|
+
archived: flag(filter.archived),
|
|
537
585
|
open: flag(filter.open),
|
|
538
586
|
category: filter.category,
|
|
539
587
|
goal: filter.goal,
|
|
540
588
|
assignee: filter.assignee,
|
|
589
|
+
unassigned: flag(filter.unassigned),
|
|
541
590
|
dueBy: filter.dueBy,
|
|
542
591
|
limit: number(filter.limit),
|
|
543
592
|
offset: number(filter.offset),
|
|
@@ -551,6 +600,12 @@ export function createClient(options: ClientOptions = {}): ConsoleClient {
|
|
|
551
600
|
createTask: (input) => request("POST", `${base}${at("tasks")}`, input, restTaskSchema),
|
|
552
601
|
updateTask: (id, patch) =>
|
|
553
602
|
request("PATCH", `${base}${at("tasks", id)}`, patch, restTaskSchema),
|
|
603
|
+
archiveTask: (id) =>
|
|
604
|
+
request("POST", `${base}${at("tasks", id)}/archive`, undefined, restTaskSchema),
|
|
605
|
+
restoreTask: (id) =>
|
|
606
|
+
request("POST", `${base}${at("tasks", id)}/restore`, undefined, restTaskSchema),
|
|
607
|
+
archiveTasksOfGoal: (goalId) =>
|
|
608
|
+
request("POST", `${base}${at("tasks")}/archive`, { goalId }, restArchivedTasksSchema),
|
|
554
609
|
decisions: (filter = {}, signal) =>
|
|
555
610
|
request(
|
|
556
611
|
"GET",
|
|
@@ -639,6 +694,30 @@ export function createClient(options: ClientOptions = {}): ConsoleClient {
|
|
|
639
694
|
eventStreamUrl: (after) => withQuery(`${at("events")}/stream`, { after: String(after) }),
|
|
640
695
|
skills: (signal) =>
|
|
641
696
|
request("GET", `${base}${at("skills")}`, undefined, restSkillsSchema, signal),
|
|
697
|
+
skill: (path, cursor, signal) =>
|
|
698
|
+
request(
|
|
699
|
+
"GET",
|
|
700
|
+
withQuery(`${at("skills")}/one`, { path, cursor }),
|
|
701
|
+
undefined,
|
|
702
|
+
restSkillLoadSchema,
|
|
703
|
+
signal,
|
|
704
|
+
),
|
|
705
|
+
skillFile: (path, page = {}, signal) =>
|
|
706
|
+
request(
|
|
707
|
+
"GET",
|
|
708
|
+
withQuery(`${at("skills")}/file`, {
|
|
709
|
+
path,
|
|
710
|
+
offset: page.offset === undefined ? undefined : String(page.offset),
|
|
711
|
+
limit: page.limit === undefined ? undefined : String(page.limit),
|
|
712
|
+
}),
|
|
713
|
+
undefined,
|
|
714
|
+
restSkillFileSchema,
|
|
715
|
+
signal,
|
|
716
|
+
),
|
|
717
|
+
setPackToken: (input) =>
|
|
718
|
+
request("PUT", `${base}${at()}/pack-token`, input, restProjectSchema),
|
|
719
|
+
removePackToken: () =>
|
|
720
|
+
request("DELETE", `${base}${at()}/pack-token`, undefined, restProjectSchema),
|
|
642
721
|
rules: (signal) =>
|
|
643
722
|
request("GET", `${base}${at("rules")}`, undefined, restProjectRulesSchema, signal),
|
|
644
723
|
documents: (filter = {}, signal) =>
|
|
@@ -681,8 +760,14 @@ export function createClient(options: ClientOptions = {}): ConsoleClient {
|
|
|
681
760
|
request("POST", `${base}${at("docs", path)}/files`, formOf(input), restDocumentSchema),
|
|
682
761
|
documentFileUrl: (path, fileId) =>
|
|
683
762
|
`${base}${at("docs", path)}/files/${encodeURIComponent(fileId)}`,
|
|
684
|
-
goals: (signal) =>
|
|
685
|
-
request(
|
|
763
|
+
goals: (filter = {}, signal) =>
|
|
764
|
+
request(
|
|
765
|
+
"GET",
|
|
766
|
+
withQuery(at("goals"), { state: filter.state, category: filter.category }),
|
|
767
|
+
undefined,
|
|
768
|
+
restGoalsSchema,
|
|
769
|
+
signal,
|
|
770
|
+
),
|
|
686
771
|
goal: (id, signal) =>
|
|
687
772
|
request("GET", `${base}${at("goals", id)}`, undefined, restGoalSchema, signal),
|
|
688
773
|
createGoal: (input) => request("POST", `${base}${at("goals")}`, input, restGoalSchema),
|