@popoverai/dotrequirements 0.32.1 → 0.34.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 (135) hide show
  1. package/dist/cli.js +32 -7
  2. package/dist/cloud.d.ts +18 -0
  3. package/dist/cloud.js +38 -0
  4. package/dist/commands/board/index.d.ts +13 -0
  5. package/dist/commands/board/index.js +96 -0
  6. package/dist/commands/branch-merge.d.ts +78 -0
  7. package/dist/commands/branch-merge.js +129 -0
  8. package/dist/commands/create-requirement-document.js +2 -2
  9. package/dist/commands/diff.js +15 -5
  10. package/dist/commands/init.js +7 -6
  11. package/dist/commands/link.js +27 -21
  12. package/dist/commands/mockup/index.d.ts +11 -0
  13. package/dist/commands/mockup/index.js +82 -0
  14. package/dist/commands/report.js +22 -9
  15. package/dist/commands/review-test.js +3 -2
  16. package/dist/commands/scores/index.d.ts +50 -0
  17. package/dist/commands/scores/index.js +190 -0
  18. package/dist/commands/solution/ask.d.ts +9 -0
  19. package/dist/commands/solution/ask.js +27 -0
  20. package/dist/commands/solution/author.d.ts +19 -0
  21. package/dist/commands/solution/author.js +202 -0
  22. package/dist/commands/solution/branch.d.ts +103 -0
  23. package/dist/commands/solution/branch.js +341 -0
  24. package/dist/commands/solution/brief.d.ts +81 -0
  25. package/dist/commands/solution/brief.js +47 -0
  26. package/dist/commands/solution/checkout.d.ts +27 -0
  27. package/dist/commands/solution/checkout.js +66 -0
  28. package/dist/commands/solution/client.d.ts +16 -0
  29. package/dist/commands/solution/client.js +46 -0
  30. package/dist/commands/solution/contract.d.ts +9 -0
  31. package/dist/commands/solution/contract.js +23 -0
  32. package/dist/commands/solution/create.d.ts +14 -0
  33. package/dist/commands/solution/create.js +52 -0
  34. package/dist/commands/solution/demo-script.d.ts +28 -0
  35. package/dist/commands/solution/demo-script.js +43 -0
  36. package/dist/commands/solution/image.d.ts +60 -0
  37. package/dist/commands/solution/image.js +148 -0
  38. package/dist/commands/solution/index.d.ts +12 -0
  39. package/dist/commands/solution/index.js +281 -0
  40. package/dist/commands/solution/look-up.d.ts +9 -0
  41. package/dist/commands/solution/look-up.js +69 -0
  42. package/dist/commands/solution/next.d.ts +12 -0
  43. package/dist/commands/solution/next.js +48 -0
  44. package/dist/commands/solution/plan-file.d.ts +22 -0
  45. package/dist/commands/solution/plan-file.js +33 -0
  46. package/dist/commands/solution/preview-screenshot.d.ts +21 -0
  47. package/dist/commands/solution/preview-screenshot.js +56 -0
  48. package/dist/commands/solution/pull-request.d.ts +25 -0
  49. package/dist/commands/solution/pull-request.js +117 -0
  50. package/dist/commands/solution/pushing.d.ts +66 -0
  51. package/dist/commands/solution/pushing.js +185 -0
  52. package/dist/commands/solution/rehearse.d.ts +10 -0
  53. package/dist/commands/solution/rehearse.js +24 -0
  54. package/dist/commands/solution/request.d.ts +3 -0
  55. package/dist/commands/solution/request.js +13 -0
  56. package/dist/commands/solution/review.d.ts +27 -0
  57. package/dist/commands/solution/review.js +104 -0
  58. package/dist/commands/solution/run-file.d.ts +42 -0
  59. package/dist/commands/solution/run-file.js +63 -0
  60. package/dist/commands/solution/share.d.ts +62 -0
  61. package/dist/commands/solution/share.js +346 -0
  62. package/dist/commands/solution/stall.d.ts +14 -0
  63. package/dist/commands/solution/stall.js +41 -0
  64. package/dist/commands/solution/start.d.ts +11 -0
  65. package/dist/commands/solution/start.js +20 -0
  66. package/dist/commands/solution/status.d.ts +39 -0
  67. package/dist/commands/solution/status.js +145 -0
  68. package/dist/commands/solution/summary.d.ts +13 -0
  69. package/dist/commands/solution/summary.js +5 -0
  70. package/dist/commands/solution/things.d.ts +118 -0
  71. package/dist/commands/solution/things.js +78 -0
  72. package/dist/commands/solution/thread.d.ts +13 -0
  73. package/dist/commands/solution/thread.js +53 -0
  74. package/dist/commands/solution/upload.d.ts +24 -0
  75. package/dist/commands/solution/upload.js +27 -0
  76. package/dist/commands/solution/video.d.ts +88 -0
  77. package/dist/commands/solution/video.js +364 -0
  78. package/dist/commands/solution/working-folder.d.ts +44 -0
  79. package/dist/commands/solution/working-folder.js +64 -0
  80. package/dist/commands/style-check.js +4 -4
  81. package/dist/commands/sync.d.ts +2 -1
  82. package/dist/commands/sync.js +21 -5
  83. package/dist/convex.d.ts +64 -10
  84. package/dist/convex.js +75 -10
  85. package/dist/harness/finalize.js +16 -8
  86. package/dist/harness/reportingStatus.js +2 -11
  87. package/dist/push/core.js +7 -2
  88. package/dist/rehearsal/derive.d.ts +23 -0
  89. package/dist/rehearsal/derive.js +112 -0
  90. package/dist/rehearsal/driver.d.ts +44 -0
  91. package/dist/rehearsal/driver.js +337 -0
  92. package/dist/rehearsal/earlier.d.ts +25 -0
  93. package/dist/rehearsal/earlier.js +138 -0
  94. package/dist/rehearsal/index.d.ts +5 -0
  95. package/dist/rehearsal/index.js +4 -0
  96. package/dist/rehearsal/live.d.ts +72 -0
  97. package/dist/rehearsal/live.js +301 -0
  98. package/dist/rehearsal/report.d.ts +4 -0
  99. package/dist/rehearsal/report.js +69 -0
  100. package/dist/rehearsal/types.d.ts +377 -0
  101. package/dist/rehearsal/types.js +8 -0
  102. package/dist/requirements/cloud-ai.d.ts +0 -6
  103. package/dist/requirements/cloud-ai.js +2 -11
  104. package/dist/requirements/cloud-coverage.js +4 -4
  105. package/dist/requirements/index.d.ts +6 -0
  106. package/dist/requirements/index.js +24 -0
  107. package/dist/schema/browser.d.ts +1 -1
  108. package/dist/schema/browser.js +3 -1
  109. package/dist/schema/file-writer.d.ts +5 -0
  110. package/dist/schema/file-writer.js +4 -0
  111. package/dist/schema/parser.d.ts +11 -2
  112. package/dist/schema/parser.js +11 -7
  113. package/dist/schema/schemas.d.ts +40 -0
  114. package/dist/schema/schemas.js +4 -0
  115. package/dist/sync/execute.d.ts +10 -1
  116. package/dist/sync/execute.js +76 -24
  117. package/dist/sync/index.d.ts +1 -1
  118. package/dist/sync/index.js +1 -1
  119. package/dist/sync/publish.d.ts +7 -0
  120. package/dist/sync/publish.js +2 -2
  121. package/dist/sync/segment.js +4 -1
  122. package/dist/sync/snapshot.d.ts +27 -5
  123. package/dist/sync/snapshot.js +92 -15
  124. package/dist/sync/solution-documents.d.ts +64 -0
  125. package/dist/sync/solution-documents.js +97 -0
  126. package/dist/sync/types.d.ts +19 -1
  127. package/dist/utils/command-error.d.ts +19 -0
  128. package/dist/utils/command-error.js +44 -0
  129. package/dist/utils/oauth-flow.js +2 -2
  130. package/dist/utils/project-selector.js +4 -4
  131. package/dist/version-messages.d.ts +28 -0
  132. package/dist/version-messages.js +87 -0
  133. package/package.json +3 -2
  134. package/dist/config.d.ts +0 -5
  135. package/dist/config.js +0 -12
