cloving 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +121 -21
- package/assets/watch-fonts/fira-code-OFL.md +93 -0
- package/assets/watch-fonts/fira-code-latin-400-normal.woff2 +0 -0
- package/assets/watch-fonts/fira-code-latin-500-normal.woff2 +0 -0
- package/assets/watch-fonts/heebo-OFL.md +93 -0
- package/assets/watch-fonts/heebo-latin-500-normal.woff2 +0 -0
- package/assets/watch-fonts/heebo-latin-700-normal.woff2 +0 -0
- package/assets/watch-fonts/heebo-latin-800-normal.woff2 +0 -0
- package/assets/watch-fonts/manifest.json +112 -0
- package/assets/watch-fonts/space-grotesk-OFL.md +93 -0
- package/assets/watch-fonts/space-grotesk-latin-400-normal.woff2 +0 -0
- package/assets/watch-fonts/space-grotesk-latin-500-normal.woff2 +0 -0
- package/assets/watch-fonts/space-grotesk-latin-600-normal.woff2 +0 -0
- package/assets/watch-fonts/space-grotesk-latin-700-normal.woff2 +0 -0
- package/dist/src/authority/commands.d.ts +1 -0
- package/dist/src/authority/commands.js +25 -4
- package/dist/src/authority/dispatch-decision.d.ts +1 -0
- package/dist/src/authority/dispatch-decision.js +7 -4
- package/dist/src/authority/events.js +2 -2
- package/dist/src/authority/handoff-chain.d.ts +24 -0
- package/dist/src/authority/handoff-chain.js +46 -0
- package/dist/src/authority/reconciliation.d.ts +1 -0
- package/dist/src/authority/reconciliation.js +18 -11
- package/dist/src/authority/transitions.d.ts +1 -1
- package/dist/src/authority/transitions.js +3 -0
- package/dist/src/broker/actor/authority-queries.d.ts +4 -0
- package/dist/src/broker/actor/authority-queries.js +51 -2
- package/dist/src/broker/actor/delivery-intents.d.ts +1 -0
- package/dist/src/broker/actor/effect-delivery.js +9 -0
- package/dist/src/broker/authority-admission.js +13 -5
- package/dist/src/chats/analysis-batches.d.ts +18 -0
- package/dist/src/chats/analysis-batches.js +15 -1
- package/dist/src/chats/analysis-checkpoint.d.ts +29 -0
- package/dist/src/chats/analysis-checkpoint.js +31 -0
- package/dist/src/chats/analysis-input.d.ts +7 -1
- package/dist/src/chats/analysis-input.js +20 -6
- package/dist/src/chats/analysis-merge.d.ts +16 -0
- package/dist/src/chats/analysis-merge.js +134 -0
- package/dist/src/chats/analysis-prompt.d.ts +8 -0
- package/dist/src/chats/analysis-prompt.js +27 -1
- package/dist/src/chats/analysis-proposal.d.ts +2 -0
- package/dist/src/chats/analysis-proposal.js +9 -0
- package/dist/src/chats/analysis-shape.d.ts +1 -0
- package/dist/src/chats/analysis-shape.js +11 -4
- package/dist/src/chats/reference-mapping.d.ts +16 -0
- package/dist/src/chats/reference-mapping.js +153 -0
- package/dist/src/chats/workflow-generation-projection.d.ts +8 -0
- package/dist/src/chats/workflow-generation-projection.js +75 -0
- package/dist/src/chats/workflow-generation-source.d.ts +25 -0
- package/dist/src/chats/workflow-generation-source.js +124 -0
- package/dist/src/chats/workflow-generation-text.d.ts +23 -0
- package/dist/src/chats/workflow-generation-text.js +74 -0
- package/dist/src/chats/workflow-generation.d.ts +69 -0
- package/dist/src/chats/workflow-generation.js +142 -0
- package/dist/src/cli/render.d.ts +1 -0
- package/dist/src/cli/render.js +60 -13
- package/dist/src/cli/usage.js +5 -2
- package/dist/src/cli/watch-board-view.d.ts +12 -1
- package/dist/src/cli/watch-board-view.js +57 -11
- package/dist/src/cli/watch-board.d.ts +7 -1
- package/dist/src/cli/watch-board.js +42 -10
- package/dist/src/cli/watch-client.d.ts +1 -1
- package/dist/src/cli/watch-client.js +7 -3
- package/dist/src/cli/watch-model.d.ts +10 -4
- package/dist/src/cli/watch-model.js +35 -58
- package/dist/src/cli/watch-page.js +21 -4
- package/dist/src/cli/watch-phases.js +3 -3
- package/dist/src/cli/watch-pr-command.d.ts +5 -2
- package/dist/src/cli/watch-pr-command.js +41 -4
- package/dist/src/cli/watch-pr-identity.d.ts +14 -2
- package/dist/src/cli/watch-pr-identity.js +25 -0
- package/dist/src/cli/watch-pr-observer.d.ts +1 -0
- package/dist/src/cli/watch-pr-observer.js +48 -6
- package/dist/src/cli/watch-pull-request.d.ts +10 -0
- package/dist/src/cli/watch-pull-request.js +130 -0
- package/dist/src/cli/watch-reads.d.ts +7 -1
- package/dist/src/cli/watch-reads.js +42 -20
- package/dist/src/cli/watch-render.d.ts +14 -1
- package/dist/src/cli/watch-render.js +2 -1
- package/dist/src/cli/watch-server.js +33 -2
- package/dist/src/cli/watch-turn.js +1 -1
- package/dist/src/cli/watch-view.d.ts +7 -0
- package/dist/src/cli/watch-view.js +51 -3
- package/dist/src/daemon/analysis-worker.d.ts +0 -2
- package/dist/src/daemon/analysis-worker.js +71 -19
- package/dist/src/daemon/chats-batch-binding.d.ts +23 -0
- package/dist/src/daemon/chats-batch-binding.js +99 -0
- package/dist/src/daemon/chats-capture.d.ts +18 -0
- package/dist/src/daemon/chats-capture.js +194 -0
- package/dist/src/daemon/chats-checkpoints.d.ts +41 -0
- package/dist/src/daemon/chats-checkpoints.js +186 -0
- package/dist/src/daemon/chats-files.d.ts +29 -2
- package/dist/src/daemon/chats-files.js +142 -3
- package/dist/src/daemon/chats-follow-up.d.ts +38 -0
- package/dist/src/daemon/chats-follow-up.js +180 -0
- package/dist/src/daemon/chats-question.d.ts +15 -0
- package/dist/src/daemon/chats-question.js +93 -0
- package/dist/src/daemon/chats-worker.d.ts +1 -0
- package/dist/src/daemon/chats-worker.js +52 -51
- package/dist/src/daemon/claude-turn.d.ts +2 -1
- package/dist/src/daemon/claude-turn.js +1 -1
- package/dist/src/daemon/claude-worker.d.ts +0 -2
- package/dist/src/daemon/claude-worker.js +6 -11
- package/dist/src/daemon/daemon.d.ts +5 -1
- package/dist/src/daemon/daemon.js +38 -10
- package/dist/src/daemon/delivery-router.js +6 -0
- package/dist/src/daemon/github-calls.d.ts +4 -0
- package/dist/src/daemon/github-calls.js +16 -7
- package/dist/src/daemon/github-ci.d.ts +6 -0
- package/dist/src/daemon/github-ci.js +170 -0
- package/dist/src/daemon/github-merge-call.d.ts +14 -0
- package/dist/src/daemon/github-merge-call.js +73 -0
- package/dist/src/daemon/github-merge.d.ts +3 -5
- package/dist/src/daemon/github-merge.js +52 -95
- package/dist/src/daemon/github-methods.d.ts +28 -0
- package/dist/src/daemon/github-methods.js +80 -16
- package/dist/src/daemon/github-operation.d.ts +2 -0
- package/dist/src/daemon/github-retry.d.ts +6 -0
- package/dist/src/daemon/github-retry.js +49 -0
- package/dist/src/daemon/github-ticket-status.js +27 -1
- package/dist/src/daemon/github-worker.js +2 -1
- package/dist/src/daemon/handoff-worker.d.ts +10 -0
- package/dist/src/daemon/handoff-worker.js +232 -0
- package/dist/src/daemon/issue-queue.d.ts +1 -0
- package/dist/src/daemon/issue-queue.js +94 -42
- package/dist/src/daemon/notify-journal.d.ts +18 -0
- package/dist/src/daemon/notify-journal.js +108 -0
- package/dist/src/daemon/notify-message.js +2 -1
- package/dist/src/daemon/notify.js +176 -37
- package/dist/src/daemon/retrying-turn.d.ts +3 -0
- package/dist/src/daemon/retrying-turn.js +55 -9
- package/dist/src/daemon/ticket-dependency-waits.d.ts +18 -0
- package/dist/src/daemon/ticket-dependency-waits.js +60 -0
- package/dist/src/daemon/ticket-registration.d.ts +8 -4
- package/dist/src/daemon/ticket-registration.js +76 -22
- package/dist/src/daemon/ticket-source.d.ts +4 -1
- package/dist/src/daemon/ticket-source.js +8 -2
- package/dist/src/decision-visibility.d.ts +2 -0
- package/dist/src/decision-visibility.js +10 -0
- package/dist/src/execution-pin.d.ts +4 -0
- package/dist/src/execution-pin.js +23 -2
- package/dist/src/host/start-delivery.d.ts +2 -1
- package/dist/src/host/start-delivery.js +1 -1
- package/dist/src/host/step-bridge-host.d.ts +1 -0
- package/dist/src/host/step-bridge-host.js +16 -0
- package/dist/src/host/world-reconciliation.d.ts +1 -0
- package/dist/src/host/world-reconciliation.js +3 -0
- package/dist/src/host/world-runs.js +5 -0
- package/dist/src/issue-identity.d.ts +6 -0
- package/dist/src/issue-identity.js +23 -0
- package/dist/src/service/queue-runs.d.ts +3 -0
- package/dist/src/service/queue-runs.js +39 -0
- package/dist/src/service/registry.d.ts +8 -2
- package/dist/src/service/registry.js +20 -8
- package/dist/src/service/replies.d.ts +2 -0
- package/dist/src/service/run-handlers.js +44 -12
- package/dist/src/service/service.d.ts +3 -0
- package/dist/src/service/service.js +3 -1
- package/dist/src/service/submission-handler.d.ts +1 -0
- package/dist/src/service/submission-handler.js +92 -13
- package/dist/src/service/worker-totals.js +25 -1
- package/dist/src/step-bridge.d.ts +9 -0
- package/dist/src/steps/handoff.d.ts +2 -0
- package/dist/src/steps/handoff.js +13 -0
- package/dist/src/ticket-dependencies.d.ts +1 -0
- package/dist/src/ticket-dependencies.js +15 -0
- package/dist/src/ticket-status.js +7 -4
- package/dist/src/token-prices.d.ts +2 -0
- package/dist/src/token-prices.js +41 -9
- package/dist/src/worker-usage.d.ts +9 -0
- package/dist/src/worker-usage.js +1 -1
- package/dist/src/workflow-admission.d.ts +1 -0
- package/dist/src/workflow-candidate.js +1 -0
- package/dist/src/workflow-contracts.d.ts +2 -0
- package/dist/src/workflow-contracts.js +8 -3
- package/dist/src/workflow-declaration.d.ts +11 -0
- package/dist/src/workflow-declaration.js +71 -15
- package/dist/src/workflow-discovery.d.ts +18 -0
- package/dist/src/workflow-discovery.js +33 -0
- package/dist/src/workflow-refusals.d.ts +6 -0
- package/dist/src/workflow-refusals.js +39 -0
- package/dist/src/workflows.d.ts +2 -1
- package/dist/src/workflows.js +1 -0
- package/dist/tools/admit-workflow.d.ts +13 -0
- package/dist/tools/admit-workflow.js +94 -0
- package/dist/tools/self-host-project.d.ts +17 -0
- package/dist/tools/self-host-project.js +177 -0
- package/dist/tools/self-host.js +27 -81
- package/dist/tools/workflow-bundle-dependencies.d.ts +5 -0
- package/dist/tools/workflow-bundle-dependencies.js +93 -0
- package/dist/tools/workflow-bundles.d.ts +20 -0
- package/dist/tools/workflow-bundles.js +173 -0
- package/dist/tools/workflow-candidate-counts.d.ts +8 -0
- package/dist/tools/workflow-candidate-counts.js +251 -0
- package/dist/tools/workflow-candidate-program.d.ts +11 -0
- package/dist/tools/workflow-candidate-program.js +78 -0
- package/dist/tools/workflow-candidate-source.d.ts +6 -0
- package/dist/tools/workflow-candidate-source.js +107 -0
- package/dist/tools/workflow-candidate-syntax.d.ts +15 -0
- package/dist/tools/workflow-candidate-syntax.js +219 -0
- package/dist/tools/workflow-folder-capture.d.ts +17 -0
- package/dist/tools/workflow-folder-capture.js +216 -0
- package/dist/tools/workflow-folders.d.ts +33 -0
- package/dist/tools/workflow-folders.js +150 -0
- package/dist/tools/workflow-source-effects.d.ts +10 -0
- package/dist/tools/workflow-source-effects.js +213 -0
- package/dist/workflows/analyze-chats.d.ts +6 -1
- package/dist/workflows/analyze-chats.declaration.json +14 -1
- package/dist/workflows/analyze-chats.js +188 -11
- package/dist/workflows/develop-prd.js +71 -3
- package/dist/workflows/develop-ticket.js +5 -0
- package/dist/workflows/ticket-prompts.js +12 -2
- package/package.json +21 -3
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { type PrRepository } from "./watch-pr-identity.ts";
|
|
2
|
+
import { type WorkflowStages } from "../workflow-declaration.ts";
|
|
1
3
|
import { type Fields } from "../protocol.ts";
|
|
4
|
+
import { type WorkflowRefusal } from "../workflow-refusals.ts";
|
|
2
5
|
interface ReadStatus extends Fields {
|
|
3
6
|
readonly runId: string;
|
|
4
7
|
readonly latestSequence: number;
|
|
@@ -13,8 +16,11 @@ interface ReadRun {
|
|
|
13
16
|
readonly events: readonly ReadEvent[];
|
|
14
17
|
}
|
|
15
18
|
export interface WatchRead {
|
|
19
|
+
readonly queue?: Fields;
|
|
16
20
|
readonly service: string;
|
|
17
21
|
readonly workflows: readonly string[];
|
|
22
|
+
readonly workflowRefusals: readonly WorkflowRefusal[];
|
|
23
|
+
readonly workflowStages?: WorkflowStages;
|
|
18
24
|
readonly summaries: readonly ReadStatus[];
|
|
19
25
|
readonly runs: readonly ReadRun[];
|
|
20
26
|
readonly completionCandidates: readonly ReadRun[];
|
|
@@ -24,5 +30,5 @@ export interface WatchReader {
|
|
|
24
30
|
readonly read: (now: string) => Promise<WatchRead>;
|
|
25
31
|
readonly run: (runId: string) => Promise<WatchRead>;
|
|
26
32
|
}
|
|
27
|
-
export declare function watchReader(runtimeDirectory: string): WatchReader;
|
|
33
|
+
export declare function watchReader(runtimeDirectory: string, repository?: PrRepository | null): WatchReader;
|
|
28
34
|
export {};
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import { establishedIssue } from "./watch-pr-identity.js";
|
|
2
|
+
import { isWorkflowStages, } from "../workflow-declaration.js";
|
|
1
3
|
import { record } from "../protocol.js";
|
|
2
4
|
import { send } from "./client.js";
|
|
3
5
|
import { activeRun, recentRun } from "./watch-board.js";
|
|
6
|
+
import { workflowRefusals, } from "../workflow-refusals.js";
|
|
4
7
|
const unavailable = {
|
|
5
8
|
service: "down",
|
|
6
9
|
workflows: [],
|
|
10
|
+
workflowRefusals: [],
|
|
7
11
|
summaries: [],
|
|
8
12
|
runs: [],
|
|
9
13
|
completionCandidates: [],
|
|
@@ -79,15 +83,15 @@ async function creationOf(reader, runId) {
|
|
|
79
83
|
}
|
|
80
84
|
return null;
|
|
81
85
|
}
|
|
82
|
-
function matchingCompletion(status,
|
|
83
|
-
const
|
|
86
|
+
function matchingCompletion(status, context) {
|
|
87
|
+
const issue = establishedIssue(context.repository, status["issueIdentity"]);
|
|
84
88
|
return (status.state === "completed" &&
|
|
85
89
|
status["workflowId"] === "develop-issue" &&
|
|
86
90
|
record(status["outcome"])?.["kind"] === "handoff_requested" &&
|
|
87
91
|
record(status["outcome"])?.["ticketStatus"] !== "partial" &&
|
|
88
92
|
record(status["outcome"])?.["issueUpdate"] !== "failed" &&
|
|
89
|
-
|
|
90
|
-
|
|
93
|
+
issue !== null &&
|
|
94
|
+
context.issues.has(JSON.stringify(issue)));
|
|
91
95
|
}
|
|
92
96
|
async function completionOf(reader, search) {
|
|
93
97
|
const { runId, latestSequence } = search.summary;
|
|
@@ -106,12 +110,16 @@ async function completionOf(reader, search) {
|
|
|
106
110
|
state: status.state,
|
|
107
111
|
workflowId: status["workflowId"],
|
|
108
112
|
ticketId: status["ticketId"],
|
|
113
|
+
issueIdentity: status["issueIdentity"],
|
|
109
114
|
outcome: status["outcome"],
|
|
110
115
|
},
|
|
111
116
|
};
|
|
112
117
|
reader.completions.set(runId, known);
|
|
113
118
|
}
|
|
114
|
-
if (!matchingCompletion(known.status,
|
|
119
|
+
if (!matchingCompletion(known.status, {
|
|
120
|
+
issues: search.issues,
|
|
121
|
+
repository: reader.repository,
|
|
122
|
+
}))
|
|
115
123
|
return null;
|
|
116
124
|
const creation = known.creation === undefined
|
|
117
125
|
? await creationOf(reader, runId)
|
|
@@ -119,11 +127,20 @@ async function completionOf(reader, search) {
|
|
|
119
127
|
reader.completions.set(runId, { ...known, creation });
|
|
120
128
|
return { status: known.status, events: creation === null ? [] : [creation] };
|
|
121
129
|
}
|
|
130
|
+
function refreshedLinks(run, status) {
|
|
131
|
+
const links = Object.fromEntries(["parentRunId", "chainId", "childRunIds"]
|
|
132
|
+
.filter((name) => Object.hasOwn(status, name))
|
|
133
|
+
.map((name) => [name, status[name]]));
|
|
134
|
+
return {
|
|
135
|
+
...run,
|
|
136
|
+
status: { ...run.status, ...links },
|
|
137
|
+
};
|
|
138
|
+
}
|
|
122
139
|
async function detailed(reader, summary) {
|
|
123
140
|
const { runId, latestSequence: sequence } = summary;
|
|
124
141
|
const known = reader.details.get(runId);
|
|
125
142
|
if (known !== undefined && known.sequence === sequence)
|
|
126
|
-
return known.value;
|
|
143
|
+
return refreshedLinks(known.value, summary);
|
|
127
144
|
const shown = await asked(reader, {
|
|
128
145
|
operation: "status",
|
|
129
146
|
parameters: { runId },
|
|
@@ -160,10 +177,10 @@ async function decisionsOf(reader) {
|
|
|
160
177
|
});
|
|
161
178
|
return list(questions["decisions"]);
|
|
162
179
|
}
|
|
163
|
-
function
|
|
180
|
+
function stoppedIssues(runs, context) {
|
|
164
181
|
const stopped = runs
|
|
165
182
|
.map((run) => run.status)
|
|
166
|
-
.filter((status) => recentRun(status.latestAt, now) &&
|
|
183
|
+
.filter((status) => recentRun(status.latestAt, context.now) &&
|
|
167
184
|
status["workflowId"] === "develop-issue" &&
|
|
168
185
|
(["failed", "cancelled"].includes(status.state) ||
|
|
169
186
|
(status.state === "completed" &&
|
|
@@ -171,16 +188,15 @@ function stoppedTicketIds(runs, now) {
|
|
|
171
188
|
.toSorted((first, second) => Date.parse(second.latestAt ?? "") - Date.parse(first.latestAt ?? ""))
|
|
172
189
|
.slice(0, 20);
|
|
173
190
|
return new Set(stopped.flatMap((status) => {
|
|
174
|
-
const
|
|
175
|
-
return status.state === "completed" &&
|
|
176
|
-
|
|
177
|
-
record(status["outcome"])?.["issueUpdate"] !== "failed" &&
|
|
178
|
-
typeof ticketId === "string" &&
|
|
179
|
-
ticketId !== ""
|
|
180
|
-
? [ticketId]
|
|
191
|
+
const issue = establishedIssue(context.repository, status["issueIdentity"]);
|
|
192
|
+
return status.state === "completed" && issue !== null
|
|
193
|
+
? [JSON.stringify(issue)]
|
|
181
194
|
: [];
|
|
182
195
|
}));
|
|
183
196
|
}
|
|
197
|
+
function stageMetadata(value) {
|
|
198
|
+
return Object.fromEntries(Object.entries(record(value) ?? {}).flatMap(([workflowId, stages]) => isWorkflowStages(stages) ? [[workflowId, stages]] : []));
|
|
199
|
+
}
|
|
184
200
|
async function service(reader, now) {
|
|
185
201
|
const status = await asked(reader, {
|
|
186
202
|
operation: "status",
|
|
@@ -194,20 +210,25 @@ async function service(reader, now) {
|
|
|
194
210
|
const current = summaries.filter((summary) => activeRun(summary.state) || recentRun(summary.latestAt, now));
|
|
195
211
|
for (const summary of current)
|
|
196
212
|
runs.push(await detailed(reader, summary));
|
|
197
|
-
const
|
|
198
|
-
const older =
|
|
213
|
+
const issues = stoppedIssues(runs, { now, repository: reader.repository });
|
|
214
|
+
const older = issues.size === 0
|
|
199
215
|
? []
|
|
200
216
|
: summaries.filter((summary) => !recentRun(summary.latestAt, now) &&
|
|
201
217
|
summary["workflowId"] === "develop-issue" &&
|
|
202
218
|
summary.state === "completed");
|
|
203
219
|
for (const summary of older) {
|
|
204
|
-
const candidate = await completionOf(reader, { summary,
|
|
220
|
+
const candidate = await completionOf(reader, { summary, issues });
|
|
205
221
|
if (candidate !== null)
|
|
206
222
|
completionCandidates.push(candidate);
|
|
207
223
|
}
|
|
208
224
|
return {
|
|
209
225
|
service: "up",
|
|
226
|
+
...(record(status["queue"]) === undefined
|
|
227
|
+
? {}
|
|
228
|
+
: { queue: record(status["queue"]) ?? {} }),
|
|
210
229
|
workflows: list(status["workflows"]).filter((value) => typeof value === "string"),
|
|
230
|
+
workflowStages: stageMetadata(status["workflowStages"]),
|
|
231
|
+
workflowRefusals: workflowRefusals(status["workflowRefusals"]),
|
|
211
232
|
summaries,
|
|
212
233
|
runs,
|
|
213
234
|
completionCandidates,
|
|
@@ -226,7 +247,7 @@ async function singleRun(reader, runId) {
|
|
|
226
247
|
const status = statusOf(reply.result["run"]);
|
|
227
248
|
const known = reader.details.get(runId);
|
|
228
249
|
const value = known !== undefined && known.sequence === status.latestSequence
|
|
229
|
-
? known.value
|
|
250
|
+
? refreshedLinks(known.value, status)
|
|
230
251
|
: await remember(reader, status);
|
|
231
252
|
return {
|
|
232
253
|
...unavailable,
|
|
@@ -235,9 +256,10 @@ async function singleRun(reader, runId) {
|
|
|
235
256
|
decisions: await decisionsOf(reader),
|
|
236
257
|
};
|
|
237
258
|
}
|
|
238
|
-
export function watchReader(runtimeDirectory) {
|
|
259
|
+
export function watchReader(runtimeDirectory, repository = null) {
|
|
239
260
|
const reader = {
|
|
240
261
|
runtimeDirectory,
|
|
262
|
+
repository,
|
|
241
263
|
details: new Map(),
|
|
242
264
|
completions: new Map(),
|
|
243
265
|
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { CardForm } from "./watch-run-input.ts";
|
|
2
2
|
import type { WorkerUsage } from "../worker-usage.ts";
|
|
3
|
-
import type { PrObservation } from "./watch-pr-identity.ts";
|
|
3
|
+
import type { PrIdentity, PrObservation } from "./watch-pr-identity.ts";
|
|
4
|
+
import type { WorkflowRefusal } from "../workflow-refusals.ts";
|
|
5
|
+
import type { Fields } from "../protocol.ts";
|
|
4
6
|
export interface WatchItem {
|
|
5
7
|
readonly kind: string;
|
|
6
8
|
readonly text: string;
|
|
@@ -62,6 +64,9 @@ export interface WatchStep {
|
|
|
62
64
|
readonly startedAt: string | null;
|
|
63
65
|
}
|
|
64
66
|
export interface WatchCard {
|
|
67
|
+
readonly parentRunId?: string | null;
|
|
68
|
+
readonly chainId?: string;
|
|
69
|
+
readonly childRunIds?: readonly string[];
|
|
65
70
|
readonly estimatedCostUsd: number | null;
|
|
66
71
|
readonly runId: string;
|
|
67
72
|
readonly title: string | null;
|
|
@@ -92,8 +97,14 @@ export interface WatchWorkflow {
|
|
|
92
97
|
readonly columns: readonly WatchColumn[];
|
|
93
98
|
}
|
|
94
99
|
export interface WatchRun {
|
|
100
|
+
readonly parentRunId?: string | null;
|
|
101
|
+
readonly chainId?: string;
|
|
102
|
+
readonly childRunIds?: readonly string[];
|
|
103
|
+
readonly mergeProof?: PrIdentity | null;
|
|
104
|
+
readonly issueIdentity?: PrIdentity | null;
|
|
95
105
|
readonly issueUpdate?: "failed";
|
|
96
106
|
readonly ticketStatus?: "complete" | "partial";
|
|
107
|
+
readonly promotionId?: string;
|
|
97
108
|
readonly estimatedCostUsd: number | null;
|
|
98
109
|
readonly ticketId: string | null;
|
|
99
110
|
readonly title: string | null;
|
|
@@ -121,6 +132,8 @@ export interface WatchRun {
|
|
|
121
132
|
readonly mergeCommit: string | null;
|
|
122
133
|
}
|
|
123
134
|
export interface WatchModel {
|
|
135
|
+
readonly queue?: Fields;
|
|
136
|
+
readonly workflowRefusals?: readonly WorkflowRefusal[];
|
|
124
137
|
readonly cardForms?: readonly CardForm[];
|
|
125
138
|
readonly workflows: readonly WatchWorkflow[];
|
|
126
139
|
readonly startWorkflowId: string | null;
|
|
@@ -75,7 +75,8 @@ export function completedDetail(run) {
|
|
|
75
75
|
const update = run.issueUpdate === "failed"
|
|
76
76
|
? " Issue status update failed; check the GitHub operation."
|
|
77
77
|
: "";
|
|
78
|
-
|
|
78
|
+
const promotion = run.promotionId === undefined ? "" : ` Promotion: ${run.promotionId}.`;
|
|
79
|
+
return `${verdicts[run.decision] ?? ""}The run completed${time} · cost ${cost}.${promotion}${ticket}${update}`;
|
|
79
80
|
}
|
|
80
81
|
export function phaseTime(phase, now) {
|
|
81
82
|
if (phase.startedAt === null)
|
|
@@ -13,6 +13,20 @@ import { watchStream } from "./watch-stream.js";
|
|
|
13
13
|
export const defaultWatchPort = 3663;
|
|
14
14
|
const forbidden = { status: 403, type: "text/plain", body: "refused" };
|
|
15
15
|
const notFound = { status: 404, type: "text/plain", body: "not found" };
|
|
16
|
+
const fontFiles = new Map([
|
|
17
|
+
"fira-code-latin-400-normal.woff2",
|
|
18
|
+
"fira-code-latin-500-normal.woff2",
|
|
19
|
+
"heebo-latin-500-normal.woff2",
|
|
20
|
+
"heebo-latin-700-normal.woff2",
|
|
21
|
+
"heebo-latin-800-normal.woff2",
|
|
22
|
+
"space-grotesk-latin-400-normal.woff2",
|
|
23
|
+
"space-grotesk-latin-500-normal.woff2",
|
|
24
|
+
"space-grotesk-latin-600-normal.woff2",
|
|
25
|
+
"space-grotesk-latin-700-normal.woff2",
|
|
26
|
+
].map((name) => [
|
|
27
|
+
`/watch-fonts-v1/${name}`,
|
|
28
|
+
new URL(`assets/watch-fonts/${name}`, import.meta.resolve("#package")),
|
|
29
|
+
]));
|
|
16
30
|
const libraryFile = fileURLToPath(import.meta.resolve("preact"));
|
|
17
31
|
function parsed(text) {
|
|
18
32
|
try {
|
|
@@ -81,6 +95,7 @@ async function snapshot(watch, runId) {
|
|
|
81
95
|
]);
|
|
82
96
|
const model = watchModel({
|
|
83
97
|
...read,
|
|
98
|
+
repository: watch.observer.repository ?? null,
|
|
84
99
|
home: homedir(),
|
|
85
100
|
client: watch.settings.client,
|
|
86
101
|
updatedAt,
|
|
@@ -93,9 +108,25 @@ async function snapshot(watch, runId) {
|
|
|
93
108
|
cardForms: watch.actions?.forms.filter((form) => shown.workflows.some((workflow) => workflow.workflowId === form.workflowId)) ?? [],
|
|
94
109
|
};
|
|
95
110
|
}
|
|
111
|
+
async function fontReply(request) {
|
|
112
|
+
const fontFile = fontFiles.get(request.url ?? "");
|
|
113
|
+
if (fontFile === undefined)
|
|
114
|
+
return request.url?.startsWith("/watch-fonts-v1/") ? notFound : null;
|
|
115
|
+
if (request.method !== "GET")
|
|
116
|
+
return notFound;
|
|
117
|
+
return {
|
|
118
|
+
status: 200,
|
|
119
|
+
type: "font/woff2",
|
|
120
|
+
body: await readFile(fontFile),
|
|
121
|
+
cache: "public, max-age=31536000, immutable",
|
|
122
|
+
};
|
|
123
|
+
}
|
|
96
124
|
async function answered(watch, request) {
|
|
97
125
|
if (!watchHost(request))
|
|
98
126
|
return forbidden;
|
|
127
|
+
const font = await fontReply(request);
|
|
128
|
+
if (font !== null)
|
|
129
|
+
return font;
|
|
99
130
|
const url = new URL(String(request.url), "http://localhost");
|
|
100
131
|
if (request.method === "GET")
|
|
101
132
|
return readReply(watch, url);
|
|
@@ -137,7 +168,7 @@ async function readReply(watch, url) {
|
|
|
137
168
|
function replied(response, reply) {
|
|
138
169
|
response.writeHead(reply.status, {
|
|
139
170
|
"content-type": reply.type,
|
|
140
|
-
"cache-control": "no-store",
|
|
171
|
+
"cache-control": reply.cache ?? "no-store",
|
|
141
172
|
});
|
|
142
173
|
response.end(reply.body);
|
|
143
174
|
}
|
|
@@ -161,7 +192,7 @@ export async function watchServer(settings) {
|
|
|
161
192
|
: await watchActions(settings.runtimeDirectory),
|
|
162
193
|
settings,
|
|
163
194
|
observer,
|
|
164
|
-
reader: watchReader(settings.runtimeDirectory),
|
|
195
|
+
reader: watchReader(settings.runtimeDirectory, observer.repository ?? null),
|
|
165
196
|
streams: new Map(),
|
|
166
197
|
github: new Map(),
|
|
167
198
|
};
|
|
@@ -32,7 +32,7 @@ export function Turn(props) {
|
|
|
32
32
|
const groups = groupActivity(turn.activity);
|
|
33
33
|
const working = turn.outcome === "in work";
|
|
34
34
|
const cost = priceText(turn.costUsd, turn.estimatedCostUsd);
|
|
35
|
-
const heading = ["
|
|
35
|
+
const heading = ["Agent turn", turn.outcome, turnTime(turn, now), cost];
|
|
36
36
|
const place = `Branch ${turn.branch} · work tree ${turn.worktree}`;
|
|
37
37
|
const activity = groups.map((items, index) => component(Group, { items, open: working && index === groups.length - 1 }));
|
|
38
38
|
return element("section", {
|
|
@@ -2,6 +2,9 @@ import type { CardControls } from "./watch-card-view.ts";
|
|
|
2
2
|
import { type Shown } from "./watch-element.ts";
|
|
3
3
|
import { type Copying, type WatchModel, type WatchPhase, type WatchRun } from "./watch-render.ts";
|
|
4
4
|
import { type ColumnControls } from "./watch-board-view.ts";
|
|
5
|
+
export declare function Queue(props: {
|
|
6
|
+
readonly model: WatchModel;
|
|
7
|
+
}): Shown;
|
|
5
8
|
interface Timed {
|
|
6
9
|
readonly run: WatchRun;
|
|
7
10
|
readonly now: string;
|
|
@@ -38,6 +41,7 @@ export declare function Header(props: {
|
|
|
38
41
|
export interface PageProps {
|
|
39
42
|
readonly cards?: CardControls;
|
|
40
43
|
readonly model: WatchModel | null;
|
|
44
|
+
readonly observationNow?: string | undefined;
|
|
41
45
|
readonly selected: string;
|
|
42
46
|
readonly now: string;
|
|
43
47
|
readonly stale: boolean;
|
|
@@ -45,6 +49,9 @@ export interface PageProps {
|
|
|
45
49
|
readonly columns?: ColumnControls;
|
|
46
50
|
readonly start?: StartControls;
|
|
47
51
|
}
|
|
52
|
+
export declare function RefusedWorkflows(props: {
|
|
53
|
+
readonly model: WatchModel;
|
|
54
|
+
}): Shown;
|
|
48
55
|
export declare function Page(props: PageProps): Shown;
|
|
49
56
|
export declare function BoardPage(props: PageProps & {
|
|
50
57
|
readonly model: WatchModel;
|
|
@@ -1,10 +1,36 @@
|
|
|
1
1
|
import { priceText, usageText, totalsSuffix } from "./usage-render.js";
|
|
2
2
|
import { component, element } from "./watch-element.js";
|
|
3
3
|
import { clockTime, completedDetail, counted, elapsed, phaseTime, runName, runTone, waitingDetail, } from "./watch-render.js";
|
|
4
|
-
import { Board, WorkflowList, } from "./watch-board-view.js";
|
|
4
|
+
import { Board, HandoffLinks, WorkflowList, } from "./watch-board-view.js";
|
|
5
5
|
import { boardWorkflow, watchHash, watchLocation } from "./watch-navigation.js";
|
|
6
6
|
import { Decision, Events, Turn } from "./watch-turn.js";
|
|
7
7
|
import { StartRun } from "./watch-start-view.js";
|
|
8
|
+
import { record } from "../protocol.js";
|
|
9
|
+
export function Queue(props) {
|
|
10
|
+
const queue = props.model.queue;
|
|
11
|
+
if (queue === undefined)
|
|
12
|
+
return null;
|
|
13
|
+
const skipped = Array.isArray(queue["skipped"])
|
|
14
|
+
? queue["skipped"]
|
|
15
|
+
: [];
|
|
16
|
+
return [
|
|
17
|
+
element("p", {
|
|
18
|
+
class: "meta",
|
|
19
|
+
children: `Queue: ${String(queue["busy"])} of ${String(queue["lanes"])} lanes busy`,
|
|
20
|
+
}),
|
|
21
|
+
...skipped.map((value) => {
|
|
22
|
+
const ticket = record(value) ?? {};
|
|
23
|
+
const dependencies = ticket["dependencies"];
|
|
24
|
+
const needs = Array.isArray(dependencies)
|
|
25
|
+
? `; needs ${dependencies.map(String).join(", ")}`
|
|
26
|
+
: "";
|
|
27
|
+
return element("p", {
|
|
28
|
+
class: "meta",
|
|
29
|
+
children: `Skipped ticket ${String(ticket["ticketId"])}: ${String(ticket["reason"])}${needs}`,
|
|
30
|
+
});
|
|
31
|
+
}),
|
|
32
|
+
];
|
|
33
|
+
}
|
|
8
34
|
export const clove = {
|
|
9
35
|
viewBox: "0.6625858545303345 0.6630800366401672 46.674827575683594 46.673831939697266",
|
|
10
36
|
paths: [
|
|
@@ -98,7 +124,7 @@ export function PullRequest(props) {
|
|
|
98
124
|
children: `#${String(pullRequest.number)}`,
|
|
99
125
|
});
|
|
100
126
|
const scores = reviews.map((review) => element("li", {
|
|
101
|
-
children: `Round ${String(review.round)} ·
|
|
127
|
+
children: `Round ${String(review.round)} · Review ${String(review.score)}/5 · commit ${review.commit.slice(0, 7)}`,
|
|
102
128
|
}));
|
|
103
129
|
const merge = mergeCommit === null
|
|
104
130
|
? null
|
|
@@ -124,7 +150,7 @@ export function Run(props) {
|
|
|
124
150
|
const budget = run.spent === null || run.limit === null
|
|
125
151
|
? ""
|
|
126
152
|
: ` · ${String(run.spent)} of ${String(run.limit)} effect units`;
|
|
127
|
-
const none = "No
|
|
153
|
+
const none = "No agent turn for this run.";
|
|
128
154
|
const turns = run.turns.length === 0
|
|
129
155
|
? element("p", { class: "meta", children: none })
|
|
130
156
|
: run.turns.map((item, index) => [
|
|
@@ -142,6 +168,7 @@ export function Run(props) {
|
|
|
142
168
|
];
|
|
143
169
|
return [
|
|
144
170
|
component(Banner, { run, now }),
|
|
171
|
+
component(HandoffLinks, { run }),
|
|
145
172
|
element("section", {
|
|
146
173
|
class: "run-usage",
|
|
147
174
|
children: [
|
|
@@ -198,6 +225,22 @@ export function Header(props) {
|
|
|
198
225
|
],
|
|
199
226
|
});
|
|
200
227
|
}
|
|
228
|
+
export function RefusedWorkflows(props) {
|
|
229
|
+
const refusals = props.model.workflowRefusals ?? [];
|
|
230
|
+
if (refusals.length === 0)
|
|
231
|
+
return null;
|
|
232
|
+
return element("section", {
|
|
233
|
+
class: "workflow-refusals",
|
|
234
|
+
children: [
|
|
235
|
+
element("h2", { children: "Refused workflows" }),
|
|
236
|
+
element("ul", {
|
|
237
|
+
children: refusals.map((entry) => element("li", {
|
|
238
|
+
children: `${entry.scope} ${entry.label}: ${entry.codes.join(", ")}`,
|
|
239
|
+
})),
|
|
240
|
+
}),
|
|
241
|
+
],
|
|
242
|
+
});
|
|
243
|
+
}
|
|
201
244
|
export function Page(props) {
|
|
202
245
|
const { model, selected, now, stale, copying } = props;
|
|
203
246
|
const head = component(Header, { model, stale });
|
|
@@ -215,6 +258,8 @@ export function Page(props) {
|
|
|
215
258
|
return [
|
|
216
259
|
head,
|
|
217
260
|
down,
|
|
261
|
+
component(Queue, { model }),
|
|
262
|
+
component(RefusedWorkflows, { model }),
|
|
218
263
|
element("a", {
|
|
219
264
|
class: "back",
|
|
220
265
|
href: watchHash({ workflowId: back, runId: null }),
|
|
@@ -235,7 +280,9 @@ export function BoardPage(props) {
|
|
|
235
280
|
class: "board-page",
|
|
236
281
|
children: [
|
|
237
282
|
component(Header, { model, stale, start }),
|
|
283
|
+
component(Queue, { model }),
|
|
238
284
|
down,
|
|
285
|
+
component(RefusedWorkflows, { model }),
|
|
239
286
|
component(StartRun, {
|
|
240
287
|
workflows: model.workflows,
|
|
241
288
|
copying,
|
|
@@ -256,6 +303,7 @@ export function BoardPage(props) {
|
|
|
256
303
|
: component(Board, {
|
|
257
304
|
workflow,
|
|
258
305
|
now,
|
|
306
|
+
observationNow: props.observationNow,
|
|
259
307
|
controls: props.columns,
|
|
260
308
|
cardForm: model.cardForms?.find((form) => form.workflowId === workflowId),
|
|
261
309
|
cards: props.cards,
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import type { AdapterOutcome, DeliveryIntent } from "../broker/actor/delivery-intents.ts";
|
|
2
|
-
import { type TokenPrices } from "../token-prices.ts";
|
|
3
2
|
import { type RetrySettings } from "./retrying-turn.ts";
|
|
4
3
|
import { type WorkerReport } from "./operation-journal.ts";
|
|
5
4
|
interface Settings extends RetrySettings {
|
|
6
|
-
readonly tokenPrices?: TokenPrices;
|
|
7
5
|
readonly journal: string;
|
|
8
6
|
readonly document: (digest: string) => Promise<string | undefined>;
|
|
9
7
|
readonly report: (report: WorkerReport) => Promise<unknown>;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { mkdir, rm } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { analysisFollowUp, analysisFollowUpPrompt, analysisLaunchBytes, } from "../chats/analysis-prompt.js";
|
|
4
|
+
import { prepareAnalysisBatch } from "../chats/analysis-batches.js";
|
|
5
|
+
import { isAnalysisSnapshot, analysisDocumentBytes, } from "../chats/analysis-input.js";
|
|
5
6
|
import { record } from "../protocol.js";
|
|
6
|
-
import {
|
|
7
|
+
import { sumPrices } from "../worker-usage.js";
|
|
7
8
|
import { startRetriedTurn } from "./retrying-turn.js";
|
|
8
9
|
import { analysisAvailable, analysisMethod } from "./analysis-launch.js";
|
|
9
10
|
import { analysisToken } from "./analysis-token.js";
|
|
@@ -19,13 +20,60 @@ function own(intent) {
|
|
|
19
20
|
function failed(reason) {
|
|
20
21
|
return { kind: "failed", reason };
|
|
21
22
|
}
|
|
22
|
-
function
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
function firstBatch(snapshot) {
|
|
24
|
+
const batch = prepareAnalysisBatch(snapshot, {
|
|
25
|
+
nextRecordIndex: 0,
|
|
26
|
+
completedBatchCount: 0,
|
|
27
|
+
previousResult: null,
|
|
28
|
+
});
|
|
29
|
+
if (batch.kind === "refused")
|
|
30
|
+
throw new Error(batch.code);
|
|
31
|
+
if (batch.nextRecordIndex !== batch.totalRecords)
|
|
32
|
+
throw new Error("analysis-too-large");
|
|
33
|
+
return batch;
|
|
34
|
+
}
|
|
35
|
+
function promptOf(text, target) {
|
|
36
|
+
if (text !== undefined && Buffer.byteLength(text) > analysisDocumentBytes)
|
|
37
|
+
throw new Error("analysis-too-large");
|
|
38
|
+
const payload = record(JSON.parse(text ?? "null"));
|
|
39
|
+
if (payload === undefined)
|
|
40
|
+
throw new Error("analysis-input-refused");
|
|
41
|
+
const snapshot = payload["snapshot"];
|
|
42
|
+
if (!isAnalysisSnapshot(snapshot) || snapshot.importId !== target)
|
|
43
|
+
throw new Error("analysis-input-refused");
|
|
44
|
+
const followUp = "followUp" in payload ? analysisFollowUp(payload["followUp"]) : undefined;
|
|
45
|
+
const data = batchInput(snapshot, payload);
|
|
46
|
+
const prompt = turnPrompt(data, followUp);
|
|
47
|
+
if (analysisLaunchBytes(prompt) > analysisDocumentBytes)
|
|
48
|
+
throw new Error("analysis-too-large");
|
|
49
|
+
return prompt;
|
|
50
|
+
}
|
|
51
|
+
function turnPrompt(data, followUp) {
|
|
52
|
+
const context = data.context === undefined ? {} : { context: data.context };
|
|
53
|
+
if (followUp === undefined)
|
|
54
|
+
return data.prompt;
|
|
55
|
+
return analysisFollowUpPrompt(data.snapshot, { ...followUp, ...context });
|
|
56
|
+
}
|
|
57
|
+
function batchInput(snapshot, payload) {
|
|
58
|
+
if (!("context" in payload)) {
|
|
59
|
+
const batch = firstBatch(snapshot);
|
|
60
|
+
return { snapshot: batch.snapshot, prompt: batch.prompt };
|
|
28
61
|
}
|
|
62
|
+
const context = record(payload["context"]);
|
|
63
|
+
if (context === undefined || Object.keys(context).length !== 3)
|
|
64
|
+
throw new Error("analysis-input-refused");
|
|
65
|
+
const position = [context["batchIndex"], context["firstRecordIndex"]];
|
|
66
|
+
if (!position.every((value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0) ||
|
|
67
|
+
Number(position[0]) > 3)
|
|
68
|
+
throw new Error("analysis-input-refused");
|
|
69
|
+
if (context["previousResult"] !== null &&
|
|
70
|
+
record(context["previousResult"]) === undefined)
|
|
71
|
+
throw new Error("analysis-input-refused");
|
|
72
|
+
return {
|
|
73
|
+
snapshot,
|
|
74
|
+
context,
|
|
75
|
+
prompt: JSON.stringify({ evidence: snapshot, context }),
|
|
76
|
+
};
|
|
29
77
|
}
|
|
30
78
|
async function cleaned(folder) {
|
|
31
79
|
await Promise.all(["configuration", "working"].map((name) => rm(join(folder, name), { recursive: true, force: true })));
|
|
@@ -33,7 +81,7 @@ async function cleaned(folder) {
|
|
|
33
81
|
async function privateRecord(folder, entry) {
|
|
34
82
|
await writeRecord(folder, { ...entry, permissions: "private" });
|
|
35
83
|
}
|
|
36
|
-
function outcome(end
|
|
84
|
+
function outcome(end) {
|
|
37
85
|
const endedAt = new Date().toISOString();
|
|
38
86
|
if (end.stopped)
|
|
39
87
|
return { outcome: "stopped", endedAt };
|
|
@@ -44,12 +92,10 @@ function outcome(end, prices) {
|
|
|
44
92
|
costUsd: result.costUsd,
|
|
45
93
|
usage: result.usage,
|
|
46
94
|
model: result.model,
|
|
95
|
+
...(result.attempts === undefined ? {} : { attempts: result.attempts }),
|
|
47
96
|
sessionId: result.sessionId,
|
|
48
97
|
turns: result.turns,
|
|
49
|
-
estimatedCostUsd:
|
|
50
|
-
worker: "claude",
|
|
51
|
-
price: priceForModel(prices, result.model),
|
|
52
|
-
}),
|
|
98
|
+
estimatedCostUsd: sumPrices((result.attempts ?? []).map((attempt) => attempt.estimatedCostUsd)),
|
|
53
99
|
};
|
|
54
100
|
if (end.exitCode !== 0 || result.failed)
|
|
55
101
|
return {
|
|
@@ -121,7 +167,7 @@ async function begun(parts, opening) {
|
|
|
121
167
|
}, { ...parts.settings, metadata: started });
|
|
122
168
|
const done = turn.ended
|
|
123
169
|
.then(async (end) => {
|
|
124
|
-
const result = outcome(end
|
|
170
|
+
const result = outcome(end);
|
|
125
171
|
await privateRecord(folder, { name: "result.json", value: result });
|
|
126
172
|
await cleaned(folder);
|
|
127
173
|
await parts.settings.report(reportOf({ intent, worker: "claude", commandId: `analysis-turn:${key}` }, result));
|
|
@@ -142,9 +188,15 @@ async function deliver(parts, call) {
|
|
|
142
188
|
return known;
|
|
143
189
|
const { key, folder } = located(parts.settings.journal, intent.operationId);
|
|
144
190
|
const text = await parts.settings.document(intent.payload);
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
191
|
+
let prompt;
|
|
192
|
+
try {
|
|
193
|
+
prompt = promptOf(text, intent.target);
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
return failed(error instanceof Error && error.message === "analysis-too-large"
|
|
197
|
+
? "analysis-too-large"
|
|
198
|
+
: "analysis-input-refused");
|
|
199
|
+
}
|
|
148
200
|
await mkdir(join(folder, "configuration"), { recursive: true, mode: 0o700 });
|
|
149
201
|
if (!(await analysisAvailable(folder))) {
|
|
150
202
|
await cleaned(folder);
|
|
@@ -173,7 +225,7 @@ async function deliver(parts, call) {
|
|
|
173
225
|
key,
|
|
174
226
|
folder,
|
|
175
227
|
directory,
|
|
176
|
-
prompt
|
|
228
|
+
prompt,
|
|
177
229
|
token: credential.token,
|
|
178
230
|
});
|
|
179
231
|
return { receipt: key, worker: "claude" };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type AnalysisSnapshot } from "../chats/analysis-input.ts";
|
|
2
|
+
import { type AnalysisCapture } from "./chats-capture.ts";
|
|
3
|
+
interface AnalysisBatchBindingInput {
|
|
4
|
+
readonly runId: string;
|
|
5
|
+
readonly importId: string;
|
|
6
|
+
readonly snapshot: AnalysisSnapshot | undefined;
|
|
7
|
+
readonly batch?: unknown;
|
|
8
|
+
}
|
|
9
|
+
export declare function boundAnalysisBatch(directory: string, input: AnalysisBatchBindingInput): Promise<{
|
|
10
|
+
capture: AnalysisCapture;
|
|
11
|
+
snapshot: AnalysisSnapshot;
|
|
12
|
+
batch: {
|
|
13
|
+
batchIndex: number;
|
|
14
|
+
nextRecordIndex: number;
|
|
15
|
+
};
|
|
16
|
+
previous: import("../chats/analysis-checkpoint.ts").AnalysisCheckpoint;
|
|
17
|
+
}>;
|
|
18
|
+
export declare function previousCheckpoint(folder: string, input: {
|
|
19
|
+
readonly capture: AnalysisCapture;
|
|
20
|
+
readonly batchIndex: number;
|
|
21
|
+
readonly snapshot: AnalysisSnapshot;
|
|
22
|
+
}): Promise<import("../chats/analysis-checkpoint.ts").AnalysisCheckpoint>;
|
|
23
|
+
export {};
|