cloving 1.0.1 → 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 +251 -20
- 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 +33 -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 +3 -0
- package/dist/src/authority/reconciliation.js +21 -5
- package/dist/src/authority/transitions.d.ts +1 -1
- package/dist/src/authority/transitions.js +5 -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/authority-session.d.ts +2 -0
- package/dist/src/broker/actor/authority-session.js +3 -4
- 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 +42 -0
- package/dist/src/chats/analysis-batches.js +97 -0
- package/dist/src/chats/analysis-checkpoint.d.ts +29 -0
- package/dist/src/chats/analysis-checkpoint.js +31 -0
- package/dist/src/chats/analysis-contract.d.ts +80 -0
- package/dist/src/chats/analysis-contract.js +16 -0
- package/dist/src/chats/analysis-data.d.ts +3 -0
- package/dist/src/chats/analysis-data.js +85 -0
- package/dist/src/chats/analysis-input.d.ts +18 -0
- package/dist/src/chats/analysis-input.js +97 -0
- package/dist/src/chats/analysis-links.d.ts +2 -0
- package/dist/src/chats/analysis-links.js +25 -0
- 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 +18 -0
- package/dist/src/chats/analysis-prompt.js +42 -0
- package/dist/src/chats/analysis-proposal.d.ts +4 -0
- package/dist/src/chats/analysis-proposal.js +41 -0
- package/dist/src/chats/analysis-provenance.d.ts +4 -0
- package/dist/src/chats/analysis-provenance.js +99 -0
- package/dist/src/chats/analysis-shape.d.ts +4 -0
- package/dist/src/chats/analysis-shape.js +235 -0
- package/dist/src/chats/analysis.d.ts +3 -0
- package/dist/src/chats/analysis.js +42 -0
- package/dist/src/chats/corpus-input.d.ts +5 -0
- package/dist/src/chats/corpus-input.js +288 -0
- package/dist/src/chats/destination.js +3 -1
- package/dist/src/chats/import.d.ts +8 -6
- package/dist/src/chats/import.js +195 -23
- package/dist/src/chats/input-file.d.ts +3 -0
- package/dist/src/chats/input-file.js +32 -0
- package/dist/src/chats/normalize.d.ts +11 -2
- package/dist/src/chats/normalize.js +18 -2
- package/dist/src/chats/previous-import.d.ts +5 -0
- package/dist/src/chats/previous-import.js +34 -0
- package/dist/src/chats/reader.d.ts +7 -1
- package/dist/src/chats/reader.js +46 -15
- package/dist/src/chats/redact-import.d.ts +14 -0
- package/dist/src/chats/redact-import.js +141 -0
- package/dist/src/chats/redaction.d.ts +41 -0
- package/dist/src/chats/redaction.js +161 -0
- package/dist/src/chats/reference-mapping.d.ts +16 -0
- package/dist/src/chats/reference-mapping.js +153 -0
- package/dist/src/chats/revision-input.d.ts +3 -0
- package/dist/src/chats/revision-input.js +180 -0
- package/dist/src/chats/revision.d.ts +48 -0
- package/dist/src/chats/revision.js +94 -0
- package/dist/src/chats/selection.d.ts +25 -0
- package/dist/src/chats/selection.js +109 -0
- package/dist/src/chats/source.d.ts +23 -0
- package/dist/src/chats/source.js +135 -0
- package/dist/src/chats/structure.d.ts +57 -0
- package/dist/src/chats/structure.js +216 -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/arguments.d.ts +8 -0
- package/dist/src/cli/arguments.js +94 -13
- package/dist/src/cli/client.d.ts +1 -0
- package/dist/src/cli/client.js +38 -1
- package/dist/src/cli/commands.d.ts +3 -0
- package/dist/src/cli/commands.js +29 -11
- package/dist/src/cli/main.d.ts +2 -1
- package/dist/src/cli/main.js +61 -14
- package/dist/src/cli/render.d.ts +3 -0
- package/dist/src/cli/render.js +122 -7
- package/dist/src/cli/usage-render.d.ts +3 -0
- package/dist/src/cli/usage-render.js +28 -0
- package/dist/src/cli/usage.d.ts +3 -2
- package/dist/src/cli/usage.js +42 -7
- package/dist/src/cli/watch-actions.d.ts +10 -0
- package/dist/src/cli/watch-actions.js +58 -0
- package/dist/src/cli/watch-board-view.d.ts +44 -1
- package/dist/src/cli/watch-board-view.js +137 -18
- package/dist/src/cli/watch-board.d.ts +7 -1
- package/dist/src/cli/watch-board.js +48 -11
- package/dist/src/cli/watch-card-client.d.ts +1 -0
- package/dist/src/cli/watch-card-client.js +44 -0
- package/dist/src/cli/watch-card-forms.d.ts +2 -0
- package/dist/src/cli/watch-card-forms.js +33 -0
- package/dist/src/cli/watch-card-reply.d.ts +5 -0
- package/dist/src/cli/watch-card-reply.js +34 -0
- package/dist/src/cli/watch-card-view.d.ts +40 -0
- package/dist/src/cli/watch-card-view.js +86 -0
- package/dist/src/cli/watch-client.d.ts +1 -0
- package/dist/src/cli/watch-client.js +122 -0
- package/dist/src/cli/watch-model.d.ts +10 -4
- package/dist/src/cli/watch-model.js +61 -67
- package/dist/src/cli/watch-page.d.ts +1 -1
- package/dist/src/cli/watch-page.js +89 -86
- package/dist/src/cli/watch-phases.js +3 -3
- package/dist/src/cli/watch-pr-board.d.ts +3 -0
- package/dist/src/cli/watch-pr-board.js +26 -0
- package/dist/src/cli/watch-pr-command.d.ts +18 -0
- package/dist/src/cli/watch-pr-command.js +74 -0
- package/dist/src/cli/watch-pr-identity.d.ts +32 -0
- package/dist/src/cli/watch-pr-identity.js +87 -0
- package/dist/src/cli/watch-pr-observer.d.ts +20 -0
- package/dist/src/cli/watch-pr-observer.js +150 -0
- package/dist/src/cli/watch-pr-settings.d.ts +8 -0
- package/dist/src/cli/watch-pr-settings.js +47 -0
- 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 +44 -18
- package/dist/src/cli/watch-render.d.ts +29 -2
- package/dist/src/cli/watch-render.js +11 -3
- package/dist/src/cli/watch-run-input.d.ts +14 -0
- package/dist/src/cli/watch-run-input.js +49 -0
- package/dist/src/cli/watch-server.d.ts +3 -0
- package/dist/src/cli/watch-server.js +77 -8
- package/dist/src/cli/watch-start-view.d.ts +18 -0
- package/dist/src/cli/watch-start-view.js +77 -0
- package/dist/src/cli/watch-turn.d.ts +1 -0
- package/dist/src/cli/watch-turn.js +8 -3
- package/dist/src/cli/watch-usage.d.ts +6 -0
- package/dist/src/cli/watch-usage.js +65 -0
- package/dist/src/cli/watch-view.d.ts +22 -0
- package/dist/src/cli/watch-view.js +111 -19
- package/dist/src/cli.js +48 -6
- package/dist/src/daemon/analysis-launch.d.ts +5 -0
- package/dist/src/daemon/analysis-launch.js +81 -0
- package/dist/src/daemon/analysis-token.d.ts +6 -0
- package/dist/src/daemon/analysis-token.js +88 -0
- package/dist/src/daemon/analysis-worker.d.ts +20 -0
- package/dist/src/daemon/analysis-worker.js +271 -0
- 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 +42 -0
- package/dist/src/daemon/chats-files.js +252 -0
- 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 +13 -0
- package/dist/src/daemon/chats-worker.js +201 -0
- package/dist/src/daemon/claude-turn.d.ts +11 -0
- package/dist/src/daemon/claude-turn.js +96 -15
- package/dist/src/daemon/claude-worker.d.ts +2 -1
- package/dist/src/daemon/claude-worker.js +92 -45
- package/dist/src/daemon/codex-stream.js +16 -0
- package/dist/src/daemon/daemon.d.ts +8 -1
- package/dist/src/daemon/daemon.js +51 -14
- 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 +84 -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.d.ts +3 -0
- package/dist/src/daemon/github-ticket-status.js +294 -0
- 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 +2 -0
- package/dist/src/daemon/issue-queue.js +186 -43
- 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/operation-journal.d.ts +1 -0
- package/dist/src/daemon/operation-journal.js +4 -2
- package/dist/src/daemon/retrying-turn.d.ts +12 -0
- package/dist/src/daemon/retrying-turn.js +231 -0
- 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 +3 -0
- package/dist/src/host/world-reconciliation.js +9 -0
- package/dist/src/host/world-runs.js +14 -1
- 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 +54 -30
- 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.d.ts +3 -0
- package/dist/src/service/worker-totals.js +52 -0
- 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.d.ts +8 -0
- package/dist/src/ticket-status.js +48 -0
- package/dist/src/token-prices.d.ts +21 -0
- package/dist/src/token-prices.js +108 -0
- package/dist/src/worker-usage.d.ts +31 -0
- package/dist/src/worker-usage.js +44 -0
- package/dist/src/workflow-admission.d.ts +1 -0
- package/dist/src/workflow-candidate.d.ts +29 -0
- package/dist/src/workflow-candidate.js +60 -0
- package/dist/src/workflow-contracts.d.ts +4 -0
- package/dist/src/workflow-contracts.js +32 -5
- package/dist/src/workflow-declaration.d.ts +12 -1
- package/dist/src/workflow-declaration.js +71 -13
- 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 +3 -1
- package/dist/src/workflows.js +2 -0
- package/dist/tools/admit-workflow.d.ts +13 -0
- package/dist/tools/admit-workflow.js +94 -0
- package/dist/tools/self-host-processes.js +7 -2
- package/dist/tools/self-host-project.d.ts +17 -0
- package/dist/tools/self-host-project.js +177 -0
- package/dist/tools/self-host-workflows.d.ts +1 -1
- package/dist/tools/self-host-workflows.js +2 -2
- package/dist/tools/self-host.js +30 -84
- package/dist/tools/self-update-host.d.ts +7 -0
- package/dist/tools/self-update-host.js +48 -1
- package/dist/tools/self-update.d.ts +1 -0
- package/dist/tools/self-update.js +85 -13
- 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 +15 -0
- package/dist/workflows/analyze-chats.declaration.json +22 -0
- package/dist/workflows/analyze-chats.js +250 -0
- package/dist/workflows/develop-prd.js +71 -3
- package/dist/workflows/develop-ticket.d.ts +1 -7
- package/dist/workflows/develop-ticket.js +47 -141
- package/dist/workflows/issue-labels.d.ts +3 -1
- package/dist/workflows/issue-labels.js +34 -0
- package/dist/workflows/ticket-prompts.d.ts +35 -0
- package/dist/workflows/ticket-prompts.js +143 -0
- package/package.json +25 -5
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
+
import { ticketStatus } from "../ticket-status.js";
|
|
3
|
+
import { sumPrices } from "../worker-usage.js";
|
|
4
|
+
import { analysisWorker } from "./analysis-worker.js";
|
|
5
|
+
import { analysisMethod } from "./analysis-launch.js";
|
|
2
6
|
import { profileCommand, } from "../turn-profile.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
7
|
+
import {} from "./claude-turn.js";
|
|
8
|
+
import { startRetriedTurn } from "./retrying-turn.js";
|
|
9
|
+
import { interrupted, located, operationKey, readRecord as read, replied, reportOf, writeRecord as written, } from "./operation-journal.js";
|
|
5
10
|
import { changes, treeFailure, workTree } from "./work-tree.js";
|
|
6
11
|
export const claudeLimits = {
|
|
7
12
|
summaryCharacters: 16_000,
|
|
@@ -9,9 +14,6 @@ export const claudeLimits = {
|
|
|
9
14
|
stopMilliseconds: 2_000,
|
|
10
15
|
};
|
|
11
16
|
const worker = "claude";
|
|
12
|
-
function located(settings, operationId) {
|
|
13
|
-
return locatedIn(settings.journal, operationId);
|
|
14
|
-
}
|
|
15
17
|
function alive(processId) {
|
|
16
18
|
if (typeof processId !== "number")
|
|
17
19
|
return false;
|
|
@@ -23,14 +25,11 @@ function alive(processId) {
|
|
|
23
25
|
return Reflect.get(Object(error), "code") === "EPERM";
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
|
-
function replied(key, recorded) {
|
|
27
|
-
return repliedWith({ receipt: key, worker }, recorded);
|
|
28
|
-
}
|
|
29
28
|
async function reconciled(parts, intent) {
|
|
30
|
-
const { key, folder } = located(parts.settings, intent.operationId);
|
|
29
|
+
const { key, folder } = located(parts.settings.journal, intent.operationId);
|
|
31
30
|
const result = await read(folder, "result.json");
|
|
32
31
|
if (result !== undefined)
|
|
33
|
-
return replied(key, result);
|
|
32
|
+
return replied({ receipt: key, worker }, result);
|
|
34
33
|
if (parts.active.has(key))
|
|
35
34
|
return { kind: "accepted", receipt: key, worker };
|
|
36
35
|
const started = await read(folder, "started.json");
|
|
@@ -40,64 +39,73 @@ async function reconciled(parts, intent) {
|
|
|
40
39
|
return { kind: "unknown", evidence: `claude-turn:${key}` };
|
|
41
40
|
const ending = interrupted("claude-turn-interrupted");
|
|
42
41
|
await written(folder, { name: "result.json", value: ending });
|
|
43
|
-
return replied(key, ending);
|
|
42
|
+
return replied({ receipt: key, worker }, ending);
|
|
44
43
|
}
|
|
45
44
|
async function resultText(tree, result) {
|
|
46
45
|
const fields = {
|
|
46
|
+
ticketStatus: ticketStatus(result.text),
|
|
47
47
|
summary: result.text.slice(0, claudeLimits.summaryCharacters),
|
|
48
48
|
...(await changes(tree)),
|
|
49
49
|
worktree: tree.path,
|
|
50
50
|
costUsd: result.costUsd,
|
|
51
|
+
usage: result.usage,
|
|
52
|
+
model: result.model,
|
|
53
|
+
...(result.attempts === undefined ? {} : { attempts: result.attempts }),
|
|
54
|
+
estimatedCostUsd: sumPrices((result.attempts ?? []).map((attempt) => attempt.estimatedCostUsd)),
|
|
51
55
|
sessionId: result.sessionId,
|
|
52
56
|
turns: result.turns,
|
|
53
57
|
};
|
|
54
58
|
const text = JSON.stringify(fields);
|
|
55
59
|
const excess = Buffer.byteLength(text) - claudeLimits.resultBytes;
|
|
56
60
|
if (excess <= 0)
|
|
57
|
-
return text;
|
|
61
|
+
return { text };
|
|
58
62
|
const kept = Math.max(0, fields.summary.length - excess);
|
|
59
|
-
|
|
63
|
+
const shortened = JSON.stringify({
|
|
64
|
+
...fields,
|
|
65
|
+
summary: fields.summary.slice(0, kept),
|
|
66
|
+
});
|
|
67
|
+
if (Buffer.byteLength(shortened) <= claudeLimits.resultBytes)
|
|
68
|
+
return { text: shortened };
|
|
69
|
+
const metadata = JSON.stringify({
|
|
70
|
+
...fields,
|
|
71
|
+
ticketStatus: undefined,
|
|
72
|
+
summary: "",
|
|
73
|
+
});
|
|
74
|
+
return {
|
|
75
|
+
reason: "claude-result-too-large",
|
|
76
|
+
...(Buffer.byteLength(metadata) <= claudeLimits.resultBytes
|
|
77
|
+
? { text: metadata }
|
|
78
|
+
: {}),
|
|
79
|
+
};
|
|
60
80
|
}
|
|
61
81
|
async function outcome(running, end) {
|
|
62
82
|
const endedAt = new Date().toISOString();
|
|
63
83
|
const { result } = end;
|
|
64
|
-
const
|
|
65
|
-
|
|
84
|
+
const report = result === undefined ? {} : await resultText(running.tree, result);
|
|
85
|
+
const { text, reason } = report;
|
|
86
|
+
if (reason === undefined &&
|
|
87
|
+
text !== undefined &&
|
|
88
|
+
end.exitCode === 0 &&
|
|
89
|
+
result?.failed === false)
|
|
66
90
|
return { outcome: "completed", result: text, endedAt };
|
|
67
91
|
if (running.stopping.requested)
|
|
68
92
|
return { outcome: "stopped", endedAt };
|
|
69
93
|
return {
|
|
70
94
|
outcome: "failed",
|
|
71
|
-
reason: "claude-turn-failed",
|
|
95
|
+
reason: reason ?? "claude-turn-failed",
|
|
72
96
|
...(text === undefined ? {} : { result: text }),
|
|
73
97
|
endedAt,
|
|
74
98
|
};
|
|
75
99
|
}
|
|
76
|
-
function reported(started, recorded) {
|
|
77
|
-
const { intent, key } = started;
|
|
78
|
-
return reportOf({ intent, commandId: `claude-turn:${key}`, worker }, recorded);
|
|
79
|
-
}
|
|
80
100
|
async function concluded(parts, running) {
|
|
101
|
+
const { intent, key } = running;
|
|
81
102
|
const recorded = await outcome(running, await running.turn.ended);
|
|
82
103
|
await written(running.folder, { name: "result.json", value: recorded });
|
|
83
|
-
await parts.settings.report(
|
|
104
|
+
await parts.settings.report(reportOf({ intent, commandId: `claude-turn:${key}`, worker }, recorded));
|
|
84
105
|
}
|
|
85
106
|
async function begun(parts, start) {
|
|
86
107
|
const { intent, key, folder, tree, prompt } = start;
|
|
87
|
-
const
|
|
88
|
-
name: "started.json",
|
|
89
|
-
value: {
|
|
90
|
-
operationId: intent.operationId,
|
|
91
|
-
target: intent.target,
|
|
92
|
-
branch: tree.branch,
|
|
93
|
-
worktree: tree.path,
|
|
94
|
-
startCommit: tree.startCommit,
|
|
95
|
-
processId,
|
|
96
|
-
startedAt: new Date().toISOString(),
|
|
97
|
-
},
|
|
98
|
-
});
|
|
99
|
-
await record(null);
|
|
100
|
-
const turn = startTurn({
|
|
108
|
+
const turn = startRetriedTurn({
|
|
101
109
|
worker: parts.settings.worker ?? "claude",
|
|
102
110
|
command: profileCommand(parts.settings.command, start.profile),
|
|
103
111
|
environment: start.profile.env ?? {},
|
|
@@ -105,16 +113,26 @@ async function begun(parts, start) {
|
|
|
105
113
|
directory: tree.path,
|
|
106
114
|
folder,
|
|
107
115
|
prompt,
|
|
116
|
+
}, {
|
|
117
|
+
...parts.settings,
|
|
118
|
+
metadata: {
|
|
119
|
+
operationId: intent.operationId,
|
|
120
|
+
target: intent.target,
|
|
121
|
+
branch: tree.branch,
|
|
122
|
+
worktree: tree.path,
|
|
123
|
+
startCommit: tree.startCommit,
|
|
124
|
+
},
|
|
108
125
|
});
|
|
109
126
|
const stopping = { requested: false };
|
|
110
127
|
parts.active.set(key, {
|
|
111
128
|
turn,
|
|
112
129
|
stopping,
|
|
113
|
-
concluded:
|
|
130
|
+
concluded: turn
|
|
131
|
+
.then((running) => concluded(parts, { ...start, turn: running, stopping }))
|
|
114
132
|
.catch(() => undefined)
|
|
115
133
|
.finally(() => parts.active.delete(key)),
|
|
116
134
|
});
|
|
117
|
-
await
|
|
135
|
+
await turn;
|
|
118
136
|
}
|
|
119
137
|
async function firstTurn(settings, opening) {
|
|
120
138
|
const { tree, intent } = opening;
|
|
@@ -171,8 +189,11 @@ async function selectedProfile(settings, intent) {
|
|
|
171
189
|
async function delivered(parts, call) {
|
|
172
190
|
const { intent, signal } = call;
|
|
173
191
|
const { settings } = parts;
|
|
192
|
+
const aborted = () => signal.aborted;
|
|
174
193
|
if (!turnIntent(intent))
|
|
175
194
|
return failure("unsupported-effect");
|
|
195
|
+
if (aborted())
|
|
196
|
+
return failure("claude-start-aborted");
|
|
176
197
|
const known = await reconciled(parts, intent);
|
|
177
198
|
if (known.kind !== "absent")
|
|
178
199
|
return known;
|
|
@@ -188,22 +209,25 @@ async function delivered(parts, call) {
|
|
|
188
209
|
target: intent.target,
|
|
189
210
|
signal,
|
|
190
211
|
}).catch(treeFailure);
|
|
191
|
-
if (
|
|
212
|
+
if (aborted())
|
|
192
213
|
return failure("claude-start-aborted");
|
|
193
214
|
if (typeof tree === "string")
|
|
194
215
|
return failure(tree);
|
|
195
|
-
const place = located(settings, intent.operationId);
|
|
216
|
+
const place = located(settings.journal, intent.operationId);
|
|
196
217
|
const first = await firstTurn(settings, { tree, intent });
|
|
218
|
+
if (aborted())
|
|
219
|
+
return failure("claude-start-aborted");
|
|
197
220
|
await begun(parts, { ...place, intent, tree: first, prompt, profile });
|
|
198
221
|
return { receipt: place.key, worker };
|
|
199
222
|
}
|
|
200
223
|
async function halted(parts, active) {
|
|
201
224
|
active.stopping.requested = true;
|
|
202
|
-
active.turn.
|
|
225
|
+
const turn = await active.turn.catch(() => undefined);
|
|
226
|
+
turn?.stop(parts.settings.stopMilliseconds ?? claudeLimits.stopMilliseconds);
|
|
203
227
|
await active.concluded;
|
|
204
228
|
}
|
|
205
229
|
async function stopped(parts, intent) {
|
|
206
|
-
const { key } = located(parts.settings, intent.operationId);
|
|
230
|
+
const { key } = located(parts.settings.journal, intent.operationId);
|
|
207
231
|
const active = parts.active.get(key);
|
|
208
232
|
if (active !== undefined)
|
|
209
233
|
await halted(parts, active);
|
|
@@ -212,12 +236,35 @@ async function stopped(parts, intent) {
|
|
|
212
236
|
export function claudeWorker(settings) {
|
|
213
237
|
if (settings.command.length === 0)
|
|
214
238
|
throw new Error("invalid-claude-command");
|
|
215
|
-
const parts = {
|
|
239
|
+
const parts = {
|
|
240
|
+
settings,
|
|
241
|
+
active: new Map(),
|
|
242
|
+
stopping: new AbortController(),
|
|
243
|
+
};
|
|
244
|
+
const analysis = analysisWorker(settings);
|
|
245
|
+
const guarded = async (intent, run) => {
|
|
246
|
+
if (!turnIntent(intent) ||
|
|
247
|
+
Object.hasOwn(settings.profiles ?? {}, "analyze-chats") ||
|
|
248
|
+
(await runWorkflow(settings, intent.runId)) !== "analyze-chats")
|
|
249
|
+
return failure("analysis-worker-unavailable");
|
|
250
|
+
return run();
|
|
251
|
+
};
|
|
216
252
|
return {
|
|
217
|
-
deliver: (intent, signal) =>
|
|
218
|
-
|
|
219
|
-
|
|
253
|
+
deliver: (intent, signal) => intent.method === analysisMethod
|
|
254
|
+
? guarded(intent, () => analysis.deliver(intent, signal))
|
|
255
|
+
: delivered(parts, {
|
|
256
|
+
intent,
|
|
257
|
+
signal: AbortSignal.any([signal, parts.stopping.signal]),
|
|
258
|
+
}),
|
|
259
|
+
reconcile: (intent, signal) => intent.method === analysisMethod
|
|
260
|
+
? guarded(intent, () => analysis.reconcile(intent, signal))
|
|
261
|
+
: reconciled(parts, intent),
|
|
262
|
+
stop: (intent, signal) => intent.method === analysisMethod
|
|
263
|
+
? guarded(intent, () => analysis.stop(intent, signal))
|
|
264
|
+
: stopped(parts, intent),
|
|
220
265
|
close: async () => {
|
|
266
|
+
parts.stopping.abort();
|
|
267
|
+
await analysis.close();
|
|
221
268
|
await Promise.all([...parts.active.values()].map((active) => halted(parts, active)));
|
|
222
269
|
},
|
|
223
270
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { sumUsage, usageOf } from "../worker-usage.js";
|
|
1
2
|
function record(value) {
|
|
2
3
|
return typeof value === "object" && value !== null ? { ...value } : {};
|
|
3
4
|
}
|
|
@@ -43,9 +44,20 @@ function completed(item) {
|
|
|
43
44
|
}
|
|
44
45
|
function updated(event, state) {
|
|
45
46
|
const type = event["type"];
|
|
47
|
+
if (typeof type === "string" &&
|
|
48
|
+
["thread.started", "turn.started", "turn.completed"].includes(type))
|
|
49
|
+
state.model = text(event["model"]) || state.model;
|
|
46
50
|
if (type === "thread.started")
|
|
47
51
|
state.sessionId = text(event["thread_id"]) || null;
|
|
48
52
|
if (type === "turn.completed") {
|
|
53
|
+
const usage = record(event["usage"]);
|
|
54
|
+
const current = usageOf({
|
|
55
|
+
input_tokens: usage["input_tokens"],
|
|
56
|
+
cache_read_input_tokens: usage["cached_input_tokens"],
|
|
57
|
+
output_tokens: usage["output_tokens"],
|
|
58
|
+
});
|
|
59
|
+
state.usage =
|
|
60
|
+
state.turns === 0 ? current : sumUsage([state.usage, current]);
|
|
49
61
|
state.turns += 1;
|
|
50
62
|
state.error = null;
|
|
51
63
|
}
|
|
@@ -82,8 +94,10 @@ function translated(event, state) {
|
|
|
82
94
|
}
|
|
83
95
|
export function codexStream() {
|
|
84
96
|
const state = {
|
|
97
|
+
model: null,
|
|
85
98
|
sessionId: null,
|
|
86
99
|
turns: 0,
|
|
100
|
+
usage: usageOf(null),
|
|
87
101
|
failure: null,
|
|
88
102
|
error: null,
|
|
89
103
|
message: "",
|
|
@@ -105,6 +119,8 @@ export function codexStream() {
|
|
|
105
119
|
state.error ||
|
|
106
120
|
`codex ended with the code ${String(exitCode)}`,
|
|
107
121
|
total_cost_usd: null,
|
|
122
|
+
...(state.model === null ? {} : { model: state.model }),
|
|
123
|
+
usage: state.usage,
|
|
108
124
|
session_id: state.sessionId,
|
|
109
125
|
num_turns: state.turns,
|
|
110
126
|
});
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { type WorkflowFunction } from "../host/start-delivery.ts";
|
|
2
2
|
import { type WorkflowHandler } from "../host/world-host.ts";
|
|
3
3
|
import type { TurnProfiles } from "../turn-profile.ts";
|
|
4
|
+
import type { TokenPrices } from "../token-prices.ts";
|
|
4
5
|
import type { DeclaredWorkflow } from "../workflow-declaration.ts";
|
|
6
|
+
import type { WorkflowRefusal } from "../workflow-refusals.ts";
|
|
5
7
|
import type { Worker } from "./claude-turn.ts";
|
|
6
8
|
export interface DaemonSettings {
|
|
9
|
+
readonly fallbackModels?: readonly string[];
|
|
10
|
+
readonly tokenPrices?: TokenPrices;
|
|
7
11
|
readonly worker?: Worker;
|
|
8
12
|
readonly profiles?: TurnProfiles;
|
|
9
13
|
readonly directory: string;
|
|
@@ -11,6 +15,7 @@ export interface DaemonSettings {
|
|
|
11
15
|
readonly repository: string;
|
|
12
16
|
readonly manifests: Readonly<Record<string, string | undefined>>;
|
|
13
17
|
readonly declarations?: readonly DeclaredWorkflow[];
|
|
18
|
+
readonly workflowRefusals?: readonly WorkflowRefusal[];
|
|
14
19
|
readonly workflows: Readonly<Record<string, WorkflowFunction | undefined>>;
|
|
15
20
|
readonly handler: WorkflowHandler;
|
|
16
21
|
readonly command: readonly string[];
|
|
@@ -19,6 +24,8 @@ export interface DaemonSettings {
|
|
|
19
24
|
readonly notifyCommand?: readonly string[];
|
|
20
25
|
readonly notifyMilliseconds?: number;
|
|
21
26
|
readonly queueMilliseconds?: number;
|
|
27
|
+
readonly queueLanes?: number;
|
|
28
|
+
readonly resetQueue?: boolean;
|
|
22
29
|
readonly githubCommand?: readonly string[];
|
|
23
30
|
readonly checkCommand?: readonly string[];
|
|
24
31
|
readonly privateTexts?: readonly string[];
|
|
@@ -43,4 +50,4 @@ export declare const bridgeTiming: {
|
|
|
43
50
|
pollMilliseconds: number;
|
|
44
51
|
retryMilliseconds: number;
|
|
45
52
|
};
|
|
46
|
-
export declare function startDaemon(
|
|
53
|
+
export declare function startDaemon(givenSettings: DaemonSettings): Promise<DaemonOpening>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdir } from "node:fs/promises";
|
|
1
|
+
import { mkdir, realpath } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { startDelivery, } from "../host/start-delivery.js";
|
|
4
4
|
import { registerStepBridge, sdkStepCall, stepBridge, } from "../host/step-bridge-host.js";
|
|
@@ -6,9 +6,12 @@ import { startHost } from "../host/world-host.js";
|
|
|
6
6
|
import { worldLoop } from "../host/world-reconciliation.js";
|
|
7
7
|
import { cancelled, workflowOutcome, taggedRun, taggedRuns, } from "../host/world-runs.js";
|
|
8
8
|
import { startService, } from "../service/service.js";
|
|
9
|
+
import { workflowPin } from "../broker/workflow-pin.js";
|
|
9
10
|
import { claudeWorker } from "./claude-worker.js";
|
|
10
11
|
import { deliveryRouter } from "./delivery-router.js";
|
|
12
|
+
import { handoffWorker } from "./handoff-worker.js";
|
|
11
13
|
import { githubWorker } from "./github-worker.js";
|
|
14
|
+
import { chatsWorker } from "./chats-worker.js";
|
|
12
15
|
import { worldDirectory } from "./host-environment.js";
|
|
13
16
|
import { issueQueue } from "./issue-queue.js";
|
|
14
17
|
import { notifyRuns } from "./notify.js";
|
|
@@ -71,11 +74,17 @@ function githubOf(settings, given) {
|
|
|
71
74
|
}
|
|
72
75
|
function adapters(settings, options) {
|
|
73
76
|
const { directory, repository, command } = settings;
|
|
74
|
-
const { given, table } = options;
|
|
75
|
-
const
|
|
77
|
+
const { given, table, registrations } = options;
|
|
78
|
+
const functions = Object.fromEntries(table.map((row) => [row.workflowId, settings.workflows[row.functionName]]));
|
|
79
|
+
const workflows = Object.fromEntries(registrations.map((registration) => [
|
|
80
|
+
workflowPin(registration.manifest),
|
|
81
|
+
functions[registration.workflowId],
|
|
82
|
+
]));
|
|
76
83
|
const document = async (digest) => (await given).document(digest);
|
|
77
84
|
const report = async (effect) => (await given).reportEffect(effect);
|
|
78
85
|
const worker = claudeWorker({
|
|
86
|
+
fallbackModels: settings.fallbackModels ?? [],
|
|
87
|
+
tokenPrices: settings.tokenPrices ?? {},
|
|
79
88
|
worker: settings.worker ?? "claude",
|
|
80
89
|
profiles: settings.profiles ?? {},
|
|
81
90
|
workflowId: async (runId) => (await given).workflowId(runId),
|
|
@@ -87,23 +96,46 @@ function adapters(settings, options) {
|
|
|
87
96
|
journal: join(directory, "journal"),
|
|
88
97
|
});
|
|
89
98
|
const github = githubOf(settings, given);
|
|
99
|
+
const chats = chatsWorker({
|
|
100
|
+
runtimeDirectory: settings.runtimeDirectory,
|
|
101
|
+
document,
|
|
102
|
+
workflowId: async (runId) => (await given).workflowId(runId),
|
|
103
|
+
});
|
|
90
104
|
const runs = startDelivery({
|
|
91
105
|
document,
|
|
92
106
|
runs: taggedRuns,
|
|
93
107
|
cancel: cancelled,
|
|
94
108
|
input: async (runId) => (await given).input(runId),
|
|
95
|
-
workflow:
|
|
109
|
+
workflow: ({ workflow }) => Promise.resolve(workflows[workflow]),
|
|
96
110
|
});
|
|
97
|
-
|
|
111
|
+
const handoff = handoffOf(settings, given);
|
|
112
|
+
return { worker, github, runs, chats, handoff };
|
|
98
113
|
}
|
|
99
|
-
|
|
100
|
-
|
|
114
|
+
function handoffOf(settings, given) {
|
|
115
|
+
return handoffWorker({
|
|
116
|
+
runtimeDirectory: settings.runtimeDirectory,
|
|
117
|
+
journal: join(settings.directory, "handoffs"),
|
|
118
|
+
document: async (digest) => (await given).document(digest),
|
|
119
|
+
runStatus: async (runId) => (await (await given).state()).runs[runId]?.status,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
async function daemonRegistrations(settings) {
|
|
101
123
|
const table = ticketRegistrationTable({
|
|
102
124
|
repository: settings.repository,
|
|
103
125
|
command: settings.ticketCommand,
|
|
104
126
|
nextCommand: settings.nextCommand,
|
|
127
|
+
githubCommand: settings.githubCommand,
|
|
105
128
|
}, settings.declarations);
|
|
106
129
|
const admitted = await ticketRegistrations(settings.manifests, { table });
|
|
130
|
+
return { table, admitted };
|
|
131
|
+
}
|
|
132
|
+
export async function startDaemon(givenSettings) {
|
|
133
|
+
const settings = {
|
|
134
|
+
...givenSettings,
|
|
135
|
+
repository: await realpath(givenSettings.repository),
|
|
136
|
+
};
|
|
137
|
+
const { directory } = settings;
|
|
138
|
+
const { table, admitted } = await daemonRegistrations(settings);
|
|
107
139
|
if (admitted.kind === "rejected")
|
|
108
140
|
return {
|
|
109
141
|
kind: "refused",
|
|
@@ -111,25 +143,27 @@ export async function startDaemon(settings) {
|
|
|
111
143
|
detail: admitted.detail,
|
|
112
144
|
};
|
|
113
145
|
const given = Promise.withResolvers();
|
|
114
|
-
const { worker, github, runs } = adapters(settings, {
|
|
146
|
+
const { worker, github, runs, chats, handoff } = adapters(settings, {
|
|
115
147
|
given: given.promise,
|
|
116
148
|
table,
|
|
149
|
+
registrations: admitted.registrations,
|
|
117
150
|
});
|
|
118
151
|
await mkdir(join(directory, "state"), { recursive: true });
|
|
119
152
|
await mkdir(settings.runtimeDirectory, { recursive: true, mode: 0o700 });
|
|
120
153
|
const opening = await startService({
|
|
121
154
|
stateDirectory: join(directory, "state"),
|
|
122
155
|
runtimeDirectory: settings.runtimeDirectory,
|
|
156
|
+
workflowRefusals: settings.workflowRefusals ?? [],
|
|
123
157
|
workflows: admitted.registrations.map((registration) => ({
|
|
124
158
|
...registration,
|
|
125
159
|
...(settings.queueMilliseconds !== undefined &&
|
|
126
160
|
registration.workflowId === "develop-issue"
|
|
127
|
-
? { admission:
|
|
161
|
+
? { admission: settings.queueLanes ?? 1 }
|
|
128
162
|
: {}),
|
|
129
163
|
})),
|
|
130
164
|
delivery: deliveryRouter({
|
|
131
165
|
runs,
|
|
132
|
-
effects: { claude: worker, github },
|
|
166
|
+
effects: { claude: worker, github, chats, handoff },
|
|
133
167
|
}),
|
|
134
168
|
effects: { leaseMilliseconds: turnLeaseMilliseconds },
|
|
135
169
|
host: (ports) => {
|
|
@@ -138,7 +172,7 @@ export async function startDaemon(settings) {
|
|
|
138
172
|
},
|
|
139
173
|
});
|
|
140
174
|
if (opening.kind === "refused") {
|
|
141
|
-
await Promise.all([worker.close(), github.close()]);
|
|
175
|
+
await Promise.all([worker.close(), github.close(), chats.close()]);
|
|
142
176
|
return opening;
|
|
143
177
|
}
|
|
144
178
|
return {
|
|
@@ -147,11 +181,12 @@ export async function startDaemon(settings) {
|
|
|
147
181
|
service: opening.service,
|
|
148
182
|
worker,
|
|
149
183
|
github,
|
|
184
|
+
chats,
|
|
150
185
|
}),
|
|
151
186
|
};
|
|
152
187
|
}
|
|
153
188
|
async function runningDaemon(settings, resources) {
|
|
154
|
-
const { service, worker, github } = resources;
|
|
189
|
+
const { service, worker, github, chats } = resources;
|
|
155
190
|
await github.scan();
|
|
156
191
|
const notifier = settings.notifyCommand === undefined
|
|
157
192
|
? undefined
|
|
@@ -163,7 +198,7 @@ async function runningDaemon(settings, resources) {
|
|
|
163
198
|
? {}
|
|
164
199
|
: { intervalMilliseconds: settings.notifyMilliseconds }),
|
|
165
200
|
}).catch(async (error) => {
|
|
166
|
-
await Promise.all([worker.close(), github.close()]);
|
|
201
|
+
await Promise.all([worker.close(), github.close(), chats.close()]);
|
|
167
202
|
await service.close();
|
|
168
203
|
throw error;
|
|
169
204
|
});
|
|
@@ -173,13 +208,15 @@ async function runningDaemon(settings, resources) {
|
|
|
173
208
|
directory: settings.directory,
|
|
174
209
|
runtimeDirectory: settings.runtimeDirectory,
|
|
175
210
|
intervalMilliseconds: settings.queueMilliseconds,
|
|
211
|
+
lanes: settings.queueLanes ?? 1,
|
|
212
|
+
resetQueue: settings.resetQueue ?? false,
|
|
176
213
|
});
|
|
177
214
|
return {
|
|
178
215
|
socket: service.socket,
|
|
179
216
|
close: async () => {
|
|
180
217
|
await notifier?.stop();
|
|
181
218
|
await queue?.stop();
|
|
182
|
-
await Promise.all([worker.close(), github.close()]);
|
|
219
|
+
await Promise.all([worker.close(), github.close(), chats.close()]);
|
|
183
220
|
await service.close();
|
|
184
221
|
},
|
|
185
222
|
};
|
|
@@ -25,6 +25,12 @@ export function deliveryRouter(routes) {
|
|
|
25
25
|
return runs.reconcile(intent);
|
|
26
26
|
return workerOf(routes, intent)?.reconcile(intent, signal) ?? refusal();
|
|
27
27
|
},
|
|
28
|
+
retry: (intent, signal) => {
|
|
29
|
+
if (!protectedEffect(intent))
|
|
30
|
+
return refusal();
|
|
31
|
+
return (workerOf(routes, intent)?.retry?.(intent, signal) ??
|
|
32
|
+
Promise.resolve({ kind: "unknown" }));
|
|
33
|
+
},
|
|
28
34
|
stop: (intent, signal) => {
|
|
29
35
|
if (!protectedEffect(intent))
|
|
30
36
|
return runs.stop(intent);
|
|
@@ -24,6 +24,10 @@ export interface Finding {
|
|
|
24
24
|
readonly line: number | null;
|
|
25
25
|
readonly body: string;
|
|
26
26
|
}
|
|
27
|
+
export declare function githubText(text: string, settings: {
|
|
28
|
+
readonly environment?: NodeJS.ProcessEnv;
|
|
29
|
+
readonly privateTexts?: readonly string[];
|
|
30
|
+
}): string;
|
|
27
31
|
export declare function calls(settings: CallSettings, signal: AbortSignal): Calls;
|
|
28
32
|
export declare function scoreOf(comments: unknown, commit: string): Scored | undefined;
|
|
29
33
|
export declare function findingsOf(comments: unknown, commit: string): readonly Finding[];
|
|
@@ -22,17 +22,26 @@ function privateEnvironment(environment) {
|
|
|
22
22
|
function failureDetail(error, place) {
|
|
23
23
|
const stderr = field(error, "stderr");
|
|
24
24
|
const text = typeof stderr === "string" ? stderr : "";
|
|
25
|
-
|
|
25
|
+
return {
|
|
26
|
+
detail: githubText(text, place).slice(-2_000),
|
|
27
|
+
status: Number(/\(HTTP (\d{3})\)/.exec(text)?.[1]),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export function githubText(text, settings) {
|
|
31
|
+
const environment = { ...process.env, ...settings.environment };
|
|
32
|
+
const secrets = Object.entries(environment)
|
|
26
33
|
.filter(([name]) => /TOKEN|SECRET|PASSWORD|KEY/i.test(name))
|
|
27
34
|
.map(([, value]) => value);
|
|
28
|
-
const
|
|
35
|
+
const privateTexts = [
|
|
36
|
+
...(settings.privateTexts ?? []),
|
|
37
|
+
...privateEnvironment(environment),
|
|
38
|
+
];
|
|
39
|
+
const hidden = [...secrets, ...privateTexts]
|
|
29
40
|
.filter((value) => typeof value === "string" && value !== "")
|
|
30
41
|
.sort((left, right) => right.length - left.length);
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
status: Number(/\(HTTP (\d{3})\)/.exec(text)?.[1]),
|
|
35
|
-
};
|
|
42
|
+
return hidden.reduce((redacted, value) => redacted.replaceAll(privateTexts.includes(value)
|
|
43
|
+
? new RegExp(value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "gi")
|
|
44
|
+
: value, "[hidden]"), text);
|
|
36
45
|
}
|
|
37
46
|
async function output(command, place) {
|
|
38
47
|
try {
|