@skillcdn/console 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +79 -2
  3. package/dist/api.d.ts +7 -0
  4. package/dist/api.d.ts.map +1 -0
  5. package/dist/api.js +11 -0
  6. package/dist/api.js.map +1 -0
  7. package/dist/cli/cli.d.ts +32 -0
  8. package/dist/cli/cli.d.ts.map +1 -0
  9. package/dist/cli/cli.js +553 -0
  10. package/dist/cli/cli.js.map +1 -0
  11. package/dist/cli/credentials.d.ts +16 -0
  12. package/dist/cli/credentials.d.ts.map +1 -0
  13. package/dist/cli/credentials.js +46 -0
  14. package/dist/cli/credentials.js.map +1 -0
  15. package/dist/cli/format.d.ts +16 -0
  16. package/dist/cli/format.d.ts.map +1 -0
  17. package/dist/cli/format.js +151 -0
  18. package/dist/cli/format.js.map +1 -0
  19. package/dist/cli/help.d.ts +16 -0
  20. package/dist/cli/help.d.ts.map +1 -0
  21. package/dist/cli/help.js +180 -0
  22. package/dist/cli/help.js.map +1 -0
  23. package/dist/cli/main.d.ts +3 -0
  24. package/dist/cli/main.d.ts.map +1 -0
  25. package/dist/cli/main.js +25 -0
  26. package/dist/cli/main.js.map +1 -0
  27. package/dist/cli/terminal.d.ts +12 -0
  28. package/dist/cli/terminal.d.ts.map +1 -0
  29. package/dist/cli/terminal.js +68 -0
  30. package/dist/cli/terminal.js.map +1 -0
  31. package/dist/client.d.ts +92 -0
  32. package/dist/client.d.ts.map +1 -0
  33. package/dist/client.js +117 -0
  34. package/dist/client.js.map +1 -0
  35. package/dist/components/board.d.ts +20 -0
  36. package/dist/components/board.d.ts.map +1 -0
  37. package/dist/components/board.js +19 -0
  38. package/dist/components/board.js.map +1 -0
  39. package/dist/components/decision-form.d.ts +13 -0
  40. package/dist/components/decision-form.d.ts.map +1 -0
  41. package/dist/components/decision-form.js +23 -0
  42. package/dist/components/decision-form.js.map +1 -0
  43. package/dist/components/decision-list.d.ts +22 -0
  44. package/dist/components/decision-list.d.ts.map +1 -0
  45. package/dist/components/decision-list.js +28 -0
  46. package/dist/components/decision-list.js.map +1 -0
  47. package/dist/components/event-feed.d.ts +13 -0
  48. package/dist/components/event-feed.d.ts.map +1 -0
  49. package/dist/components/event-feed.js +59 -0
  50. package/dist/components/event-feed.js.map +1 -0
  51. package/dist/components/markdown.d.ts +4 -0
  52. package/dist/components/markdown.d.ts.map +1 -0
  53. package/dist/components/markdown.js +34 -0
  54. package/dist/components/markdown.js.map +1 -0
  55. package/dist/components/people.d.ts +11 -0
  56. package/dist/components/people.d.ts.map +1 -0
  57. package/dist/components/people.js +7 -0
  58. package/dist/components/people.js.map +1 -0
  59. package/dist/components/runs.d.ts +27 -0
  60. package/dist/components/runs.d.ts.map +1 -0
  61. package/dist/components/runs.js +45 -0
  62. package/dist/components/runs.js.map +1 -0
  63. package/dist/components/shell.d.ts +22 -0
  64. package/dist/components/shell.d.ts.map +1 -0
  65. package/dist/components/shell.js +16 -0
  66. package/dist/components/shell.js.map +1 -0
  67. package/dist/components/sign-in.d.ts +11 -0
  68. package/dist/components/sign-in.d.ts.map +1 -0
  69. package/dist/components/sign-in.js +15 -0
  70. package/dist/components/sign-in.js.map +1 -0
  71. package/dist/components/skills.d.ts +7 -0
  72. package/dist/components/skills.d.ts.map +1 -0
  73. package/dist/components/skills.js +26 -0
  74. package/dist/components/skills.js.map +1 -0
  75. package/dist/components/task-form.d.ts +14 -0
  76. package/dist/components/task-form.d.ts.map +1 -0
  77. package/dist/components/task-form.js +34 -0
  78. package/dist/components/task-form.js.map +1 -0
  79. package/dist/components/task-view.d.ts +22 -0
  80. package/dist/components/task-view.d.ts.map +1 -0
  81. package/dist/components/task-view.js +32 -0
  82. package/dist/components/task-view.js.map +1 -0
  83. package/dist/components/tokens.d.ts +26 -0
  84. package/dist/components/tokens.d.ts.map +1 -0
  85. package/dist/components/tokens.js +42 -0
  86. package/dist/components/tokens.js.map +1 -0
  87. package/dist/components/ui.d.ts +61 -0
  88. package/dist/components/ui.d.ts.map +1 -0
  89. package/dist/components/ui.js +109 -0
  90. package/dist/components/ui.js.map +1 -0
  91. package/dist/console.css +1382 -0
  92. package/dist/console.d.ts +44 -0
  93. package/dist/console.d.ts.map +1 -0
  94. package/dist/console.js +181 -0
  95. package/dist/console.js.map +1 -0
  96. package/dist/data.d.ts +41 -0
  97. package/dist/data.d.ts.map +1 -0
  98. package/dist/data.js +208 -0
  99. package/dist/data.js.map +1 -0
  100. package/dist/index.d.ts +19 -0
  101. package/dist/index.d.ts.map +1 -0
  102. package/dist/index.js +23 -0
  103. package/dist/index.js.map +1 -0
  104. package/dist/limits.d.ts +37 -0
  105. package/dist/limits.d.ts.map +1 -0
  106. package/dist/limits.js +40 -0
  107. package/dist/limits.js.map +1 -0
  108. package/dist/router.d.ts +37 -0
  109. package/dist/router.d.ts.map +1 -0
  110. package/dist/router.js +55 -0
  111. package/dist/router.js.map +1 -0
  112. package/dist/routes.d.ts +47 -0
  113. package/dist/routes.d.ts.map +1 -0
  114. package/dist/routes.js +53 -0
  115. package/dist/routes.js.map +1 -0
  116. package/dist/schemas.d.ts +789 -0
  117. package/dist/schemas.d.ts.map +1 -0
  118. package/dist/schemas.js +341 -0
  119. package/dist/schemas.js.map +1 -0
  120. package/dist/text.d.ts +6 -0
  121. package/dist/text.d.ts.map +1 -0
  122. package/dist/text.js +31 -0
  123. package/dist/text.js.map +1 -0
  124. package/dist/vocabulary.d.ts +35 -0
  125. package/dist/vocabulary.d.ts.map +1 -0
  126. package/dist/vocabulary.js +57 -0
  127. package/dist/vocabulary.js.map +1 -0
  128. package/package.json +70 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/client.js ADDED