@@ -0,0 +1,145 @@
1
+ import { api } from "../../convex.js";
2
+ import { outcomesOf } from "./brief.js";
3
+ import { solutionClient } from "./client.js";
4
+ import { requireWhere } from "./run-file.js";
5
+ const drafts = (outcome, agent) => outcome.drafter === agent;
6
+ const reviews = (outcome, agent) => (outcome.reviewers ?? []).includes(agent);
7
+ /**
8
+ * The outcome an agent is at, read off the plan panel: the one named, when
9
+ * `--outcome` names it; otherwise the one it is drafting, else one it
10
+ * reviews that stands reviewing, else one it stalled or asked on, else one
11
+ * ready for it to draft. Undefined when it is at none, as after it recorded
12
+ * its work; refused when it is at more than one and nothing says which.
13
+ */
14
+ export function agentAt(panel, agent, named) {
15
+ const outcomes = outcomesOf(panel);
16
+ if (named) {
17
+ const outcome = outcomes.find((each) => each.name === named);
18
+ if (!outcome) {
19
+ throw new Error(`The plan has no outcome called "${named}". Its outcomes: ${outcomes.map((each) => each.name).join(", ")}.`);
20
+ }
21
+ const drafting = drafts(outcome, agent);
22
+ const reviewing = reviews(outcome, agent);
23
+ if (!drafting && !reviewing) {
24
+ throw new Error(`${agent} neither drafts nor reviews "${named}".`);
25
+ }
26
+ return {
27
+ outcome,
28
+ part: reviewing && (!drafting || outcome.status === "reviewing")
29
+ ? "review"
30
+ : "draft",
31
+ };
32
+ }
33
+ const tiers = [
34
+ (outcome) => drafts(outcome, agent) && outcome.status === "drafting"
35
+ ? { outcome, part: "draft" }
36
+ : undefined,
37
+ (outcome) => reviews(outcome, agent) && outcome.status === "reviewing"
38
+ ? { outcome, part: "review" }
39
+ : undefined,
40
+ (outcome) => outcome.status === "stalled" || outcome.status === "awaiting decision"
41
+ ? drafts(outcome, agent)
42
+ ? { outcome, part: "draft" }
43
+ : reviews(outcome, agent)
44
+ ? { outcome, part: "review" }
45
+ : undefined
46
+ : undefined,
47
+ (outcome) => drafts(outcome, agent) && outcome.status === "ready"
48
+ ? { outcome, part: "draft" }
49
+ : undefined,
50
+ ];
51
+ for (const tier of tiers) {
52
+ const found = outcomes.flatMap((outcome) => {
53
+ const at = tier(outcome);
54
+ return at ? [at] : [];
55
+ });
56
+ if (found.length === 1)
57
+ return found[0];
58
+ if (found.length > 1) {
59
+ throw new Error(`${agent} is at more than one outcome: ${found.map((at) => `"${at.outcome.name}"`).join(", ")}. Name one with --outcome "<name>".`);
60
+ }
61
+ }
62
+ return undefined;
63
+ }
64
+ /** The plan panel, or a refusal when the solution isn't there. */
65
+ export async function panelOf(client, solutionId) {
66
+ const panel = await client.query(api.solutions.queries.getPlan, {
67
+ solutionId,
68
+ });
69
+ if (!panel)
70
+ throw new Error("Solution not found.");
71
+ return panel;
72
+ }
73
+ /**
74
+ * The outcome a verb is about: the one named, else the one the agent is at
75
+ * on the panel. Refused, saying how to name it, when it is at none.
76
+ */
77
+ export async function outcomeFor(client, where, what) {
78
+ if (where.outcome)
79
+ return where.outcome;
80
+ const at = agentAt(await panelOf(client, where.solutionId), where.agent);
81
+ if (!at) {
82
+ throw new Error(`${where.agent} is at no outcome now, so nothing says which ${what}. Name it with --outcome "<name>".`);
83
+ }
84
+ return at.outcome.name;
85
+ }
86
+ /**
87
+ * Whether a reviewer still owes its result on an outcome standing
88
+ * reviewing: an outcome with several reviewers stands reviewing until the
89
+ * last gives its result, so one that gave its own since the latest
90
+ * submission owes nothing more.
91
+ */
92
+ async function reviewerOwes(client, solutionId, outcome, agent) {
93
+ const thread = (await client.query(api.solutions.queries.getThread, {
94
+ solutionId,
95
+ outcome,
96
+ })) ?? [];
97
+ let since = 0;
98
+ thread.forEach((entry, at) => {
99
+ if (entry.kind === "submission")
100
+ since = at + 1;
101
+ });
102
+ return !thread
103
+ .slice(since)
104
+ .some((entry) => entry.agent === agent &&
105
+ (entry.kind === "review" || entry.kind === "escalation"));
106
+ }
107
+ /**
108
+ * `dotreq solution status`: where the outcome the agent is at stands, as
109
+ * recorded — its one word, with the reason when stalled. With `--json`,
110
+ * also which outcome that is, whether the agent drafts or reviews it there,
111
+ * and whether it still owes its part: what the Stop hook and the runner's
112
+ * read-back judge an agent's session by (STEP-REVIEW-9). An agent at no
113
+ * outcome, as after it recorded its work, owes nothing.
114
+ */
115
+ export async function statusCommand(options) {
116
+ const where = requireWhere(options);
117
+ const client = solutionClient();
118
+ const panel = await panelOf(client, where.solutionId);
119
+ const at = agentAt(panel, where.agent, where.outcome);
120
+ if (!at) {
121
+ if (options.json) {
122
+ process.stdout.write(`${JSON.stringify({ agent: where.agent, outcome: null, part: null, status: null, reason: null, reviews: false, owes: false })}\n`);
123
+ return;
124
+ }
125
+ process.stdout.write(`${where.agent} is at no outcome now.\n`);
126
+ return;
127
+ }
128
+ const { outcome, part } = at;
129
+ // CHECKPOINT-6.3.2.3: a drafter whose work was set aside owes nothing
130
+ // more there; the new draft is another session's.
131
+ const setAside = part === "draft" && outcome.setAside === true;
132
+ const owes = part === "draft"
133
+ ? !setAside &&
134
+ (outcome.status === "drafting" || outcome.status === "ready")
135
+ : outcome.status === "reviewing" &&
136
+ (await reviewerOwes(client, where.solutionId, outcome.name, where.agent));
137
+ if (options.json) {
138
+ process.stdout.write(`${JSON.stringify({ agent: where.agent, outcome: outcome.name, part, status: outcome.status, reason: outcome.reason ?? null, reviews: part === "review", ...(setAside ? { setAside } : {}), owes })}\n`);
139
+ return;
140
+ }
141
+ process.stdout.write(outcome.reason
142
+ ? `${outcome.name}: ${outcome.status} — ${outcome.reason}\n`
143
+ : `${outcome.name}: ${outcome.status}\n`);
144
+ }
145
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The executive summary a verb carries (STEP-REVIEW-20): for the owner,
3
+ * what the work is and what most needs their eye, where the comment is for
4
+ * the thread. `--executive-summary` is its name; `--summary` is short for
5
+ * it, for a person typing it by hand (VERB-1.6, 2.5).
6
+ */
7
+ export type SummaryOptions = {
8
+ executiveSummary?: string;
9
+ summary?: string;
10
+ };
11
+ /** The summary given, by either name; undefined when none, or only blanks. */
12
+ export declare function summaryGiven(options: SummaryOptions): string | undefined;
13
+ //# sourceMappingURL=summary.d.ts.map
@@ -0,0 +1,5 @@
1
+ /** The summary given, by either name; undefined when none, or only blanks. */
2
+ export function summaryGiven(options) {
3
+ return (options.executiveSummary?.trim() || options.summary?.trim() || undefined);
4
+ }
5
+ //# sourceMappingURL=summary.js.map
@@ -0,0 +1,118 @@
1
+ /** Where a thing is, as the backend stores it (solutions/schema.ts, `thingValidator`). */
2
+ export type Thing = {
3
+ kind: "document";
4
+ documentId: string;
5
+ } | {
6
+ kind: "board";
7
+ boardId: string;
8
+ } | {
9
+ kind: "mockup";
10
+ mockupId: string;
11
+ } | {
12
+ kind: "file";
13
+ path: string;
14
+ branch?: string;
15
+ } | {
16
+ kind: "link";
17
+ url: string;
18
+ title?: string;
19
+ } | {
20
+ kind: "preview";
21
+ port: number;
22
+ page?: string;
23
+ command: string;
24
+ screenshot?: string;
25
+ } | {
26
+ kind: "pull request";
27
+ url: string;
28
+ number: number;
29
+ } | {
30
+ kind: "video";
31
+ storageId: string;
32
+ name: string;
33
+ script: string;
34
+ /** Where each step of the script begins in the video, in seconds, when the recorder said (SIGHT-7.4). */
35
+ stepStarts?: number[];
36
+ } | {
37
+ kind: "demo script";
38
+ name: string;
39
+ script: string;
40
+ } | {
41
+ kind: "image";
42
+ storageId: string;
43
+ name: string;
44
+ } | ({
45
+ kind: "scores";
46
+ } & Scores);
47
+ /** One axis of a solution's scores: a whole number from 1 to 5, and why. */
48
+ export type AxisScore = {
49
+ score: number;
50
+ reason: string;
51
+ };
52
+ /**
53
+ * A solution's scores, by axis, as the backend stores them on an outcome
54
+ * (solutions/scores.ts). Made with `dotreq scores`, submitted as
55
+ * `scores:<id>`.
56
+ */
57
+ export type Scores = {
58
+ costOfDelay: AxisScore;
59
+ relevance: AxisScore;
60
+ entities: AxisScore;
61
+ api: AxisScore;
62
+ testing: AxisScore;
63
+ experience: AxisScore;
64
+ doubt: AxisScore;
65
+ };
66
+ /**
67
+ * A thing as an agent names it on the command line: where it is, or, for
68
+ * scores, the reference `dotreq scores create` printed, which the backend
69
+ * copies onto the outcome when the work is recorded
70
+ * (solutions/schema.ts, `submittedThingValidator`); for a video, the file in
71
+ * the checkout and the script it was recorded from, which `author` submits
72
+ * as the stored copy's id and the script's text (SIGHT-7.0); for an image,
73
+ * the file, which `author` submits as the stored copy's id and its name
74
+ * (SIGHT-9.0); for a demo's script, the steps file, which `author` submits
75
+ * as its text (SIGHT-13.0); for the solution's pull request, its number, which `author`
76
+ * checks against the repository and submits with its address (PULL-3); for
77
+ * a preview, its port, page and command, which `author` submits with a
78
+ * screenshot of its page when one can be taken (SIGHT-12.0). Any of them
79
+ * goes with the `--title` given for it, when titles are given (12.3).
80
+ */
81
+ export type Reference = Exclude<Thing, {
82
+ kind: "scores";
83
+ } | {
84
+ kind: "video";
85
+ } | {
86
+ kind: "demo script";
87
+ } | {
88
+ kind: "image";
89
+ } | {
90
+ kind: "pull request";
91
+ } | {
92
+ kind: "preview";
93
+ }> | {
94
+ kind: "scores";
95
+ scoresId: string;
96
+ } | {
97
+ kind: "video";
98
+ path: string;
99
+ scriptPath: string;
100
+ } | {
101
+ kind: "demo script";
102
+ path: string;
103
+ } | {
104
+ kind: "image";
105
+ path: string;
106
+ } | {
107
+ kind: "pull request";
108
+ number: number;
109
+ } | {
110
+ kind: "preview";
111
+ port: number;
112
+ page?: string;
113
+ command: string;
114
+ };
115
+ export declare const REFERENCE_FORMS = "A reference is document:<id>, board:<id>, mockup:<id>, scores:<id>, pr:<number>, file:<path>[@<branch>], link:<url>, image:<path>, video:<path> <script> (one argument, e.g. \"video:final.mp4 steps.json\"), demo-script:<path> or preview:<port>[/<page>] <command> (one argument, e.g. \"preview:8080/design/roll-count pnpm dev\", with the page when it isn't the first one).";
116
+ /** A thing from the reference an agent types on the command line. */
117
+ export declare function parseThing(reference: string): Reference;
118
+ //# sourceMappingURL=things.d.ts.map
@@ -0,0 +1,78 @@
1
+ /** A preview's reference, as an example the agent can follow. */
2
+ const PREVIEW_EXAMPLE = '"preview:8080/design/roll-count pnpm dev"';
3
+ export const REFERENCE_FORMS = `A reference is document:<id>, board:<id>, mockup:<id>, scores:<id>, pr:<number>, file:<path>[@<branch>], link:<url>, image:<path>, video:<path> <script> (one argument, e.g. "video:final.mp4 steps.json"), demo-script:<path> or preview:<port>[/<page>] <command> (one argument, e.g. ${PREVIEW_EXAMPLE}, with the page when it isn't the first one).`;
4
+ /** A thing from the reference an agent types on the command line. */
5
+ export function parseThing(reference) {
6
+ const colon = reference.indexOf(":");
7
+ if (colon === -1) {
8
+ throw new Error(`"${reference}" isn't a reference. ${REFERENCE_FORMS}`);
9
+ }
10
+ const kind = reference.slice(0, colon);
11
+ const rest = reference.slice(colon + 1);
12
+ if (!rest)
13
+ throw new Error(`"${reference}" names nothing. ${REFERENCE_FORMS}`);
14
+ switch (kind) {
15
+ case "document":
16
+ return { kind, documentId: rest };
17
+ case "board":
18
+ return { kind, boardId: rest };
19
+ case "mockup":
20
+ return { kind, mockupId: rest };
21
+ case "scores":
22
+ return { kind, scoresId: rest };
23
+ case "pr": {
24
+ // PULL-3: the solution's pull request, by the reference
25
+ // `dotreq solution pull-request` printed.
26
+ const number = Number(rest.replace(/^#/, ""));
27
+ if (!Number.isInteger(number) || number <= 0) {
28
+ throw new Error(`"${reference}" isn't a pull request's reference. It is pr: and the pull request's number, as \`dotreq solution pull-request\` prints it, e.g. pr:42.`);
29
+ }
30
+ return { kind: "pull request", number };
31
+ }
32
+ case "image":
33
+ // SIGHT-9.0: an image from the checkout, such as a screenshot.
34
+ return { kind, path: rest };
35
+ case "file": {
36
+ const at = rest.lastIndexOf("@");
37
+ if (at === -1)
38
+ return { kind, path: rest };
39
+ return { kind, path: rest.slice(0, at), branch: rest.slice(at + 1) };
40
+ }
41
+ case "link":
42
+ return { kind, url: rest };
43
+ case "demo-script":
44
+ // SIGHT-13.0: a demo's script, which the agent reviewing it records.
45
+ return { kind: "demo script", path: rest };
46
+ case "video": {
47
+ // SIGHT-7.0.1: a video comes with the script it was recorded from.
48
+ const space = rest.search(/\s/);
49
+ const path = space === -1 ? rest : rest.slice(0, space);
50
+ const scriptPath = space === -1 ? "" : rest.slice(space + 1).trim();
51
+ if (!scriptPath) {
52
+ throw new Error(`"${reference}" names a video without its script, so nothing was submitted. Submit the steps file it was recorded from with it, as one argument: "video:${path} steps.json".`);
53
+ }
54
+ return { kind, path, scriptPath };
55
+ }
56
+ case "preview": {
57
+ // SIGHT-3.2: the port, then, when the preview opens on a page other
58
+ // than the first, that page's path (3.2.0), then the command.
59
+ const space = rest.search(/\s/);
60
+ const address = /^(\d+)(\/\S*)?$/.exec(space === -1 ? rest : rest.slice(0, space));
61
+ const port = Number(address?.[1]);
62
+ const page = address?.[2] ?? "";
63
+ const command = space === -1 ? "" : rest.slice(space + 1).trim();
64
+ if (!address || port <= 0 || !command) {
65
+ throw new Error(`"${reference}" needs a port and the command that listens on it, as one argument: ${PREVIEW_EXAMPLE}.`);
66
+ }
67
+ if (page.startsWith("//")) {
68
+ throw new Error(`"${reference}" names a page that isn't a path on the preview. Name it from the root, as in ${PREVIEW_EXAMPLE}.`);
69
+ }
70
+ return page && page !== "/"
71
+ ? { kind, port, page, command }
72
+ : { kind, port, command };
73
+ }
74
+ default:
75
+ throw new Error(`"${kind}" isn't a kind of thing. ${REFERENCE_FORMS}`);
76
+ }
77
+ }
78
+ //# sourceMappingURL=things.js.map
@@ -0,0 +1,13 @@
1
+ import { type WhereOptions } from "./run-file.js";
2
+ /**
3
+ * `dotreq solution thread`: the thread of the outcome the agent is at, or
4
+ * of the one `--outcome` names, oldest first — each entry on one line
5
+ * saying who, any result, and what they said (VERB-6, STEP-REVIEW-5); with
6
+ * `--latest`, the newest comment only, and with `--latest <n>` the newest
7
+ * n, stalls, restarts and redrafts left out. The brief names this command
8
+ * rather than carrying the thread.
9
+ */
10
+ export declare function threadCommand(options: WhereOptions & {
11
+ latest?: string | true;
12
+ }): Promise<void>;
13
+ //# sourceMappingURL=thread.d.ts.map
@@ -0,0 +1,53 @@
1
+ import { api } from "../../convex.js";
2
+ import { solutionClient } from "./client.js";
3
+ import { requireWhere } from "./run-file.js";
4
+ import { outcomeFor } from "./status.js";
5
+ /**
6
+ * What `--latest` counts: what someone wrote — a submission note, a review
7
+ * result, an escalation or a decision. A stall, a restart and a redraft
8
+ * because the outcome it is on was redrafted are on the thread but not
9
+ * counted, so a drafter revising after a restart reads the review it is
10
+ * answering, not the restart (VERB-6.4, 6.5).
11
+ */
12
+ function isComment(entry) {
13
+ return (entry.kind !== "stall" &&
14
+ entry.kind !== "restart" &&
15
+ entry.kind !== "input changed");
16
+ }
17
+ /**
18
+ * `dotreq solution thread`: the thread of the outcome the agent is at, or
19
+ * of the one `--outcome` names, oldest first — each entry on one line
20
+ * saying who, any result, and what they said (VERB-6, STEP-REVIEW-5); with
21
+ * `--latest`, the newest comment only, and with `--latest <n>` the newest
22
+ * n, stalls, restarts and redrafts left out. The brief names this command
23
+ * rather than carrying the thread.
24
+ */
25
+ export async function threadCommand(options) {
26
+ // `--latest` alone is the newest entry; `--latest 3`, the newest three.
27
+ const latest = options.latest === undefined
28
+ ? undefined
29
+ : options.latest === true
30
+ ? 1
31
+ : Number(options.latest);
32
+ if (latest !== undefined && (!Number.isInteger(latest) || latest < 1)) {
33
+ throw new Error(`--latest is how many of the newest entries to print, 1 or more, not "${options.latest}".`);
34
+ }
35
+ const where = requireWhere(options);
36
+ const client = solutionClient();
37
+ const outcome = await outcomeFor(client, where, "thread to read");
38
+ const thread = await client.query(api.solutions.queries.getThread, { solutionId: where.solutionId, outcome });
39
+ if (thread === null)
40
+ throw new Error("Solution not found.");
41
+ if (thread.length === 0) {
42
+ process.stdout.write(`Nothing is on "${outcome}"'s thread yet.\n`);
43
+ return;
44
+ }
45
+ // The newest n comments, still oldest first (VERB-6.4).
46
+ const shown = latest === undefined ? thread : thread.filter(isComment).slice(-latest);
47
+ if (shown.length === 0) {
48
+ process.stdout.write(`Nothing but stalls and restarts is on "${outcome}"'s thread yet.\n`);
49
+ return;
50
+ }
51
+ process.stdout.write(`${shown.map((entry) => entry.line).join("\n")}\n`);
52
+ }
53
+ //# sourceMappingURL=thread.js.map
@@ -0,0 +1,24 @@
1
+ import type { FunctionReference } from "convex/server";
2
+ import type { solutionClient } from "./client.js";
3
+ /** A file read from the checkout, ready to upload. */
4
+ export type Upload = {
5
+ name: string;
6
+ contentType: string;
7
+ bytes: Uint8Array<ArrayBuffer>;
8
+ };
9
+ /**
10
+ * Upload a file the app keeps rather than the branch — a video (SIGHT-7.0)
11
+ * or an image (SIGHT-9.0): an upload URL from the backend, asked for with
12
+ * the solution it is for (none for an image a rehearsal gives an input,
13
+ * REHEARSE-4.7), the file POSTed to it with its type, and the stored copy's
14
+ * id back. Convex sets no size
15
+ * limit on these uploads; the POST has two minutes.
16
+ */
17
+ export declare function uploadToApp(client: ReturnType<typeof solutionClient>, uploadUrl: FunctionReference<"mutation">,
18
+ /** The upload URL endpoint's arguments: the solution, or the project for a rehearsal's input. */
19
+ args: {
20
+ solutionId: string;
21
+ } | {
22
+ project: string;
23
+ }, file: Upload): Promise<string>;
24
+ //# sourceMappingURL=upload.d.ts.map
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Upload a file the app keeps rather than the branch — a video (SIGHT-7.0)
3
+ * or an image (SIGHT-9.0): an upload URL from the backend, asked for with
4
+ * the solution it is for (none for an image a rehearsal gives an input,
5
+ * REHEARSE-4.7), the file POSTed to it with its type, and the stored copy's
6
+ * id back. Convex sets no size
7
+ * limit on these uploads; the POST has two minutes.
8
+ */
9
+ export async function uploadToApp(client, uploadUrl,
10
+ /** The upload URL endpoint's arguments: the solution, or the project for a rehearsal's input. */
11
+ args, file) {
12
+ const url = await client.mutation(uploadUrl, args);
13
+ const response = await fetch(url, {
14
+ method: "POST",
15
+ headers: { "Content-Type": file.contentType },
16
+ body: file.bytes,
17
+ });
18
+ if (!response.ok) {
19
+ throw new Error(`Uploading ${file.name} failed (${response.status} ${response.statusText}), so nothing was submitted. Submit it again.`);
20
+ }
21
+ const { storageId } = (await response.json());
22
+ if (!storageId) {
23
+ throw new Error(`Uploading ${file.name} returned no id, so nothing was submitted. Submit it again.`);
24
+ }
25
+ return storageId;
26
+ }
27
+ //# sourceMappingURL=upload.js.map
@@ -0,0 +1,88 @@
1
+ import type { solutionClient } from "./client.js";
2
+ /**
3
+ * Videos on an outcome (SIGHT-7): the drafter submits a video file from its
4
+ * checkout with the script it was recorded from. The video is uploaded to
5
+ * the app and never committed; the script travels as text, and the outcome's
6
+ * reviewer reads it in its brief.
7
+ *
8
+ * A browser plays MP4 with H.264 video and WebM with VP8 or VP9 video
9
+ * everywhere we support (Chrome, Edge, Firefox, Safari on macOS and iOS).
10
+ * HEVC and AV1 play only on some hardware, and QuickTime and Matroska only
11
+ * in some browsers, so they are refused. The codec is read from the file
12
+ * itself, since an extension says nothing about it. Kept in step with the
13
+ * backend's `ACCEPTED_VIDEO_FORMATS` (convex/solutions/videos.ts).
14
+ */
15
+ export declare const ACCEPTED_VIDEO_FORMATS = "an MP4 with H.264 video, or a WebM with VP8 or VP9 video";
16
+ export type VideoContentType = "video/mp4" | "video/webm";
17
+ /** What the file is: a format a browser plays, or why it isn't one. */
18
+ export type VideoFormat = {
19
+ contentType: VideoContentType;
20
+ } | {
21
+ refused: string;
22
+ };
23
+ /** A video read from the checkout, ready to upload. */
24
+ export type Video = {
25
+ name: string;
26
+ contentType: VideoContentType;
27
+ bytes: Uint8Array<ArrayBuffer>;
28
+ };
29
+ /** The video at a path, or a refusal naming the accepted formats (SIGHT-7.0.0). */
30
+ export declare function readVideo(path: string): Video;
31
+ /**
32
+ * The script a video was recorded from (SIGHT-7.0, 7.0.1): agentic-demo's
33
+ * steps file, JSON holding the browser commands for each step and the
34
+ * sentence said over it, as its text. Anything else is refused, so a
35
+ * reviewer never reads the wrong file as the demo's script.
36
+ */
37
+ export declare function readScript(path: string): string;
38
+ /**
39
+ * Where each step of the script begins in the video, in seconds
40
+ * (SIGHT-7.4): read from the summary `agentic-demo record` writes beside
41
+ * the video it records, `final.json` (@popoverai/browser-automation 0.15.4
42
+ * on), one segment per step: `index`, the step's 0-based place in the steps
43
+ * file, and `startSeconds`, where the step's first frame is in the final
44
+ * video, taken as given. The starts are kept in the steps file's order, so
45
+ * step n of a link, counted from 1 as the recorder prints it ("step 1/6"),
46
+ * is the start at n − 1 (SOLDOC-15.1.1). None when there is no such file,
47
+ * as beside a video recorded before the recorder wrote one, so a link to a
48
+ * step of the script opens the video at its start (SOLDOC-15.1.1.0); none,
49
+ * with a word on stderr, when the file isn't the recorder's summary of this
50
+ * script, one start for each of its steps.
51
+ */
52
+ export declare function readStepStarts(videoPath: string, script: string): number[] | undefined;
53
+ /**
54
+ * A demo's script, as the drafter submits it (SIGHT-13.0): the steps file
55
+ * the agent reviewing it records the video from, as its text.
56
+ */
57
+ export declare function readDemoScript(path: string): {
58
+ name: string;
59
+ script: string;
60
+ };
61
+ /** What container and video codec the bytes hold, read from the file itself. */
62
+ export declare function videoFormat(bytes: Uint8Array): VideoFormat;
63
+ /** A video read from the checkout with the script it was recorded from, and where each step of it begins when the recorder said. */
64
+ export type Recording = {
65
+ video: Video;
66
+ script: string;
67
+ stepStarts?: number[];
68
+ };
69
+ /**
70
+ * A video and its script, read and checked before anything is uploaded or
71
+ * recorded (SIGHT-7.0.0, 7.0.1), with its steps' starts (7.4).
72
+ */
73
+ export declare function readRecording(path: string, scriptPath: string): Recording;
74
+ /**
75
+ * A recording as it is submitted (SIGHT-7.0, 7.4, 13.2): the app's copy of
76
+ * the video, by the file's name, with the script's text and its steps'
77
+ * starts. Nothing goes on the branch.
78
+ */
79
+ export declare function submittedRecording(client: ReturnType<typeof solutionClient>, solutionId: string, { video, script, stepStarts }: Recording): Promise<{
80
+ kind: "video";
81
+ storageId: string;
82
+ name: string;
83
+ script: string;
84
+ stepStarts?: number[];
85
+ }>;
86
+ /** Upload a video to the app (SIGHT-7.0), and the stored copy's id back. */
87
+ export declare function uploadVideo(client: ReturnType<typeof solutionClient>, solutionId: string, video: Video): Promise<string>;
88
+ //# sourceMappingURL=video.d.ts.map