@skillcdn/console 0.1.0 → 0.1.2

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.
Files changed (80) hide show
  1. package/README.md +12 -10
  2. package/dist/api.d.ts +5 -5
  3. package/dist/api.d.ts.map +1 -1
  4. package/dist/api.js +4 -4
  5. package/dist/api.js.map +1 -1
  6. package/dist/cli/cli.d.ts +5 -0
  7. package/dist/cli/cli.d.ts.map +1 -1
  8. package/dist/cli/cli.js +100 -43
  9. package/dist/cli/cli.js.map +1 -1
  10. package/dist/cli/directory.d.ts +14 -0
  11. package/dist/cli/directory.d.ts.map +1 -0
  12. package/dist/cli/directory.js +46 -0
  13. package/dist/cli/directory.js.map +1 -0
  14. package/dist/cli/format.d.ts +6 -3
  15. package/dist/cli/format.d.ts.map +1 -1
  16. package/dist/cli/format.js +17 -6
  17. package/dist/cli/format.js.map +1 -1
  18. package/dist/cli/help.d.ts +2 -2
  19. package/dist/cli/help.d.ts.map +1 -1
  20. package/dist/cli/help.js +25 -11
  21. package/dist/cli/help.js.map +1 -1
  22. package/dist/cli/main.js +9 -0
  23. package/dist/cli/main.js.map +1 -1
  24. package/dist/client.d.ts +39 -10
  25. package/dist/client.d.ts.map +1 -1
  26. package/dist/client.js +54 -33
  27. package/dist/client.js.map +1 -1
  28. package/dist/components/event-feed.d.ts.map +1 -1
  29. package/dist/components/event-feed.js +34 -14
  30. package/dist/components/event-feed.js.map +1 -1
  31. package/dist/components/projects.d.ts +41 -0
  32. package/dist/components/projects.d.ts.map +1 -0
  33. package/dist/components/projects.js +81 -0
  34. package/dist/components/projects.js.map +1 -0
  35. package/dist/components/runs.d.ts +2 -2
  36. package/dist/components/runs.d.ts.map +1 -1
  37. package/dist/components/runs.js +2 -2
  38. package/dist/components/runs.js.map +1 -1
  39. package/dist/components/shell.d.ts +5 -0
  40. package/dist/components/shell.d.ts.map +1 -1
  41. package/dist/components/shell.js +1 -1
  42. package/dist/components/shell.js.map +1 -1
  43. package/dist/components/task-view.d.ts +5 -1
  44. package/dist/components/task-view.d.ts.map +1 -1
  45. package/dist/components/task-view.js +2 -1
  46. package/dist/components/task-view.js.map +1 -1
  47. package/dist/console.css +91 -1
  48. package/dist/console.d.ts +3 -0
  49. package/dist/console.d.ts.map +1 -1
  50. package/dist/console.js +148 -39
  51. package/dist/console.js.map +1 -1
  52. package/dist/data.d.ts +33 -10
  53. package/dist/data.d.ts.map +1 -1
  54. package/dist/data.js +202 -81
  55. package/dist/data.js.map +1 -1
  56. package/dist/index.d.ts +2 -1
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +2 -1
  59. package/dist/index.js.map +1 -1
  60. package/dist/limits.d.ts +7 -0
  61. package/dist/limits.d.ts.map +1 -1
  62. package/dist/limits.js +7 -0
  63. package/dist/limits.js.map +1 -1
  64. package/dist/router.d.ts +22 -7
  65. package/dist/router.d.ts.map +1 -1
  66. package/dist/router.js +36 -22
  67. package/dist/router.js.map +1 -1
  68. package/dist/routes.d.ts +14 -12
  69. package/dist/routes.d.ts.map +1 -1
  70. package/dist/routes.js +28 -11
  71. package/dist/routes.js.map +1 -1
  72. package/dist/schemas.d.ts +163 -28
  73. package/dist/schemas.d.ts.map +1 -1
  74. package/dist/schemas.js +99 -27
  75. package/dist/schemas.js.map +1 -1
  76. package/dist/vocabulary.d.ts +7 -1
  77. package/dist/vocabulary.d.ts.map +1 -1
  78. package/dist/vocabulary.js +9 -0
  79. package/dist/vocabulary.js.map +1 -1
  80. package/package.json +1 -1
package/README.md CHANGED
@@ -30,25 +30,27 @@ const { items } = await client.tasks({ state: "ready" });
30
30
 
31
31
  - **The vocabulary:** `TASK_STATES`, `TASK_PRIORITIES`, `RUN_STATUSES`, `EVENT_KINDS`, with their types. One source for the database's constraints, the schemas and the board.
32
32
  - **The bounds** every input is held to (`MAX_TITLE_LENGTH`, `MAX_BODY_LENGTH`, `MAX_OPTIONS`, ...), so that a page can say so before a request is made.