@@ -0,0 +1,117 @@
1
+ import { AUTH_ROUTES, REST_ROUTES, restPath } from "./routes.js";
2
+ import { restDecisionSchema, restDecisionsSchema, restErrorSchema, restEventsSchema, restMeSchema, restPeopleSchema, restPersonSchema, restRunSchema, restRunsSchema, restSkillsSchema, restTaskSchema, restTasksSchema, restTokenCreatedSchema, restTokensSchema, } from "./schemas.js";
3
+ export class ApiError extends Error {
4
+ /** HTTP status, or 0 when there was no response at all. */
5
+ status;
6
+ /** The stable code from the error body, `network` or `invalid_response`. */
7
+ code;
8
+ constructor(status, code, message) {
9
+ super(message);
10
+ this.name = "ApiError";
11
+ this.status = status;
12
+ this.code = code;
13
+ }
14
+ }
15
+ const INVALID = "The server answered unexpectedly.";
16
+ export function createClient(options = {}) {
17
+ const base = (options.baseUrl ?? "").replace(/\/+$/, "");
18
+ const send = options.fetch ?? ((input, init) => fetch(input, init));
19
+ const { token } = options;
20
+ const withQuery = (path, params) => {
21
+ const query = new URLSearchParams();
22
+ for (const [name, value] of Object.entries(params)) {
23
+ if (value !== undefined) {
24
+ query.set(name, value);
25
+ }
26
+ }
27
+ return query.size === 0 ? `${base}${path}` : `${base}${path}?${query}`;
28
+ };
29
+ /** What a response says when it is not what was asked for. */
30
+ const failure = async (response) => {
31
+ const parsed = restErrorSchema.safeParse(await response.json().catch(() => undefined));
32
+ return parsed.success
33
+ ? new ApiError(response.status, parsed.data.error.code, parsed.data.error.message)
34
+ : new ApiError(response.status, "invalid_response", INVALID);
35
+ };
36
+ const request = async (method, url, body, schema, signal) => {
37
+ const form = body instanceof FormData;
38
+ let response;
39
+ try {
40
+ response = await send(url, {
41
+ method,
42
+ ...(signal === undefined ? {} : { signal }),
43
+ // Same origin, so the session cookie goes with it; the browser names the origin of a
44
+ // request that changes something, which the server checks. With a token, the token is
45
+ // the credential and no cookie travels.
46
+ credentials: token === undefined ? "same-origin" : "omit",
47
+ headers: {
48
+ accept: "application/json",
49
+ // A form names its own type, boundary included; everything else is JSON.
50
+ ...(body === undefined || form ? {} : { "content-type": "application/json" }),
51
+ ...(token === undefined ? {} : { authorization: `Bearer ${token}` }),
52
+ },
53
+ ...(body === undefined ? {} : { body: form ? body : JSON.stringify(body) }),
54
+ });
55
+ }
56
+ catch (error) {
57
+ if (signal?.aborted === true) {
58
+ throw error;
59
+ }
60
+ throw new ApiError(0, "network", "The server could not be reached.");
61
+ }
62
+ if (!response.ok) {
63
+ throw await failure(response);
64
+ }
65
+ if (schema === undefined) {
66
+ return undefined;
67
+ }
68
+ const parsed = schema.safeParse(await response.json().catch(() => undefined));
69
+ if (!parsed.success) {
70
+ throw new ApiError(response.status, "invalid_response", INVALID);
71
+ }
72
+ return parsed.data;
73
+ };
74
+ const flag = (value) => value === undefined ? undefined : String(value);
75
+ return {
76
+ me: (signal) => request("GET", `${base}${REST_ROUTES.me}`, undefined, restMeSchema, signal),
77
+ people: (signal) => request("GET", `${base}${REST_ROUTES.people}`, undefined, restPeopleSchema, signal),
78
+ updatePerson: (id, patch) => request("PATCH", `${base}${restPath("people", id)}`, patch, restPersonSchema),
79
+ tasks: (filter = {}, signal) => request("GET", withQuery(REST_ROUTES.tasks, { state: filter.state }), undefined, restTasksSchema, signal),
80
+ task: (ref, signal) => request("GET", `${base}${restPath("tasks", ref)}`, undefined, restTaskSchema, signal),
81
+ createTask: (input) => request("POST", `${base}${REST_ROUTES.tasks}`, input, restTaskSchema),
82
+ updateTask: (id, patch) => request("PATCH", `${base}${restPath("tasks", id)}`, patch, restTaskSchema),
83
+ decisions: (filter = {}, signal) => request("GET", withQuery(REST_ROUTES.decisions, { open: flag(filter.open), task: filter.task }), undefined, restDecisionsSchema, signal),
84
+ decision: (id, signal) => request("GET", `${base}${restPath("decisions", id)}`, undefined, restDecisionSchema, signal),
85
+ awaitDecision: (id, waitSeconds, signal) => request("GET", withQuery(restPath("decisions", id), { wait: String(waitSeconds) }), undefined, restDecisionSchema, signal),
86
+ raiseDecision: (input) => request("POST", `${base}${REST_ROUTES.decisions}`, input, restDecisionSchema),
87
+ answerDecision: (id, input) => request("POST", `${base}${restPath("decisions", id)}/answer`, input, restDecisionSchema),
88
+ runs: (filter = {}, signal) => request("GET", withQuery(REST_ROUTES.runs, {
89
+ task: filter.task,
90
+ open: flag(filter.open),
91
+ mine: flag(filter.mine),
92
+ }), undefined, restRunsSchema, signal),
93
+ run: (id, signal) => request("GET", `${base}${restPath("runs", id)}`, undefined, restRunSchema, signal),
94
+ startRun: (input) => request("POST", `${base}${REST_ROUTES.runs}`, input, restRunSchema),
95
+ report: (runId, input) => request("POST", `${base}${restPath("runs", runId)}/reports`, input, restRunSchema),
96
+ handIn: (runId, input) => request("POST", `${base}${restPath("runs", runId)}/artifacts`, input, restRunSchema),
97
+ handInFile: (runId, input) => {
98
+ const form = new FormData();
99
+ const bytes = input.bytes instanceof Blob ? input.bytes : new Blob([Uint8Array.from(input.bytes)]);
100
+ form.set("file", new File([bytes], input.name, { type: input.contentType ?? "application/octet-stream" }), input.name);
101
+ if (input.label !== undefined) {
102
+ form.set("label", input.label);
103
+ }
104
+ return request("POST", `${base}${restPath("runs", runId)}/files`, form, restRunSchema);
105
+ },
106
+ fileUrl: (artifactId) => `${base}${restPath("files", artifactId)}`,
107
+ endRun: (runId, input) => request("POST", `${base}${restPath("runs", runId)}/end`, input, restRunSchema),
108
+ events: (after, signal) => request("GET", withQuery(REST_ROUTES.events, { after: String(after) }), undefined, restEventsSchema, signal),
109
+ eventStreamUrl: (after) => withQuery(`${REST_ROUTES.events}/stream`, { after: String(after) }),
110
+ skills: (signal) => request("GET", `${base}${REST_ROUTES.skills}`, undefined, restSkillsSchema, signal),
111
+ tokens: (signal) => request("GET", `${base}${REST_ROUTES.tokens}`, undefined, restTokensSchema, signal),
112
+ createToken: (input) => request("POST", `${base}${REST_ROUTES.tokens}`, input, restTokenCreatedSchema),
113
+ revokeToken: (id) => request("DELETE", `${base}${restPath("tokens", id)}`, undefined, undefined),
114
+ signOut: () => request("POST", `${base}${AUTH_ROUTES.logout}`, undefined, undefined),
115
+ };
116
+ }
117
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { ReactNode } from "react";
2
+ import { type RestTask, type TaskState } from "../api.js";
3
+ export interface BoardProps {
4
+ readonly tasks: readonly RestTask[];
5
+ /** The link to a task's own page, as the composition routes it. */
6
+ readonly taskHref: (task: RestTask) => string;
7
+ readonly onOpen: (task: RestTask) => void;
8
+ /** Called when a person moves a task to another column. Left out, the board is read-only. */
9
+ readonly onMove?: ((task: RestTask, state: TaskState) => void) | undefined;
10
+ /** What a column shows when it has nothing; the way to write the first task, for example. */
11
+ readonly empty?: ReactNode;
12
+ }
13
+ export declare function TaskCard(props: {
14
+ readonly task: RestTask;
15
+ readonly href: string;
16
+ readonly onOpen: (task: RestTask) => void;
17
+ readonly onMove?: ((task: RestTask, state: TaskState) => void) | undefined;
18
+ }): import("react").JSX.Element;
19
+ export declare function Board(props: BoardProps): import("react").JSX.Element;
20
+ //# sourceMappingURL=board.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"board.d.ts","sourceRoot":"","sources":["../../src/components/board.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAE,KAAK,QAAQ,EAAe,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAMvE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IACpC,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,MAAM,CAAC;IAC9C,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAC1C,6FAA6F;IAC7F,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC3E,6FAA6F;IAC7F,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;CAC5B;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE;IAC9B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAC5E,+BAqDA;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,+BAgCtC"}
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { TASK_STATES } from "../api.js";
3
+ import { Avatar, Badge, cx, PriorityBadge, STATE_LABELS } from "./ui.js";
4
+ export function TaskCard(props) {
5
+ const { task } = props;
6
+ return (_jsxs("article", { className: "sc-card", "aria-label": `#${task.number} ${task.title}`, children: [_jsxs("a", { className: "sc-card-title", href: props.href, onClick: (event) => {
7
+ if (event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey) {
8
+ event.preventDefault();
9
+ props.onOpen(task);
10
+ }
11
+ }, children: [_jsxs("span", { className: "sc-card-number", children: ["#", task.number] }), " ", task.title] }), _jsxs("div", { className: "sc-card-meta", children: [_jsx(PriorityBadge, { priority: task.priority }), task.openDecisions > 0 && (_jsx(Badge, { tone: "warning", title: "Decisions waiting for a person", children: task.openDecisions === 1 ? "1 decision" : `${task.openDecisions} decisions` })), task.openRuns > 0 && (_jsx(Badge, { tone: "accent", title: "An agent is at work on it", children: "agent at work" })), task.links.length > 0 && (_jsx(Badge, { tone: "neutral", children: task.links.length === 1 ? "1 link" : `${task.links.length} links` })), _jsx("span", { className: "sc-card-spacer" }), task.assignee !== null && _jsx(Avatar, { person: task.assignee, size: "sm" })] }), props.onMove !== undefined && (_jsxs("label", { className: "sc-card-move", children: [_jsx("span", { className: "sc-visually-hidden", children: "Move to" }), _jsx("select", { value: task.state, onChange: (event) => props.onMove?.(task, event.target.value), children: TASK_STATES.map((state) => (_jsx("option", { value: state, children: STATE_LABELS[state] }, state))) })] }))] }));
12
+ }
13
+ export function Board(props) {
14
+ return (_jsx("div", { className: "sc-board", children: TASK_STATES.map((state) => {
15
+ const tasks = props.tasks.filter((task) => task.state === state);
16
+ return (_jsxs("section", { className: cx("sc-column", `sc-column-${state}`), "aria-label": STATE_LABELS[state], children: [_jsxs("header", { className: "sc-column-header", children: [_jsx("h2", { className: "sc-column-title", children: STATE_LABELS[state] }), _jsx("span", { className: "sc-column-count", children: tasks.length })] }), _jsxs("div", { className: "sc-column-body", children: [tasks.map((task) => (_jsx(TaskCard, { task: task, href: props.taskHref(task), onOpen: props.onOpen, onMove: props.onMove }, task.id))), tasks.length === 0 && state === "idea" && props.empty] })] }, state));
17
+ }) }));
18
+ }
19
+ //# sourceMappingURL=board.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"board.js","sourceRoot":"","sources":["../../src/components/board.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { type RestDecisionInput, type RestTask } from "../api.js";
2
+ export interface DecisionFormProps {
3
+ /** The tasks the decision may be about. */
4
+ readonly tasks: readonly RestTask[];
5
+ /** The task it is about from the start, when raised from a task's page. */
6
+ readonly taskId?: string | undefined;
7
+ readonly busy?: boolean | undefined;
8
+ readonly error?: string | undefined;
9
+ readonly onSubmit: (input: RestDecisionInput) => void;
10
+ readonly onCancel?: (() => void) | undefined;
11
+ }
12
+ export declare function DecisionForm(props: DecisionFormProps): import("react").JSX.Element;
13
+ //# sourceMappingURL=decision-form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-form.d.ts","sourceRoot":"","sources":["../../src/components/decision-form.tsx"],"names":[],"mappings":"AACA,OAAO,EAML,KAAK,iBAAiB,EACtB,KAAK,QAAQ,EACd,MAAM,WAAW,CAAC;AAKnB,MAAM,WAAW,iBAAiB;IAChC,2CAA2C;IAC3C,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IACpC,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACtD,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;CAC9C;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,+BA2GpD"}
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { MAX_BODY_LENGTH, MAX_OPTION_LABEL_LENGTH, MAX_OPTIONS, MAX_QUESTION_LENGTH, MIN_OPTIONS, } from "../api.js";
4
+ import { Button } from "./ui.js";
5
+ export function DecisionForm(props) {
6
+ const [question, setQuestion] = useState("");
7
+ const [body, setBody] = useState("");
8
+ const [taskId, setTaskId] = useState(props.taskId ?? "");
9
+ const [options, setOptions] = useState(["", ""]);
10
+ const labels = options.map((option) => option.trim()).filter((option) => option.length > 0);
11
+ const ready = question.trim().length > 0 && labels.length >= MIN_OPTIONS;
12
+ const submit = (event) => {
13
+ event.preventDefault();
14
+ props.onSubmit({
15
+ question: question.trim(),
16
+ body,
17
+ options: labels.map((label) => ({ label })),
18
+ taskId: taskId === "" ? null : taskId,
19
+ });
20
+ };
21
+ return (_jsxs("form", { className: "sc-form", onSubmit: submit, children: [_jsxs("label", { className: "sc-field", children: [_jsx("span", { className: "sc-field-label", children: "Question" }), _jsx("input", { className: "sc-input", value: question, maxLength: MAX_QUESTION_LENGTH, required: true, onChange: (event) => setQuestion(event.target.value) })] }), _jsxs("label", { className: "sc-field", children: [_jsx("span", { className: "sc-field-label", children: "Context" }), _jsx("textarea", { className: "sc-input sc-textarea", value: body, maxLength: MAX_BODY_LENGTH, rows: 4, placeholder: "What a person needs to know to answer, in Markdown.", onChange: (event) => setBody(event.target.value) })] }), props.taskId === undefined && props.tasks.length > 0 && (_jsxs("label", { className: "sc-field", children: [_jsx("span", { className: "sc-field-label", children: "About" }), _jsxs("select", { className: "sc-input", value: taskId, onChange: (event) => setTaskId(event.target.value), children: [_jsx("option", { value: "", children: "No task in particular" }), props.tasks.map((task) => (_jsxs("option", { value: task.id, children: ["#", task.number, " ", task.title] }, task.id)))] })] })), _jsxs("fieldset", { className: "sc-field sc-options", children: [_jsx("legend", { className: "sc-field-label", children: "Options" }), options.map((option, index) => (_jsxs("div", { className: "sc-link-row", children: [_jsx("input", { className: "sc-input", value: option, maxLength: MAX_OPTION_LABEL_LENGTH, placeholder: `Option ${index + 1}`, onChange: (event) => setOptions(options.map((entry, at) => (at === index ? event.target.value : entry))) }), options.length > MIN_OPTIONS && (_jsx(Button, { variant: "ghost", size: "sm", onClick: () => setOptions(options.filter((_, at) => at !== index)), children: "Remove" }))] }, index))), options.length < MAX_OPTIONS && (_jsx(Button, { variant: "ghost", size: "sm", onClick: () => setOptions([...options, ""]), children: "Add an option" }))] }), props.error !== undefined && (_jsx("p", { className: "sc-form-error", role: "alert", children: props.error })), _jsxs("div", { className: "sc-form-actions", children: [_jsx(Button, { type: "submit", variant: "primary", disabled: props.busy === true || !ready, children: "Raise the decision" }), props.onCancel !== undefined && (_jsx(Button, { variant: "ghost", onClick: props.onCancel, children: "Cancel" }))] })] }));
22
+ }
23
+ //# sourceMappingURL=decision-form.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-form.js","sourceRoot":"","sources":["../../src/components/decision-form.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { type RestAnswerInput, type RestDecision, type RestTask } from "../api.js";
2
+ export interface DecisionCardProps {
3
+ readonly decision: RestDecision;
4
+ /** The task the decision is about, when it is about one and the page knows it. */
5
+ readonly task?: RestTask | undefined;
6
+ readonly taskHref?: ((task: RestTask) => string) | undefined;
7
+ /** Called with the person's answer. Left out, a waiting decision cannot be answered here. */
8
+ readonly onAnswer?: ((decision: RestDecision, input: RestAnswerInput) => void) | undefined;
9
+ readonly busy?: boolean | undefined;
10
+ }
11
+ export declare function DecisionCard(props: DecisionCardProps): import("react").JSX.Element;
12
+ export interface DecisionListProps {
13
+ readonly decisions: readonly RestDecision[];
14
+ /** The tasks the decisions may be about, by id, for the cards to name them. */
15
+ readonly tasks: ReadonlyMap<string, RestTask>;
16
+ readonly taskHref?: ((task: RestTask) => string) | undefined;
17
+ readonly onAnswer?: ((decision: RestDecision, input: RestAnswerInput) => void) | undefined;
18
+ readonly busy?: boolean | undefined;
19
+ readonly empty?: React.ReactNode;
20
+ }
21
+ export declare function DecisionList(props: DecisionListProps): import("react").JSX.Element;
22
+ //# sourceMappingURL=decision-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-list.d.ts","sourceRoot":"","sources":["../../src/components/decision-list.tsx"],"names":[],"mappings":"AACA,OAAO,EAAmB,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAOpG,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,kFAAkF;IAClF,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;IAC7D,6FAA6F;IAC7F,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC3F,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACrC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,+BAiGpD;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,SAAS,YAAY,EAAE,CAAC;IAC5C,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC9C,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;IAC7D,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC3F,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAClC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,+BA+BpD"}
@@ -0,0 +1,28 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { MAX_NOTE_LENGTH } from "../api.js";
4
+ import { Markdown } from "./markdown.js";
5
+ import { Button, cx, PersonChip, Time } from "./ui.js";
6
+ export function DecisionCard(props) {
7
+ const { decision, task } = props;
8
+ const [chosen, setChosen] = useState(undefined);
9
+ const [note, setNote] = useState("");
10
+ const answered = decision.answer !== null;
11
+ const chosenLabel = (id) => decision.options.find((option) => option.id === id)?.label ?? id;
12
+ return (_jsxs("article", { className: cx("sc-decision", answered && "sc-decision-answered"), children: [_jsxs("header", { className: "sc-decision-header", children: [_jsx("h3", { className: "sc-decision-question", children: decision.question }), _jsxs("p", { className: "sc-decision-meta", children: [_jsx(PersonChip, { person: decision.raisedBy }), " ", decision.run === null ? "asked" : `asked through ${decision.run.agent}`, " ", _jsx(Time, { iso: decision.createdAt }), task !== undefined && (_jsxs(_Fragment, { children: [" ", "about", " ", props.taskHref === undefined ? (_jsxs("span", { children: ["#", task.number, " ", task.title] })) : (_jsxs("a", { href: props.taskHref(task), children: ["#", task.number, " ", task.title] }))] }))] })] }), decision.body.length > 0 && _jsx(Markdown, { source: decision.body }), decision.answer !== null ? (_jsxs("div", { className: "sc-answer", children: [_jsx("p", { className: "sc-answer-option", children: chosenLabel(decision.answer.option) }), decision.answer.note !== null && (_jsx("p", { className: "sc-answer-note", children: decision.answer.note })), _jsxs("p", { className: "sc-decision-meta", children: [_jsx(PersonChip, { person: decision.answer.by }), " answered ", _jsx(Time, { iso: decision.answer.at })] })] })) : props.onAnswer === undefined ? (_jsx("p", { className: "sc-decision-waiting", children: "Waiting for a person." })) : (_jsxs("form", { className: "sc-answer-form", onSubmit: (event) => {
13
+ event.preventDefault();
14
+ if (chosen !== undefined) {
15
+ props.onAnswer?.(decision, {
16
+ option: chosen,
17
+ ...(note.trim() === "" ? {} : { note: note.trim() }),
18
+ });
19
+ }
20
+ }, children: [_jsx("div", { className: "sc-options-list", role: "radiogroup", "aria-label": "Options", children: decision.options.map((option) => (_jsxs("label", { className: cx("sc-option", chosen === option.id && "sc-option-chosen"), children: [_jsx("input", { type: "radio", name: `decision-${decision.id}`, value: option.id, checked: chosen === option.id, onChange: () => setChosen(option.id) }), _jsx("span", { children: option.label })] }, option.id))) }), _jsx("input", { className: "sc-input", placeholder: "A word about it, if any", maxLength: MAX_NOTE_LENGTH, value: note, onChange: (event) => setNote(event.target.value) }), _jsx("div", { className: "sc-form-actions", children: _jsx(Button, { type: "submit", variant: "primary", size: "sm", disabled: chosen === undefined || props.busy === true, children: "Answer" }) })] }))] }));
21
+ }
22
+ export function DecisionList(props) {
23
+ const waiting = props.decisions.filter((decision) => decision.answer === null);
24
+ const answered = props.decisions.filter((decision) => decision.answer !== null);
25
+ const card = (decision) => (_jsx(DecisionCard, { decision: decision, task: decision.taskId === null ? undefined : props.tasks.get(decision.taskId), taskHref: props.taskHref, onAnswer: props.onAnswer, busy: props.busy }, decision.id));
26
+ return (_jsxs("div", { className: "sc-decisions", children: [_jsxs("section", { "aria-label": "Waiting", children: [_jsxs("h2", { className: "sc-section-title", children: ["Waiting ", _jsx("span", { className: "sc-column-count", children: waiting.length })] }), waiting.length === 0 ? (props.empty ?? null) : waiting.map(card)] }), answered.length > 0 && (_jsxs("section", { "aria-label": "Answered", children: [_jsxs("h2", { className: "sc-section-title", children: ["Answered ", _jsx("span", { className: "sc-column-count", children: answered.length })] }), answered.map(card)] }))] }));
27
+ }
28
+ //# sourceMappingURL=decision-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-list.js","sourceRoot":"","sources":["../../src/components/decision-list.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ReactNode } from "react";
2
+ import type { RestEvent } from "../api.js";
3
+ /** What an event says, without its actor: the words after the name. */
4
+ export declare function describeEvent(event: RestEvent): string;
5
+ export interface EventFeedProps {
6
+ /** Oldest first, as the API hands them over; the feed shows them newest first. */
7
+ readonly events: readonly RestEvent[];
8
+ /** Where the line of an event leads, when it is about a task or a decision. */
9
+ readonly href?: ((event: RestEvent) => string | undefined) | undefined;
10
+ readonly empty?: ReactNode;
11
+ }
12
+ export declare function EventFeed(props: EventFeedProps): import("react").JSX.Element;
13
+ //# sourceMappingURL=event-feed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-feed.d.ts","sourceRoot":"","sources":["../../src/components/event-feed.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAkB3C,uEAAuE;AACvE,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAgCtD;AAED,MAAM,WAAW,cAAc;IAC7B,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC,+EAA+E;IAC/E,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,SAAS,KAAK,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;IACvE,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;CAC5B;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,+BA4B9C"}
@@ -0,0 +1,59 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { PersonChip, STATE_LABELS, Time } from "./ui.js";
3
+ // The feed: one line per event, newest first, as a sentence a person reads at a glance. It
4
+ // takes its data as props and nothing from the network.
5
+ const FIELD_WORDS = {
6
+ title: "the title",
7
+ body: "the body",
8
+ priority: "the priority",
9
+ assigneeId: "the assignee",
10
+ parentId: "what it is part of",
11
+ links: "the links",
12
+ };
13
+ /** "(as Claude Code)": what an agent did is said with what the agent calls itself. */
14
+ const as = (agent) => (agent === undefined ? "" : ` (as ${agent})`);
15
+ /** What an event says, without its actor: the words after the name. */
16
+ export function describeEvent(event) {
17
+ const { data } = event;
18
+ const task = data.number === undefined
19
+ ? "a task"
20
+ : `#${data.number}${data.title === undefined ? "" : ` ${data.title}`}`;
21
+ switch (event.kind) {
22
+ case "person.joined":
23
+ return "joined the board";
24
+ case "person.role_changed":
25
+ return `made ${data.login ?? "someone"} ${data.role === "admin" ? "an administrator" : "a member"}`;
26
+ case "task.created":
27
+ return `wrote ${task}`;
28
+ case "task.moved":
29
+ return `moved ${task} from ${STATE_LABELS[data.from ?? "idea"]} to ${STATE_LABELS[data.to ?? "idea"]}`;
30
+ case "task.updated": {
31
+ const fields = (data.fields ?? []).map((field) => FIELD_WORDS[field] ?? field);
32
+ return `changed ${fields.length === 0 ? "something" : fields.join(", ")} of ${task}`;
33
+ }
34
+ case "decision.raised":
35
+ return `asked${as(data.agent)}: ${data.question ?? "a question"}`;
36
+ case "decision.answered":
37
+ return `answered "${data.question ?? "a question"}": ${data.option ?? ""}`;
38
+ case "run.started":
39
+ return `started on ${task}${as(data.agent)}`;
40
+ case "run.reported":
41
+ return `reported on ${task}${as(data.agent)}${data.excerpt === undefined ? "" : `: ${data.excerpt}`}`;
42
+ case "run.handed_in":
43
+ return `handed in ${data.label ?? "something"} on ${task}${as(data.agent)}`;
44
+ case "run.ended":
45
+ return `${data.status === "finished" ? "finished" : data.status === "failed" ? "failed on" : "gave up on"} ${task}${as(data.agent)}`;
46
+ }
47
+ }
48
+ export function EventFeed(props) {
49
+ if (props.events.length === 0) {
50
+ return _jsx("div", { className: "sc-feed", children: props.empty ?? null });
51
+ }
52
+ const newestFirst = [...props.events].reverse();
53
+ return (_jsx("ol", { className: "sc-feed", "aria-label": "What happened", children: newestFirst.map((event) => {
54
+ const href = props.href?.(event);
55
+ const words = describeEvent(event);
56
+ return (_jsxs("li", { className: "sc-feed-item", children: [_jsx("span", { className: "sc-feed-actor", children: event.actor === null ? (_jsx("span", { className: "sc-person-login", children: "The console" })) : (_jsx(PersonChip, { person: event.actor })) }), _jsx("span", { className: "sc-feed-words", children: href === undefined ? words : _jsx("a", { href: href, children: words }) }), _jsx(Time, { iso: event.createdAt })] }, event.id));
57
+ }) }));
58
+ }
59
+ //# sourceMappingURL=event-feed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-feed.js","sourceRoot":"","sources":["../../src/components/event-feed.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function Markdown(props: {
2
+ readonly source: string;
3
+ }): import("react").JSX.Element;
4
+ //# sourceMappingURL=markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/components/markdown.tsx"],"names":[],"mappings":"AAUA,wBAAgB,QAAQ,CAAC,KAAK,EAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,+BA8C1D"}
@@ -0,0 +1,34 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import ReactMarkdown from "react-markdown";
3
+ import remarkGfm from "remark-gfm";
4
+ // What people and agents write is untrusted. It is rendered as React elements, never as HTML:
5
+ // raw HTML in the source stays text, links are limited to a few schemes and open elsewhere,
6
+ // and pictures come over https only, lazily and without a referrer.
7
+ const SAFE_LINK = /^(https?:|mailto:)/i;
8
+ const SAFE_IMAGE = /^https:\/\//i;
9
+ export function Markdown(props) {
10
+ return (_jsx("div", { className: "sc-prose", children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm],
11
+ // Everything passes through here unchanged; the components below decide what a URL may do.
12
+ urlTransform: (url) => url, components: {
13
+ a({ href, children }) {
14
+ if (href === undefined || href === "") {
15
+ return _jsx("span", { children: children });
16
+ }
17
+ if (href.startsWith("#")) {
18
+ return _jsx("a", { href: href, children: children });
19
+ }
20
+ if (SAFE_LINK.test(href)) {
21
+ return (_jsx("a", { href: href, target: "_blank", rel: "noopener noreferrer nofollow ugc", children: children }));
22
+ }
23
+ return _jsx("span", { children: children });
24
+ },
25
+ img({ src, alt, title }) {
26
+ const url = typeof src === "string" && SAFE_IMAGE.test(src) ? src : undefined;
27
+ if (url === undefined) {
28
+ return _jsx("span", { className: "sc-prose-image-text", children: alt ?? "" });
29
+ }
30
+ return (_jsx("img", { src: url, alt: alt ?? "", title: title, loading: "lazy", decoding: "async", referrerPolicy: "no-referrer" }));
31
+ },
32
+ }, children: props.source }) }));
33
+ }
34
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/components/markdown.tsx"],"names":[],"mappings":";AAAA,OAAO,aAAa,MAAM,gBAAgB,CAAC;AAC3C,OAAO,SAAS,MAAM,YAAY,CAAC;AAEnC,8FAA8F;AAC9F,4FAA4F;AAC5F,oEAAoE;AAEpE,MAAM,SAAS,GAAG,qBAAqB,CAAC;AACxC,MAAM,UAAU,GAAG,cAAc,CAAC;AAElC,MAAM,UAAU,QAAQ,CAAC,KAAkC;IACzD,OAAO,CACL,cAAK,SAAS,EAAC,UAAU,YACvB,KAAC,aAAa,IACZ,aAAa,EAAE,CAAC,SAAS,CAAC;YAC1B,2FAA2F;YAC3F,YAAY,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAC1B,UAAU,EAAE;gBACV,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE;oBAClB,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;wBACtC,OAAO,yBAAO,QAAQ,GAAQ,CAAC;oBACjC,CAAC;oBACD,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;wBACzB,OAAO,YAAG,IAAI,EAAE,IAAI,YAAG,QAAQ,GAAK,CAAC;oBACvC,CAAC;oBACD,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;wBACzB,OAAO,CACL,YAAG,IAAI,EAAE,IAAI,EAAE,MAAM,EAAC,QAAQ,EAAC,GAAG,EAAC,kCAAkC,YAClE,QAAQ,GACP,CACL,CAAC;oBACJ,CAAC;oBACD,OAAO,yBAAO,QAAQ,GAAQ,CAAC;gBACjC,CAAC;gBACD,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE;oBACrB,MAAM,GAAG,GAAG,OAAO,GAAG,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;oBAC9E,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;wBACtB,OAAO,eAAM,SAAS,EAAC,qBAAqB,YAAE,GAAG,IAAI,EAAE,GAAQ,CAAC;oBAClE,CAAC;oBACD,OAAO,CACL,cACE,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,GAAG,IAAI,EAAE,EACd,KAAK,EAAE,KAAK,EACZ,OAAO,EAAC,MAAM,EACd,QAAQ,EAAC,OAAO,EAChB,cAAc,EAAC,aAAa,GAC5B,CACH,CAAC;gBACJ,CAAC;aACF,YAEA,KAAK,CAAC,MAAM,GACC,GACZ,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { PersonRole, RestPerson } from "../api.js";
2
+ export interface PeopleListProps {
3
+ readonly people: readonly RestPerson[];
4
+ /** Whoever is looking, so that their own row says so. */
5
+ readonly me?: RestPerson | undefined;
6
+ /** Called with the role an administrator chose. Left out, roles are read here, not changed. */
7
+ readonly onChangeRole?: ((person: RestPerson, role: PersonRole) => void) | undefined;
8
+ readonly busy?: boolean | undefined;
9
+ }
10
+ export declare function PeopleList(props: PeopleListProps): import("react").JSX.Element;
11
+ //# sourceMappingURL=people.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"people.d.ts","sourceRoot":"","sources":["../../src/components/people.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAOxD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IACvC,yDAAyD;IACzD,QAAQ,CAAC,EAAE,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IACrC,+FAA+F;IAC/F,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACrF,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACrC;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,+BAiChD"}
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { PERSON_ROLES } from "../vocabulary.js";
3
+ import { PersonChip, ROLE_LABELS, RoleBadge } from "./ui.js";
4
+ export function PeopleList(props) {
5
+ return (_jsx("ul", { className: "sc-people", "aria-label": "People", children: props.people.map((person) => (_jsxs("li", { className: "sc-person-row", children: [_jsx(PersonChip, { person: person, size: "md" }), _jsxs("span", { className: "sc-person-name", children: [person.name ?? "", props.me?.id === person.id && _jsx("span", { className: "sc-muted", children: " (you)" })] }), props.onChangeRole === undefined ? (_jsx(RoleBadge, { role: person.role })) : (_jsxs("label", { className: "sc-field sc-field-inline", children: [_jsxs("span", { className: "sc-visually-hidden", children: ["Role of ", person.login] }), _jsx("select", { className: "sc-input", value: person.role, disabled: props.busy === true, onChange: (event) => props.onChangeRole?.(person, event.target.value), children: PERSON_ROLES.map((role) => (_jsx("option", { value: role, children: ROLE_LABELS[role] }, role))) })] }))] }, person.id))) }));
6
+ }
7
+ //# sourceMappingURL=people.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"people.js","sourceRoot":"","sources":["../../src/components/people.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAc7D,MAAM,UAAU,UAAU,CAAC,KAAsB;IAC/C,OAAO,CACL,aAAI,SAAS,EAAC,WAAW,gBAAY,QAAQ,YAC1C,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAC5B,cAAoB,SAAS,EAAC,eAAe,aAC3C,KAAC,UAAU,IAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAC,IAAI,GAAG,EACxC,gBAAM,SAAS,EAAC,gBAAgB,aAC7B,MAAM,CAAC,IAAI,IAAI,EAAE,EACjB,KAAK,CAAC,EAAE,EAAE,EAAE,KAAK,MAAM,CAAC,EAAE,IAAI,eAAM,SAAS,EAAC,UAAU,uBAAc,IAClE,EACN,KAAK,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,CAClC,KAAC,SAAS,IAAC,IAAI,EAAE,MAAM,CAAC,IAAI,GAAI,CACjC,CAAC,CAAC,CAAC,CACF,iBAAO,SAAS,EAAC,0BAA0B,aACzC,gBAAM,SAAS,EAAC,oBAAoB,yBAAU,MAAM,CAAC,KAAK,IAAQ,EAClE,iBACE,SAAS,EAAC,UAAU,EACpB,KAAK,EAAE,MAAM,CAAC,IAAI,EAClB,QAAQ,EAAE,KAAK,CAAC,IAAI,KAAK,IAAI,EAC7B,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,KAAmB,CAAC,YAElF,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAC1B,iBAAmB,KAAK,EAAE,IAAI,YAC3B,WAAW,CAAC,IAAI,CAAC,IADP,IAAI,CAER,CACV,CAAC,GACK,IACH,CACT,KAxBM,MAAM,CAAC,EAAE,CAyBb,CACN,CAAC,GACC,CACN,CAAC;AACJ,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { ReactNode } from "react";
2
+ import { type RestArtifact, type RestRun, type RunStatus } from "../api.js";
3
+ export declare const RUN_STATUS_LABELS: Readonly<Record<RunStatus, string>>;
4
+ export declare function RunStatusBadge(props: {
5
+ readonly status: RunStatus;
6
+ }): import("react").JSX.Element;
7
+ export interface RunCardProps {
8
+ readonly run: RestRun;
9
+ /** Where the decision the run waits for is answered, when the page knows. */
10
+ readonly decisionHref?: ((decisionId: string) => string) | undefined;
11
+ /** Where a file handed in is read; the console's own path, on the page's origin, when left out. */
12
+ readonly fileHref?: ((artifact: RestArtifact) => string) | undefined;
13
+ /** Called to mark a run that will not come back as abandoned. Left out, it cannot be here. */
14
+ readonly onAbandon?: ((run: RestRun) => void) | undefined;
15
+ readonly busy?: boolean | undefined;
16
+ }
17
+ export declare function RunCard(props: RunCardProps): import("react").JSX.Element;
18
+ export interface RunListProps {
19
+ readonly runs: readonly RestRun[];
20
+ readonly decisionHref?: ((decisionId: string) => string) | undefined;
21
+ readonly fileHref?: ((artifact: RestArtifact) => string) | undefined;
22
+ readonly onAbandon?: ((run: RestRun) => void) | undefined;
23
+ readonly busy?: boolean | undefined;
24
+ readonly empty?: ReactNode;
25
+ }
26
+ export declare function RunList(props: RunListProps): import("react").JSX.Element;
27
+ //# sourceMappingURL=runs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runs.d.ts","sourceRoot":"","sources":["../../src/components/runs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,OAAO,EAAE,KAAK,SAAS,EAAY,MAAM,WAAW,CAAC;AAOtF,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAMjE,CAAC;AAEF,wBAAgB,cAAc,CAAC,KAAK,EAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;CAAE,+BAYnE;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,6EAA6E;IAC7E,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;IACrE,mGAAmG;IACnG,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,YAAY,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;IACrE,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC1D,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACrC;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,+BAiE1C;AA4BD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,CAAC;IAClC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;IACrE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,YAAY,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;IACrE,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC1D,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;CAC5B;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,+BAkB1C"}
@@ -0,0 +1,45 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { restPath } from "../api.js";
3
+ import { Markdown } from "./markdown.js";
4
+ import { Badge, Button, formatBytes, PersonChip, Time } from "./ui.js";
5
+ // A run: one agent at work on one task for one person, with what it reported, what it handed
6
+ // in, and what it waits for. Takes its data as props and nothing from the network.
7
+ export const RUN_STATUS_LABELS = {
8
+ running: "At work",
9
+ waiting: "Waiting for a decision",
10
+ finished: "Finished",
11
+ failed: "Failed",
12
+ abandoned: "Abandoned",
13
+ };
14
+ export function RunStatusBadge(props) {
15
+ const tone = props.status === "running"
16
+ ? "accent"
17
+ : props.status === "waiting"
18
+ ? "warning"
19
+ : props.status === "finished"
20
+ ? "success"
21
+ : props.status === "failed"
22
+ ? "danger"
23
+ : "neutral";
24
+ return _jsx(Badge, { tone: tone, children: RUN_STATUS_LABELS[props.status] });
25
+ }
26
+ export function RunCard(props) {
27
+ const { run } = props;
28
+ const open = run.status === "running" || run.status === "waiting";
29
+ return (_jsxs("article", { className: "sc-run", "aria-label": `${run.agent} for ${run.person.login}`, children: [_jsxs("header", { className: "sc-run-header", children: [_jsx("span", { className: "sc-run-agent", children: run.agent }), _jsx(RunStatusBadge, { status: run.status }), _jsxs("span", { className: "sc-run-meta", children: ["for ", _jsx(PersonChip, { person: run.person }), " since ", _jsx(Time, { iso: run.startedAt }), run.endedAt !== null && (_jsxs(_Fragment, { children: [" ", "until ", _jsx(Time, { iso: run.endedAt })] }))] }), open && props.onAbandon !== undefined && (_jsx(Button, { variant: "ghost", size: "sm", disabled: props.busy === true, onClick: () => props.onAbandon?.(run), children: "Mark abandoned" }))] }), run.waitingFor !== null && (_jsxs("p", { className: "sc-run-waiting", children: ["Waiting for a decision", props.decisionHref !== undefined && (_jsxs(_Fragment, { children: [": ", _jsx("a", { href: props.decisionHref(run.waitingFor), children: "answer it" })] })), "."] })), run.reports.length > 0 && (_jsx("ol", { className: "sc-run-reports", "aria-label": "Reports", children: run.reports.map((report) => (_jsxs("li", { className: "sc-report", children: [_jsx(Time, { iso: report.createdAt }), _jsx(Markdown, { source: report.body })] }, report.id))) })), run.artifacts.length > 0 && (_jsx("ul", { className: "sc-link-list", "aria-label": "Handed in", children: run.artifacts.map((artifact) => (_jsx("li", { children: _jsx(ArtifactLink, { artifact: artifact, fileHref: props.fileHref }) }, artifact.id))) })), run.summary !== null && (_jsx("div", { className: "sc-run-summary", children: _jsx(Markdown, { source: run.summary }) }))] }));
30
+ }
31
+ /** A link as it was handed in; a file by its name, with its size, read from the console. */
32
+ function ArtifactLink(props) {
33
+ const { artifact } = props;
34
+ if (artifact.file === null) {
35
+ return (_jsx("a", { href: artifact.url ?? "", target: "_blank", rel: "noopener noreferrer nofollow ugc", children: artifact.label ?? artifact.url }));
36
+ }
37
+ return (_jsxs(_Fragment, { children: [_jsx("a", { href: props.fileHref?.(artifact) ?? restPath("files", artifact.id), rel: "nofollow ugc", children: artifact.label ?? artifact.file.name }), " ", _jsxs("span", { className: "sc-muted", children: [artifact.label === null ? "" : `${artifact.file.name}, `, formatBytes(artifact.file.size)] })] }));
38
+ }
39
+ export function RunList(props) {
40
+ if (props.runs.length === 0) {
41
+ return _jsx(_Fragment, { children: props.empty ?? null });
42
+ }
43
+ return (_jsx("div", { className: "sc-runs", children: props.runs.map((run) => (_jsx(RunCard, { run: run, decisionHref: props.decisionHref, fileHref: props.fileHref, onAbandon: props.onAbandon, busy: props.busy }, run.id))) }));
44
+ }
45
+ //# sourceMappingURL=runs.js.map