33
- - **The routes:** `REST_ROUTES`, `AUTH_ROUTES`, and the helpers that build a path (`restPath`, `loginPath`, `signInPath`). The API itself is described in [docs/specs/rest.md](https://github.com/skillcdn/console/blob/main/docs/specs/rest.md).
34
- - **The schemas,** in the mini build of zod, which runs in a browser: what the server answers (`restTaskSchema`, `restDecisionSchema`, `restEventSchema`, `restMeSchema`, ...) and what it is sent (`restTaskInputSchema`, `restTaskPatchSchema`, `restDecisionInputSchema`, `restAnswerInputSchema`). Absent values are `null` on the wire, never missing keys. The server validates with the input schemas and is tested against the others.
35
- - **The client:** `createClient({ baseUrl, fetch })` answers typed values parsed with those schemas, and throws an `ApiError` with the server's stable `code` (or `network`, `invalid_response`) for anything else. It takes a `fetch` and reads nothing else. With `token`, a token a person made on their Tokens page, every request carries `Authorization: Bearer` and no cookie: how a script or a console of a person's own acts as that person. An `EventSource` cannot carry a header, so a stream read with a token is a `fetch` of `eventStreamUrl(after)`. `handInFile` sends a file as a form, and `fileUrl` says where its bytes are read back. `skills()` reads the organization's skills as the console serves them by address.
33
+ - **The routes:** `REST_ROUTES` (the workspace's resources), `AUTH_ROUTES`, and the helpers that build a path (`projectPath(key, collection, id)` for everything under a project, `restPath`, `loginPath`, `signInPath`). The API itself is described in [docs/specs/rest.md](https://github.com/skillcdn/console/blob/main/docs/specs/rest.md).
34
+ - **The schemas,** in the mini build of zod, which runs in a browser: what the server answers (`restProjectSchema`, `restMemberSchema`, `restTaskSchema`, `restDecisionSchema`, `restEventSchema`, `restMeSchema`, ...) and what it is sent (`restProjectInputSchema`, `restTaskInputSchema`, `restTaskPatchSchema`, `restDecisionInputSchema`, `restAnswerInputSchema`, ...). Absent values are `null` on the wire, never missing keys. The server validates with the input schemas and is tested against the others.
35
+ - **The client:** `createClient({ baseUrl, fetch })` answers typed values parsed with those schemas, and throws an `ApiError` with the server's stable `code` (or `network`, `invalid_response`) for anything else. It takes a `fetch` and reads nothing else. With `token`, a token a person made on their Tokens page, every request carries `Authorization: Bearer` and no cookie: how a script or a console of a person's own acts as that person. The board is a project's: `client.projects()` lists those the person may see, and `client.project(key)` is the client of one, with its tasks, decisions, runs, files, events, skills, settings and members. An `EventSource` cannot carry a header, so a stream read with a token is a `fetch` of `eventStreamUrl(after)`. `handInFile` sends a file as a form, and `fileUrl` says where its bytes are read back. `events(after, { task })` is everything that happened to one task.
36
36
 
37
37
  ### The command line
38
38
 
39
39
  ```sh
40
- npm install -g @skillcdn/console # where the agent runs, once the package is published
40
+ npm install -g @skillcdn/console # where the agent runs
41
41
  console login --url https://console.example # asks for a token made on the Tokens page, and keeps it
42
- console take 7 # a run begins on task #7, for the person the token is
42
+ console use web # the project this directory works in; .skillcdn-console.json, committed
43
+ console take 7 # a run begins on task #7 of the project, for the person the token is
43
44
  console report "Found the cause: the parser trusts its input."
44
45
  console hand-in ./report.md --label "the report" # a file the console keeps, or an https link
45
- console skills # the organization's skills, with the URI to load each by
46
+ console skills # the project's skills, with the URI to load each by
46
47
  console ask "Keep the old behaviour?" --option "Keep it" --option "Change it"
47
48
  console finish --summary "Done: the parser refuses empty input."
48
49
  ```
49
50
 
50
- - **`console`** is the agent's side of the console ([docs/specs/cli.md](https://github.com/skillcdn/console/blob/main/docs/specs/cli.md)): a thin client of the REST API with no logic of its own, no dependencies beyond the package's, and no cost to an agent until it is used. `console help` says everything an agent needs; `--json` answers with the console's own JSON; the exit code says whether the console did it (`0`), refused or could not be reached (`1`), did not understand (`2`), or a decision still waits (`3`).
51
+ - **`console`** is the agent's side of the console ([docs/specs/cli.md](https://github.com/skillcdn/console/blob/main/docs/specs/cli.md)): a thin client of the REST API with no logic of its own, no dependencies beyond the package's, and no cost to an agent until it is used. `console help` says everything an agent needs and `console --version` which version this is; `--json` answers with the console's own JSON; the exit code says whether the console did it (`0`), refused or could not be reached (`1`), did not understand (`2`), or a decision still waits (`3`).
51
52
  - **A person signs it in once:** `login` checks the token against the console and keeps it, with the console's address, in `$XDG_CONFIG_HOME/skillcdn-console/credentials.json` (`~/.config` when unset). `CONSOLE_URL` and `CONSOLE_TOKEN` in the environment win over the file, for a hook or a job. A token is never taken on the command line.
53
+ - **Every command on the board works in one project:** `--project <key>`, else `CONSOLE_PROJECT`, else what `console use <key>` wrote to `.skillcdn-console.json` in the working directory or one above it, a file meant to be committed. `console projects` lists the projects the person may work in.
52
54
  - **`@skillcdn/console/cli`** exports `runCli(argv, io)`, the command as a function that takes its environment, its streams, its `fetch` and its credential store: what the integration tests run against the app with no socket, and what a console of a person's own could embed.
53
55
 
54
56
  ### The components and the composition
@@ -59,12 +61,12 @@ import "@skillcdn/console/console.css";
59
61
 
60
62
  createConsole({
61
63
  title: "Acme", // until the server says what the board is called
62
- components: { SignIn: MySignIn }, // any of Shell, Board, TaskView, DecisionList, EventFeed, SignIn, TokenList, PeopleList, SkillList
64
+ components: { SignIn: MySignIn }, // any of Shell, Board, TaskView, DecisionList, EventFeed, SignIn, TokenList, PeopleList, SkillList, ProjectList, MemberList
63
65
  }).mount(document.getElementById("root"));
64
66
  ```
65
67
 
66
- - **The components** take their data as props and nothing from the network: `Board` (one column per state), `TaskCard`, `TaskView` (one task with its decisions and its parts), `TaskForm`, `DecisionList` and `DecisionCard` (the waiting first, each with the way to answer), `DecisionForm`, `EventFeed` (a sentence per event, newest first; `describeEvent` makes the sentence), `Shell` (the header with the pages and the person), `SignIn` (one button per provider the deployment offers), `TokenList`, `TokenForm` and `NewToken` (the tokens a person holds, the way to make one, and the one just made with its secret shown once), `PeopleList` (everyone, with what each is, and the way for an administrator to change it), `SkillList` (the organization's skills as SkillCDN serves them at the console's address, each with where a person reads it and what an agent loads it by), `RunList` and `RunCard` (an agent at work on a task: what it reported, what it handed in, links and files alike, what it waits for; `RunStatusBadge` and `RUN_STATUS_LABELS` with them, and `fileHref` for a console served from another origin than its API), and `Markdown`, which renders what people and agents wrote as elements, never as HTML, with links to the web only and pictures over https only. The small blocks (`Button`, `Badge`, `Avatar`, `PersonChip`, `Callout`, `EmptyState`, `Spinner`, `Time`) and the words of the vocabulary (`STATE_LABELS`, `PRIORITY_LABELS`, `ROLE_LABELS`, with `RoleBadge`) are exported too.
67
- - **The composition:** `createConsole(config)` returns `{ App, mount }`. `App` is the whole console as one component; `mount(container)` renders it and returns the way to take it down. `config.baseUrl` is the origin of the API (the page's own when left out), `config.components` the pieces to replace (`ConsoleComponents` names them with the props each takes), `config.client` a client of your own, for tests. The pages route in the browser (`matchRoute`, `PATHS`, `taskHref`); the data is loaded whole and kept current by the server's stream (`useConsoleData`, for a composition of your own).
68
+ - **The components** take their data as props and nothing from the network: `Board` (one column per state), `TaskCard`, `TaskView` (one task with its decisions and its parts), `TaskForm`, `DecisionList` and `DecisionCard` (the waiting first, each with the way to answer), `DecisionForm`, `EventFeed` (a sentence per event, newest first; `describeEvent` makes the sentence), `Shell` (the header with the pages and the person), `SignIn` (one button per provider the deployment offers), `TokenList`, `TokenForm` and `NewToken` (the tokens a person holds, the way to make one, and the one just made with its secret shown once), `PeopleList` (everyone, with what each is, and the way for an administrator to change it), `ProjectList`, `ProjectForm` and `MemberList` (the projects a person may see with what they are in each, the way to make or change one, and those listed in a project with the way for an owner to add, change and remove them; `ProjectRoleBadge`, `PROJECT_ROLE_LABELS`, `VISIBILITY_LABELS` and `keyOf` with them), `SkillList` (a project's skills as SkillCDN serves them at its address, each with where a person reads it and what an agent loads it by), `RunList` and `RunCard` (an agent at work on a task: what it reported, what it handed in, links and files alike, what it waits for; `RunStatusBadge` and `RUN_STATUS_LABELS` with them, and `fileHref` for where a file is read), and `Markdown`, which renders what people and agents wrote as elements, never as HTML, with links to the web only and pictures over https only. The small blocks (`Button`, `Badge`, `Avatar`, `PersonChip`, `Callout`, `EmptyState`, `Spinner`, `Time`) and the words of the vocabulary (`STATE_LABELS`, `PRIORITY_LABELS`, `ROLE_LABELS`, with `RoleBadge`) are exported too.
69
+ - **The composition:** `createConsole(config)` returns `{ App, mount }`. `App` is the whole console as one component; `mount(container)` renders it and returns the way to take it down. `config.baseUrl` is the origin of the API (the page's own when left out), `config.components` the pieces to replace (`ConsoleComponents` names them with the props each takes), `config.client` a client of your own, for tests. The pages route in the browser: the projects at `/`, a project's pages under `/p/<key>` (`matchRoute`, `PATHS`, `projectHref`, `taskHref`); the workspace is loaded once and the project the page is on whole, kept current by the project's stream (`useConsoleData(client, projectKey)`, for a composition of your own).
68
70
  - **The styles** are one file, `@skillcdn/console/console.css`: the tokens (`--sc-*`), a small reset, and one class per block, all prefixed `sc-`. Re-skinning starts and mostly ends with the tokens.
69
71
  - React 19 is a peer dependency; `react-markdown` and `remark-gfm` are the package's own.
70
72
 
package/dist/api.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- export { ApiError, type ClientOptions, type ConsoleClient, createClient, type FetchLike, type FileUpload, } from "./client.js";
2
- export { DEFAULT_TOKEN_DAYS, EVENTS_PAGE_LIMIT, LIST_LIMIT, MAX_AGENT_LENGTH, MAX_ARTIFACTS_PER_RUN, MAX_BODY_LENGTH, MAX_FILE_BYTES, MAX_FILE_NAME_LENGTH, MAX_LINK_LABEL_LENGTH, MAX_LINKS, MAX_NOTE_LENGTH, MAX_OPTION_LABEL_LENGTH, MAX_OPTIONS, MAX_QUESTION_LENGTH, MAX_REPORTS_PER_RUN, MAX_SUMMARY_LENGTH, MAX_TITLE_LENGTH, MAX_TOKEN_DAYS, MAX_TOKEN_NAME_LENGTH, MAX_TOKENS_PER_PERSON, MAX_URL_LENGTH, MIN_OPTIONS, } from "./limits.js";
3
- export { AUTH_ROUTES, isSignInFailure, loginPath, REST_ROUTES, RETURN_TO_PARAM, restPath, SIGN_IN_FAILURES, SIGN_IN_PARAM, type SignInFailure, signInPath, } from "./routes.js";
4
- export { type RestAnswerInput, type RestArtifact, type RestArtifactInput, type RestDecision, type RestDecisionInput, type RestDecisionOption, type RestDecisions, type RestError, type RestEvent, type RestEventData, type RestEvents, type RestFile, type RestFileInput, type RestMe, type RestPeople, type RestPerson, type RestPersonPatch, type RestProvider, type RestReport, type RestReportInput, type RestRun, type RestRunEndInput, type RestRunInput, type RestRuns, type RestSkill, type RestSkills, type RestTask, type RestTaskInput, type RestTaskLink, type RestTaskPatch, type RestTasks, type RestToken, type RestTokenCreated, type RestTokenInput, type RestTokens, restAnswerInputSchema, restArtifactInputSchema, restArtifactSchema, restDecisionInputSchema, restDecisionOptionSchema, restDecisionSchema, restDecisionsSchema, restErrorSchema, restEventDataSchema, restEventSchema, restEventsSchema, restFileInputSchema, restFileSchema, restMeSchema, restPeopleSchema, restPersonPatchSchema, restPersonSchema, restProviderSchema, restReportInputSchema, restReportSchema, restRunEndInputSchema, restRunInputSchema, restRunSchema, restRunsSchema, restSkillSchema, restSkillsSchema, restTaskInputSchema, restTaskLinkSchema, restTaskPatchSchema, restTaskSchema, restTasksSchema, restTokenCreatedSchema, restTokenInputSchema, restTokenSchema, restTokensSchema, } from "./schemas.js";
1
+ export { ApiError, type ClientOptions, type ConsoleClient, createClient, type EventFilter, type FetchLike, type FileUpload, type ProjectClient, } from "./client.js";
2
+ export { DEFAULT_TOKEN_DAYS, EVENTS_PAGE_LIMIT, LIST_LIMIT, MAX_AGENT_LENGTH, MAX_ARTIFACTS_PER_RUN, MAX_BODY_LENGTH, MAX_FILE_BYTES, MAX_FILE_NAME_LENGTH, MAX_LINK_LABEL_LENGTH, MAX_LINKS, MAX_NOTE_LENGTH, MAX_OPTION_LABEL_LENGTH, MAX_OPTIONS, MAX_PROJECT_DESCRIPTION_LENGTH, MAX_PROJECT_KEY_LENGTH, MAX_PROJECT_NAME_LENGTH, MAX_QUESTION_LENGTH, MAX_REPORTS_PER_RUN, MAX_SKILLS_ADDRESS_LENGTH, MAX_SUMMARY_LENGTH, MAX_TITLE_LENGTH, MAX_TOKEN_DAYS, MAX_TOKEN_NAME_LENGTH, MAX_TOKENS_PER_PERSON, MAX_URL_LENGTH, MIN_OPTIONS, } from "./limits.js";
3
+ export { AUTH_ROUTES, isSignInFailure, loginPath, PROJECT_COLLECTIONS, type ProjectCollection, projectPath, REST_ROUTES, RETURN_TO_PARAM, restPath, SIGN_IN_FAILURES, SIGN_IN_PARAM, type SignInFailure, signInPath, } from "./routes.js";
4
+ export { type RestAnswerInput, type RestArtifact, type RestArtifactInput, type RestDecision, type RestDecisionInput, type RestDecisionOption, type RestDecisions, type RestError, type RestEvent, type RestEventData, type RestEvents, type RestFile, type RestFileInput, type RestMe, type RestMember, type RestMemberInput, type RestMemberPatch, type RestMembers, type RestPeople, type RestPerson, type RestPersonPatch, type RestProject, type RestProjectInput, type RestProjectPatch, type RestProjects, type RestProvider, type RestReport, type RestReportInput, type RestRun, type RestRunEndInput, type RestRunInput, type RestRuns, type RestSkill, type RestSkills, type RestTask, type RestTaskInput, type RestTaskLink, type RestTaskPatch, type RestTasks, type RestToken, type RestTokenCreated, type RestTokenInput, type RestTokens, restAnswerInputSchema, restArtifactInputSchema, restArtifactSchema, restDecisionInputSchema, restDecisionOptionSchema, restDecisionSchema, restDecisionsSchema, restErrorSchema, restEventDataSchema, restEventSchema, restEventsSchema, restFileInputSchema, restFileSchema, restMemberInputSchema, restMemberPatchSchema, restMemberSchema, restMembersSchema, restMeSchema, restPeopleSchema, restPersonPatchSchema, restPersonSchema, restProjectInputSchema, restProjectPatchSchema, restProjectSchema, restProjectsSchema, restProviderSchema, restReportInputSchema, restReportSchema, restRunEndInputSchema, restRunInputSchema, restRunSchema, restRunsSchema, restSkillSchema, restSkillsSchema, restTaskInputSchema, restTaskLinkSchema, restTaskPatchSchema, restTaskSchema, restTasksSchema, restTokenCreatedSchema, restTokenInputSchema, restTokenSchema, restTokensSchema, } from "./schemas.js";
5
5
  export { hasForbiddenCodePoint } from "./text.js";
6
- export { ARTIFACT_KINDS, type ArtifactKind, EVENT_KINDS, type EventKind, isProviderKey, PERSON_ROLES, type PersonRole, PROVIDER_KEYS, type ProviderKey, RUN_ENDINGS, RUN_STATUSES, type RunEnding, type RunStatus, SKILLS_STATUSES, type SkillsStatus, TASK_PRIORITIES, TASK_STATES, type TaskPriority, type TaskState, } from "./vocabulary.js";
6
+ export { ARTIFACT_KINDS, type ArtifactKind, EVENT_KINDS, type EventKind, isProviderKey, PERSON_ROLES, type PersonRole, PROJECT_ROLES, PROJECT_VISIBILITIES, PROVIDER_KEYS, type ProjectRole, type ProjectVisibility, type ProviderKey, RUN_ENDINGS, RUN_STATUSES, type RunEnding, type RunStatus, SKILLS_STATUSES, type SkillsStatus, TASK_PRIORITIES, TASK_STATES, type TaskPriority, type TaskState, } from "./vocabulary.js";
7
7
  //# sourceMappingURL=api.d.ts.map
package/dist/api.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,QAAQ,EACR,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,YAAY,EACZ,KAAK,SAAS,EACd,KAAK,UAAU,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EACrB,SAAS,EACT,eAAe,EACf,uBAAuB,EACvB,WAAW,EACX,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,cAAc,EACd,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,WAAW,EACX,eAAe,EACf,SAAS,EACT,WAAW,EACX,eAAe,EACf,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,KAAK,aAAa,EAClB,UAAU,GACX,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,MAAM,EACX,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,OAAO,EACZ,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,qBAAqB,EACrB,uBAAuB,EACvB,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,sBAAsB,EACtB,oBAAoB,EACpB,eAAe,EACf,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EACL,cAAc,EACd,KAAK,YAAY,EACjB,WAAW,EACX,KAAK,SAAS,EACd,aAAa,EACb,YAAY,EACZ,KAAK,UAAU,EACf,aAAa,EACb,KAAK,WAAW,EAChB,WAAW,EACX,YAAY,EACZ,KAAK,SAAS,EACd,KAAK,SAAS,EACd,eAAe,EACf,KAAK,YAAY,EACjB,eAAe,EACf,WAAW,EACX,KAAK,YAAY,EACjB,KAAK,SAAS,GACf,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
package/dist/api.js CHANGED
@@ -3,9 +3,9 @@
3
3
  // custom UI talks to any console with types, and so that the contract has one source. No React
4
4
  // here: the server and the command line import this entry point, and nothing of the pages.
5
5
  export { ApiError, createClient, } from "./client.js";
6
- export { DEFAULT_TOKEN_DAYS, EVENTS_PAGE_LIMIT, LIST_LIMIT, MAX_AGENT_LENGTH, MAX_ARTIFACTS_PER_RUN, MAX_BODY_LENGTH, MAX_FILE_BYTES, MAX_FILE_NAME_LENGTH, MAX_LINK_LABEL_LENGTH, MAX_LINKS, MAX_NOTE_LENGTH, MAX_OPTION_LABEL_LENGTH, MAX_OPTIONS, MAX_QUESTION_LENGTH, MAX_REPORTS_PER_RUN, MAX_SUMMARY_LENGTH, MAX_TITLE_LENGTH, MAX_TOKEN_DAYS, MAX_TOKEN_NAME_LENGTH, MAX_TOKENS_PER_PERSON, MAX_URL_LENGTH, MIN_OPTIONS, } from "./limits.js";
7
- export { AUTH_ROUTES, isSignInFailure, loginPath, REST_ROUTES, RETURN_TO_PARAM, restPath, SIGN_IN_FAILURES, SIGN_IN_PARAM, signInPath, } from "./routes.js";
8
- export { restAnswerInputSchema, restArtifactInputSchema, restArtifactSchema, restDecisionInputSchema, restDecisionOptionSchema, restDecisionSchema, restDecisionsSchema, restErrorSchema, restEventDataSchema, restEventSchema, restEventsSchema, restFileInputSchema, restFileSchema, restMeSchema, restPeopleSchema, restPersonPatchSchema, restPersonSchema, restProviderSchema, restReportInputSchema, restReportSchema, restRunEndInputSchema, restRunInputSchema, restRunSchema, restRunsSchema, restSkillSchema, restSkillsSchema, restTaskInputSchema, restTaskLinkSchema, restTaskPatchSchema, restTaskSchema, restTasksSchema, restTokenCreatedSchema, restTokenInputSchema, restTokenSchema, restTokensSchema, } from "./schemas.js";
6
+ export { DEFAULT_TOKEN_DAYS, EVENTS_PAGE_LIMIT, LIST_LIMIT, MAX_AGENT_LENGTH, MAX_ARTIFACTS_PER_RUN, MAX_BODY_LENGTH, MAX_FILE_BYTES, MAX_FILE_NAME_LENGTH, MAX_LINK_LABEL_LENGTH, MAX_LINKS, MAX_NOTE_LENGTH, MAX_OPTION_LABEL_LENGTH, MAX_OPTIONS, MAX_PROJECT_DESCRIPTION_LENGTH, MAX_PROJECT_KEY_LENGTH, MAX_PROJECT_NAME_LENGTH, MAX_QUESTION_LENGTH, MAX_REPORTS_PER_RUN, MAX_SKILLS_ADDRESS_LENGTH, MAX_SUMMARY_LENGTH, MAX_TITLE_LENGTH, MAX_TOKEN_DAYS, MAX_TOKEN_NAME_LENGTH, MAX_TOKENS_PER_PERSON, MAX_URL_LENGTH, MIN_OPTIONS, } from "./limits.js";
7
+ export { AUTH_ROUTES, isSignInFailure, loginPath, PROJECT_COLLECTIONS, projectPath, REST_ROUTES, RETURN_TO_PARAM, restPath, SIGN_IN_FAILURES, SIGN_IN_PARAM, signInPath, } from "./routes.js";
8
+ export { restAnswerInputSchema, restArtifactInputSchema, restArtifactSchema, restDecisionInputSchema, restDecisionOptionSchema, restDecisionSchema, restDecisionsSchema, restErrorSchema, restEventDataSchema, restEventSchema, restEventsSchema, restFileInputSchema, restFileSchema, restMemberInputSchema, restMemberPatchSchema, restMemberSchema, restMembersSchema, restMeSchema, restPeopleSchema, restPersonPatchSchema, restPersonSchema, restProjectInputSchema, restProjectPatchSchema, restProjectSchema, restProjectsSchema, restProviderSchema, restReportInputSchema, restReportSchema, restRunEndInputSchema, restRunInputSchema, restRunSchema, restRunsSchema, restSkillSchema, restSkillsSchema, restTaskInputSchema, restTaskLinkSchema, restTaskPatchSchema, restTaskSchema, restTasksSchema, restTokenCreatedSchema, restTokenInputSchema, restTokenSchema, restTokensSchema, } from "./schemas.js";
9
9
  export { hasForbiddenCodePoint } from "./text.js";
10
- export { ARTIFACT_KINDS, EVENT_KINDS, isProviderKey, PERSON_ROLES, PROVIDER_KEYS, RUN_ENDINGS, RUN_STATUSES, SKILLS_STATUSES, TASK_PRIORITIES, TASK_STATES, } from "./vocabulary.js";
10
+ export { ARTIFACT_KINDS, EVENT_KINDS, isProviderKey, PERSON_ROLES, PROJECT_ROLES, PROJECT_VISIBILITIES, PROVIDER_KEYS, RUN_ENDINGS, RUN_STATUSES, SKILLS_STATUSES, TASK_PRIORITIES, TASK_STATES, } from "./vocabulary.js";
11
11
  //# sourceMappingURL=api.js.map
package/dist/api.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,8FAA8F;AAC9F,+FAA+F;AAC/F,2FAA2F;AAE3F,OAAO,EACL,QAAQ,EAGR,YAAY,GAGb,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EACrB,SAAS,EACT,eAAe,EACf,uBAAuB,EACvB,WAAW,EACX,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,cAAc,EACd,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,WAAW,EACX,eAAe,EACf,SAAS,EACT,WAAW,EACX,eAAe,EACf,QAAQ,EACR,gBAAgB,EAChB,aAAa,EAEb,UAAU,GACX,MAAM,aAAa,CAAC;AACrB,OAAO,EAoCL,qBAAqB,EACrB,uBAAuB,EACvB,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,sBAAsB,EACtB,oBAAoB,EACpB,eAAe,EACf,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EACL,cAAc,EAEd,WAAW,EAEX,aAAa,EACb,YAAY,EAEZ,aAAa,EAEb,WAAW,EACX,YAAY,EAGZ,eAAe,EAEf,eAAe,EACf,WAAW,GAGZ,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,8FAA8F;AAC9F,+FAA+F;AAC/F,2FAA2F;AAE3F,OAAO,EACL,QAAQ,EAGR,YAAY,GAKb,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EACrB,SAAS,EACT,eAAe,EACf,uBAAuB,EACvB,WAAW,EACX,8BAA8B,EAC9B,sBAAsB,EACtB,uBAAuB,EACvB,mBAAmB,EACnB,mBAAmB,EACnB,yBAAyB,EACzB,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,cAAc,EACd,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,WAAW,EACX,eAAe,EACf,SAAS,EACT,mBAAmB,EAEnB,WAAW,EACX,WAAW,EACX,eAAe,EACf,QAAQ,EACR,gBAAgB,EAChB,aAAa,EAEb,UAAU,GACX,MAAM,aAAa,CAAC;AACrB,OAAO,EA4CL,qBAAqB,EACrB,uBAAuB,EACvB,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,qBAAqB,EACrB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,sBAAsB,EACtB,oBAAoB,EACpB,eAAe,EACf,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EACL,cAAc,EAEd,WAAW,EAEX,aAAa,EACb,YAAY,EAEZ,aAAa,EACb,oBAAoB,EACpB,aAAa,EAIb,WAAW,EACX,YAAY,EAGZ,eAAe,EAEf,eAAe,EACf,WAAW,GAGZ,MAAM,iBAAiB,CAAC"}
package/dist/cli/cli.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { type FetchLike } from "../client.js";
2
2
  import type { CredentialStore } from "./credentials.js";
3
+ import type { DirectoryStore } from "./directory.js";
3
4
  /** The exit codes of the command, for whoever runs it: a shell, a hook, an agent. */
4
5
  export declare const EXIT: {
5
6
  readonly ok: 0;
@@ -24,8 +25,12 @@ export interface CliIo {
24
25
  /** A file handed in, as bytes. */
25
26
  readonly readBytes: (path: string) => Promise<Uint8Array>;
26
27
  readonly store: CredentialStore;
28
+ /** What the working directory says of the project, and the way to write it. */
29
+ readonly directory: DirectoryStore;
27
30
  readonly sleep: (ms: number) => Promise<void>;
28
31
  readonly now: () => number;
32
+ /** The version of the package the command runs from, when the entry point knows it. */
33
+ readonly version?: string | undefined;
29
34
  }
30
35
  /** Runs the command and answers with its exit code. What it prints goes through `io`. */
31
36
  export declare function runCli(argv: readonly string[], io: CliIo): Promise<number>;
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli/cli.ts"],"names":[],"mappings":"AAEA,OAAO,EAA8C,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAI1F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAmBxD,qFAAqF;AACrF,eAAO,MAAM,IAAI;aACf,EAAE,EAAE,CAAC;IACL,6EAA6E;aAC7E,MAAM,EAAE,CAAC;IACT,sCAAsC;aACtC,KAAK,EAAE,CAAC;IACR,6CAA6C;aAC7C,OAAO,EAAE,CAAC;CACF,CAAC;AAWX,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IAC3D,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,sDAAsD;IACtD,QAAQ,CAAC,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,gFAAgF;IAChF,QAAQ,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACzD,2CAA2C;IAC3C,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,kCAAkC;IAClC,QAAQ,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC1D,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,QAAQ,CAAC,GAAG,EAAE,MAAM,MAAM,CAAC;CAC5B;AA4nBD,yFAAyF;AACzF,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBhF"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli/cli.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,SAAS,EAEf,MAAM,cAAc,CAAC;AAItB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAqBrD,qFAAqF;AACrF,eAAO,MAAM,IAAI;aACf,EAAE,EAAE,CAAC;IACL,6EAA6E;aAC7E,MAAM,EAAE,CAAC;IACT,sCAAsC;aACtC,KAAK,EAAE,CAAC;IACR,6CAA6C;aAC7C,OAAO,EAAE,CAAC;CACF,CAAC;AAWX,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IAC3D,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,sDAAsD;IACtD,QAAQ,CAAC,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,gFAAgF;IAChF,QAAQ,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACzD,2CAA2C;IAC3C,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,kCAAkC;IAClC,QAAQ,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC1D,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,+EAA+E;IAC/E,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,QAAQ,CAAC,GAAG,EAAE,MAAM,MAAM,CAAC;IAC3B,uFAAuF;IACvF,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAqsBD,yFAAyF;AACzF,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CA6BhF"}
package/dist/cli/cli.js CHANGED
@@ -1,14 +1,15 @@
1
1
  import { basename, extname } from "node:path";
2
2
  import { parseArgs } from "node:util";
3
- import { ApiError, createClient } from "../client.js";
3
+ import { ApiError, createClient, } from "../client.js";
4
4
  import { MAX_OPTIONS, MIN_OPTIONS } from "../limits.js";
5
5
  import { TASK_PRIORITIES, TASK_STATES } from "../vocabulary.js";
6
- import { formatAnswer, formatDecision, formatDecisionLine, formatOptions, formatRun, formatRunLine, formatSkills, formatTask, formatTaskLine, } from "./format.js";
6
+ import { formatAnswer, formatDecision, formatDecisionLine, formatOptions, formatProjectLine, formatRun, formatRunLine, formatSkills, formatTask, formatTaskLine, } from "./format.js";
7
7
  import { COMMAND_HELP, helpFor, usage } from "./help.js";
8
8
  // The `console` command (docs/specs/cli.md): the agent's side of the console. A thin client of
9
9
  // the REST API with no logic of its own: every command is one or two requests and the words to
10
10
  // say what came back. It takes what it needs from `CliIo`, so that tests run it whole, against
11
- // the app and no socket, with a store and readers of their own.
11
+ // the app and no socket, with a store and readers of their own. The board is a project's: every
12
+ // command on it works in the project the flag, the environment or the working directory names.
12
13
  /** The exit codes of the command, for whoever runs it: a shell, a hook, an agent. */
13
14
  export const EXIT = {
14
15
  ok: 0,
@@ -38,7 +39,11 @@ class CliExit extends Error {
38
39
  }
39
40
  const failed = (message) => new CliExit(EXIT.failed, message);
40
41
  const misuse = (message) => new CliExit(EXIT.usage, message);
41
- const GLOBAL_OPTIONS = { json: { type: "boolean" }, url: { type: "string" } };
42
+ const GLOBAL_OPTIONS = {
43
+ json: { type: "boolean" },
44
+ url: { type: "string" },
45
+ project: { type: "string" },
46
+ };
42
47
  function parse(args, options, allowPositionals = true) {
43
48
  try {
44
49
  return parseArgs({
@@ -64,6 +69,7 @@ const texts = (values, name) => {
64
69
  }
65
70
  return typeof value === "string" ? [value] : [];
66
71
  };
72
+ const NO_PROJECT = "Say which project: --project <key>, CONSOLE_PROJECT in the environment, or console use <key> once in this directory. console projects lists the projects you may work in.";
67
73
  /** The console and the token to talk to it with: the flags, the environment, then what login kept. */
68
74
  async function open(io, values) {
69
75
  const stored = await io.store.load();
@@ -72,29 +78,39 @@ async function open(io, values) {
72
78
  if (url === undefined || token === undefined) {
73
79
  throw failed("Not signed in. A person signs the command in: console login --url <the console's origin>");
74
80
  }
81
+ const client = createClient({ baseUrl: url, token, fetch: io.fetch });
82
+ const projectKey = async () => text(values, "project") ?? io.env.CONSOLE_PROJECT ?? (await io.directory.load())?.project;
75
83
  return {
76
- client: createClient({ baseUrl: url, token, fetch: io.fetch }),
84
+ client,
77
85
  url,
78
86
  json: on(values, "json"),
87
+ projectKey,
88
+ async project() {
89
+ const key = await projectKey();
90
+ if (key === undefined) {
91
+ throw failed(NO_PROJECT);
92
+ }
93
+ return client.project(key);
94
+ },
79
95
  };
80
96
  }
81
97
  /** Prints what came back: the console's JSON on `--json`, the words otherwise. */
82
98
  function answer(io, session, value, words) {
83
99
  io.stdout(session.json ? `${JSON.stringify(value, null, 2)}\n` : `${words()}\n`);
84
100
  }
85
- /** The run a command on a run means: the one named, else the one open run of this token. */
86
- async function currentRun(session, values) {
101
+ /** The run a command on a run means: the one named, else the one open run of this token in the project. */
102
+ async function currentRun(project, values) {
87
103
  const given = text(values, "run");
88
104
  if (given !== undefined) {
89
105
  return given;
90
106
  }
91
- const { items } = await session.client.runs({ open: true, mine: true });
107
+ const { items } = await project.runs({ open: true, mine: true });
92
108
  const [only] = items;
93
109
  if (only !== undefined && items.length === 1) {
94
110
  return only.id;
95
111
  }
96
112
  if (items.length === 0) {
97
- throw failed("No run of yours is open. Take a task first: console take <number>");
113
+ throw failed("No run of yours is open in this project. Take a task first: console take <number>");
98
114
  }
99
115
  throw failed(`Several runs of yours are open; say which with --run <id>:\n${items.map((run) => ` ${formatRunLine(run)}`).join("\n")}`);
100
116
  }
@@ -159,7 +175,7 @@ function theOne(positionals, ask) {
159
175
  * The decision once answered, or as it stands when the wait is over. Each request asks the
160
176
  * console to hold it for a while, so the answer arrives as soon as a person gives it.
161
177
  */
162
- async function waitForAnswer(io, client, decision, seconds) {
178
+ async function waitForAnswer(io, project, decision, seconds) {
163
179
  const deadline = io.now() + seconds * 1000;
164
180
  let current = decision;
165
181
  for (;;) {
@@ -167,7 +183,7 @@ async function waitForAnswer(io, client, decision, seconds) {
167
183
  if (current.answer !== null || left <= 0) {
168
184
  return current;
169
185
  }
170
- current = await client.awaitDecision(current.id, Math.max(1, Math.min(Math.ceil(left / 1000), WAIT_STEP_SECONDS)));
186
+ current = await project.awaitDecision(current.id, Math.max(1, Math.min(Math.ceil(left / 1000), WAIT_STEP_SECONDS)));
171
187
  if (current.answer === null) {
172
188
  await io.sleep(WAIT_PAUSE_MS);
173
189
  }
@@ -178,9 +194,9 @@ const stillWaiting = (id) => `Decision ${id} still waits for a person; the run w
178
194
  * Waits for the answer and says what it is, or that it is still to come. On `--json`, a decision
179
195
  * printed already as it was raised (`shown`) is printed again only with its answer.
180
196
  */
181
- async function settle(io, session, decision, seconds, shown = false) {
197
+ async function settle(io, session, project, decision, seconds, shown = false) {
182
198
  const outcome = decision.answer === null && seconds > 0
183
- ? await waitForAnswer(io, session.client, decision, seconds)
199
+ ? await waitForAnswer(io, project, decision, seconds)
184
200
  : decision;
185
201
  if (session.json) {
186
202
  if (!shown || outcome.answer !== null) {
@@ -212,7 +228,7 @@ const login = async (args, io) => {
212
228
  throw failed("The console does not know this token. Make one on your Tokens page and try again.");
213
229
  }
214
230
  const kept = await io.store.save({ url, token });
215
- io.stdout(`Signed in to ${me.workspace.name} at ${url} as ${person.login} (${person.role}). The token is kept in ${kept}.\n`);
231
+ io.stdout(`Signed in to ${me.workspace.name} at ${url} as ${person.login} (${person.role}). The token is kept in ${kept}.\nNext, say which project this directory works in: console use <key> (console projects lists them).\n`);
216
232
  return EXIT.ok;
217
233
  };
218
234
  const logout = async (args, io) => {
@@ -229,21 +245,42 @@ const whoami = async (args, io) => {
229
245
  if (person === null) {
230
246
  throw failed("The console does not know this token. Sign in again: console login");
231
247
  }
232
- answer(io, session, me, () => `${person.login} (${person.role}) at ${me.workspace.name}, ${session.url}`);
248
+ const key = await session.projectKey();
249
+ answer(io, session, { ...me, project: key ?? null }, () => `${person.login} (${person.role}) at ${me.workspace.name}, ${session.url}${key === undefined ? "; no project named here" : `; project ${key}`}`);
250
+ return EXIT.ok;
251
+ };
252
+ const projects = async (args, io) => {
253
+ const { values } = parse(args, {}, false);
254
+ const session = await open(io, values);
255
+ const found = await session.client.projects();
256
+ answer(io, session, found, () => found.items.length === 0
257
+ ? "No projects you may work in. A person makes one on the console's Projects page."
258
+ : found.items.map(formatProjectLine).join("\n"));
259
+ return EXIT.ok;
260
+ };
261
+ const use = async (args, io) => {
262
+ const { values, positionals } = parse(args, {});
263
+ const key = theOne(positionals, "Say which project: console use <key>");
264
+ const session = await open(io, values);
265
+ const project = await session.client.project(key).get();
266
+ const kept = await io.directory.save({ project: project.key });
267
+ answer(io, session, project, () => `Working in ${project.name} (${project.key}) from this directory on: kept in ${kept}, which is meant to be committed.`);
233
268
  return EXIT.ok;
234
269
  };
235
270
  const tasks = async (args, io) => {
236
271
  const { values } = parse(args, { state: { type: "string" } }, false);
237
272
  const state = stateOf(text(values, "state"));
238
273
  const session = await open(io, values);
239
- const found = await session.client.tasks(state === undefined ? {} : { state });
274
+ const project = await session.project();
275
+ const found = await project.tasks(state === undefined ? {} : { state });
240
276
  answer(io, session, found, () => found.items.length === 0 ? "No tasks." : found.items.map(formatTaskLine).join("\n"));
241
277
  return EXIT.ok;
242
278
  };
243
279
  const skills = async (args, io) => {
244
280
  const { values } = parse(args, {}, false);
245
281
  const session = await open(io, values);
246
- const found = await session.client.skills();
282
+ const project = await session.project();
283
+ const found = await project.skills();
247
284
  answer(io, session, found, () => formatSkills(found));
248
285
  return EXIT.ok;
249
286
  };
@@ -259,7 +296,8 @@ const newTask = async (args, io) => {
259
296
  const priority = priorityOf(text(values, "priority"));
260
297
  const body = await bodyOf(io, values, text(values, "body"));
261
298
  const session = await open(io, values);
262
- const made = await session.client.createTask({
299
+ const project = await session.project();
300
+ const made = await project.createTask({
263
301
  title,
264
302
  ...(body === undefined ? {} : { body }),
265
303
  ...(state === undefined ? {} : { state }),
@@ -275,10 +313,11 @@ const task = async (args, io) => {
275
313
  const { values, positionals } = parse(args, {});
276
314
  const ref = theOne(positionals, "Say which task: console task <number|id>");
277
315
  const session = await open(io, values);
278
- const found = await session.client.task(ref);
316
+ const project = await session.project();
317
+ const found = await project.task(ref);
279
318
  const [decisions, runs] = await Promise.all([
280
- session.client.decisions({ task: found.id }),
281
- session.client.runs({ task: found.id }),
319
+ project.decisions({ task: found.id }),
320
+ project.runs({ task: found.id }),
282
321
  ]);
283
322
  answer(io, session, { task: found, decisions: decisions.items, runs: runs.items }, () => formatTask(found, decisions.items, runs.items));
284
323
  return EXIT.ok;
@@ -287,9 +326,10 @@ const take = async (args, io) => {
287
326
  const { values, positionals } = parse(args, { agent: { type: "string" } });
288
327
  const ref = theOne(positionals, "Say which task: console take <number|id>");
289
328
  const session = await open(io, values);
290
- const found = await session.client.task(ref);
329
+ const project = await session.project();
330
+ const found = await project.task(ref);
291
331
  const agent = text(values, "agent");
292
- const run = await session.client.startRun({
332
+ const run = await project.startRun({
293
333
  taskId: found.id,
294
334
  ...(agent === undefined ? {} : { agent }),
295
335
  });
@@ -316,8 +356,9 @@ const report = async (args, io) => {
316
356
  throw misuse('Say what to report: console report "<markdown>", or --file <path>, or - to read standard input.');
317
357
  }
318
358
  const session = await open(io, values);
319
- const runId = await currentRun(session, values);
320
- const run = await session.client.report(runId, { body });
359
+ const project = await session.project();
360
+ const runId = await currentRun(project, values);
361
+ const run = await project.report(runId, { body });
321
362
  answer(io, session, run, () => `Reported on run ${run.id}: ${run.reports.length} report${run.reports.length === 1 ? "" : "s"} so far.`);
322
363
  return EXIT.ok;
323
364
  };
@@ -349,11 +390,12 @@ const handIn = async (args, io) => {
349
390
  const what = theOne(positionals, "Say what to hand in: console hand-in <https url | file path> [--label <words>]");
350
391
  const label = text(values, "label");
351
392
  const session = await open(io, values);
352
- const runId = await currentRun(session, values);
393
+ const project = await session.project();
394
+ const runId = await currentRun(project, values);
353
395
  // A URL is handed in as a link, and the console says whether it takes it; anything else
354
396
  // names a file on this machine.
355
397
  if (/^[a-z][a-z0-9+.-]*:\/\//i.test(what)) {
356
- const run = await session.client.handIn(runId, {
398
+ const run = await project.handIn(runId, {
357
399
  url: what,
358
400
  ...(label === undefined ? {} : { label }),
359
401
  });
@@ -369,7 +411,7 @@ const handIn = async (args, io) => {
369
411
  }
370
412
  const name = basename(what);
371
413
  const contentType = CONTENT_TYPES[extname(name).toLowerCase()];
372
- const run = await session.client.handInFile(runId, {
414
+ const run = await project.handInFile(runId, {
373
415
  name,
374
416
  bytes,
375
417
  ...(contentType === undefined ? {} : { contentType }),
@@ -394,8 +436,9 @@ const ask = async (args, io) => {
394
436
  const seconds = secondsOf(text(values, "wait"), DEFAULT_ASK_WAIT_SECONDS);
395
437
  const body = await bodyOf(io, values, text(values, "body"));
396
438
  const session = await open(io, values);
397
- const runId = await currentRun(session, values);
398
- const raised = await session.client.raiseDecision({
439
+ const project = await session.project();
440
+ const runId = await currentRun(project, values);
441
+ const raised = await project.raiseDecision({
399
442
  question,
400
443
  options: options.map((label) => ({ label })),
401
444
  runId,
@@ -405,24 +448,26 @@ const ask = async (args, io) => {
405
448
  io.stdout(session.json
406
449
  ? `${JSON.stringify(raised, null, 2)}\n`
407
450
  : `Decision ${raised.id} raised on run ${runId}; the run waits for a person.\n${formatOptions(raised)}\n`);
408
- return settle(io, session, raised, seconds, true);
451
+ return settle(io, session, project, raised, seconds, true);
409
452
  };
410
453
  const decision = async (args, io) => {
411
454
  const { values, positionals } = parse(args, { wait: { type: "string" } });
412
455
  const id = theOne(positionals, "Say which decision: console decision <id> [--wait <seconds>]");
413
456
  const seconds = secondsOf(text(values, "wait"), 0);
414
457
  const session = await open(io, values);
415
- const found = await session.client.decision(id);
458
+ const project = await session.project();
459
+ const found = await project.decision(id);
416
460
  if (seconds === 0) {
417
461
  answer(io, session, found, () => formatDecision(found));
418
462
  return EXIT.ok;
419
463
  }
420
- return settle(io, session, found, seconds);
464
+ return settle(io, session, project, found, seconds);
421
465
  };
422
466
  const decisions = async (args, io) => {
423
467
  const { values } = parse(args, { open: { type: "boolean" } }, false);
424
468
  const session = await open(io, values);
425
- const found = await session.client.decisions(on(values, "open") ? { open: true } : {});
469
+ const project = await session.project();
470
+ const found = await project.decisions(on(values, "open") ? { open: true } : {});
426
471
  answer(io, session, found, () => found.items.length === 0 ? "No decisions." : found.items.map(formatDecisionLine).join("\n"));
427
472
  return EXIT.ok;
428
473
  };
@@ -430,8 +475,9 @@ const ending = (status) => async (args, io) => {
430
475
  const { values } = parse(args, { summary: { type: "string" }, file: { type: "string" }, run: { type: "string" } }, false);
431
476
  const summary = await bodyOf(io, values, text(values, "summary"));
432
477
  const session = await open(io, values);
433
- const runId = await currentRun(session, values);
434
- const run = await session.client.endRun(runId, {
478
+ const project = await session.project();
479
+ const runId = await currentRun(project, values);
480
+ const run = await project.endRun(runId, {
435
481
  status,
436
482
  ...(summary === undefined ? {} : { summary }),
437
483
  });
@@ -451,8 +497,9 @@ const abandon = async (args, io) => {
451
497
  }
452
498
  const summary = await bodyOf(io, values, text(values, "summary"));
453
499
  const session = await open(io, values);
454
- const runId = positionals[0] ?? (await currentRun(session, values));
455
- const run = await session.client.endRun(runId, {
500
+ const project = await session.project();
501
+ const runId = positionals[0] ?? (await currentRun(project, values));
502
+ const run = await project.endRun(runId, {
456
503
  status: "abandoned",
457
504
  ...(summary === undefined ? {} : { summary }),
458
505
  });
@@ -462,9 +509,10 @@ const abandon = async (args, io) => {
462
509
  const runs = async (args, io) => {
463
510
  const { values } = parse(args, { task: { type: "string" }, open: { type: "boolean" }, mine: { type: "boolean" } }, false);
464
511
  const session = await open(io, values);
512
+ const project = await session.project();
465
513
  const ref = text(values, "task");
466
- const taskId = ref === undefined ? undefined : (await session.client.task(ref)).id;
467
- const found = await session.client.runs({
514
+ const taskId = ref === undefined ? undefined : (await project.task(ref)).id;
515
+ const found = await project.runs({
468
516
  ...(taskId === undefined ? {} : { task: taskId }),
469
517
  ...(on(values, "open") ? { open: true } : {}),
470
518
  ...(on(values, "mine") ? { mine: true } : {}),
@@ -476,14 +524,17 @@ const run = async (args, io) => {
476
524
  const { values, positionals } = parse(args, {});
477
525
  const id = theOne(positionals, "Say which run: console run <id>");
478
526
  const session = await open(io, values);
479
- const found = await session.client.run(id);
480
- answer(io, session, found, () => formatRun(found));
527
+ const project = await session.project();
528
+ const found = await project.run(id);
529
+ answer(io, session, found, () => formatRun(found, (artifactId) => project.fileUrl(artifactId)));
481
530
  return EXIT.ok;
482
531
  };
483
532
  const COMMANDS = {
484
533
  login,
485
534
  logout,
486
535
  whoami,
536
+ projects,
537
+ use,
487
538
  tasks,
488
539
  task,
489
540
  skills,
@@ -501,7 +552,7 @@ const COMMANDS = {
501
552
  };
502
553
  function help(io, name) {
503
554
  if (name === undefined) {
504
- io.stdout(usage());
555
+ io.stdout(usage(io.version));
505
556
  return EXIT.ok;
506
557
  }
507
558
  const found = helpFor(name);
@@ -516,6 +567,8 @@ function hintFor(error) {
516
567
  switch (error.code) {
517
568
  case "auth.required":
518
569
  return "The token is not one the console knows, any more or at all. A person signs the command in again: console login\n";
570
+ case "project.not_found":
571
+ return "No project has this key, or it is not yours to see. console projects lists the projects you may work in.\n";
519
572
  case "network":
520
573
  return "Is the console's address right? console whoami --url <origin> says what the command uses.\n";
521
574
  default:
@@ -526,6 +579,10 @@ function hintFor(error) {
526
579
  export async function runCli(argv, io) {
527
580
  const [name, ...rest] = argv;
528
581
  try {
582
+ if (name === "--version" || name === "-v" || name === "version") {
583
+ io.stdout(`console ${io.version ?? "(version unknown)"} (@skillcdn/console)\n`);
584
+ return EXIT.ok;
585
+ }
529
586
  if (name === undefined || name === "help" || name === "--help" || name === "-h") {
530
587
  return help(io, rest[0]);
531
588
  }