@veewo/claw 0.2.25 → 0.2.26
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/dist/cli.js +34 -132
- package/dist/cli.js.map +1 -1
- package/dist/report-collector-registry.d.ts +20 -0
- package/dist/report-collector-registry.js +42 -0
- package/dist/report-collector-registry.js.map +1 -0
- package/package.json +3 -3
- package/dist/codex-transcript.d.ts +0 -7
- package/dist/codex-transcript.js +0 -313
- package/dist/codex-transcript.js.map +0 -1
- package/dist/dsh-capture.d.ts +0 -22
- package/dist/dsh-capture.js +0 -34
- package/dist/dsh-capture.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -6,12 +6,11 @@ import { createInterface } from "node:readline";
|
|
|
6
6
|
import { pathToFileURL } from "node:url";
|
|
7
7
|
import { createHash } from "node:crypto";
|
|
8
8
|
import { spawn, spawnSync } from "node:child_process";
|
|
9
|
-
import { buildDirectWorkflowGuidance,
|
|
9
|
+
import { buildDirectWorkflowGuidance, buildKnowledgeAtomicDispatch, buildKnowledgeDelegateDispatch, buildKnowledgeAssignmentTemplate, buildDirectKnowledgeAssignments, buildKnowledgeWriterAssignments, DEFAULT_MAX_TASKS_TO_KEEP, checkProjectProtocol, ClawError, assertRootPlanCreateAllowedForPlan, buildPlanWorkflowGuidance, buildMemoryIndex, buildSessionStartDefaultPrompt, buildSessionStartRecoveredPrompt, editPlan, ensureProjectProtocol, enforceTaskRetention, findKnowledgeFinalizationJobPath, findTaskDirectory, runDailyMaintenance, ingestTruth, initProject, getTemplateTaskDoneChoices, resolvePlanTemplateFile, resolvePlanEffectiveConfig, resolveThreadGoalPlan, resolveKnowledgeWriterForHost, resolveProjectContext, resolveWorkflowProjectContext, resolveSessionWorkflowContext, deleteSessionWorkflow, sweepExpiredSessionWorkflows, resolveSessionBoundPlan, resolveContext, resolveSeedPlanTemplate, searchMemoryAsync, warmProjectMemoryEmbedding, showPlan, createSubplan, createPlanRef, switchTask, tryCaptureKnowledgeStop, claimKnowledgeFinalizationJob, doneKnowledgeFinalizationJob, readKnowledgeFinalizationJob, waitForKnowledgeFinalizationJobReady, listKnowledgeFinalizationJobs, listRetryableKnowledgeFinalizationJobs, normalizeTruthMarkdownEncoding, governKnowledgeMarkdownPaths, resolveKnowledgeDocUpdateSnapshot, recordKnowledgeFinalizationResult, unbindSession, writePlan, } from "@veewo/claw-core";
|
|
10
10
|
import { buildCodexDriverEnvelope } from "./codex-driver.js";
|
|
11
11
|
import { buildCodexHostActions } from "./codex-host-actions.js";
|
|
12
12
|
import { checkCodexRuntime, resolveCodexSdkEntryPath } from "./codex-runtime.js";
|
|
13
|
-
import {
|
|
14
|
-
import { readDshKnowledgeCapture } from "./dsh-capture.js";
|
|
13
|
+
import { collectReport, registerReportCollector } from "./report-collector-registry.js";
|
|
15
14
|
import { consumeBufferedHookInput } from "./knowledge-hook-preflight.js";
|
|
16
15
|
import { isSubagentPolicyHost, resolveInvocationHost, withoutInvocationHost } from "./invocation-host.js";
|
|
17
16
|
import { runOpencodeKnowledgeWriter } from "./opencode-runner.js";
|
|
@@ -564,6 +563,9 @@ async function main() {
|
|
|
564
563
|
case "knowledge":
|
|
565
564
|
await runKnowledge(args);
|
|
566
565
|
return;
|
|
566
|
+
case "internal-report-collector-register":
|
|
567
|
+
runInternalReportCollectorRegister(args);
|
|
568
|
+
return;
|
|
567
569
|
case "direct":
|
|
568
570
|
runDirect(args, effectiveHost);
|
|
569
571
|
return;
|
|
@@ -1013,34 +1015,18 @@ function serializeSessionError(error) {
|
|
|
1013
1015
|
}
|
|
1014
1016
|
return { code: "SESSION_COMMAND_FAILED", message: error instanceof Error ? error.message : String(error) };
|
|
1015
1017
|
}
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
catch {
|
|
1026
|
-
throw new ClawError("PROJECT_CONFIG_INVALID", "Cindy knowledge claim report input is invalid JSON.");
|
|
1027
|
-
}
|
|
1028
|
-
const sessionId = typeof parsed.session_id === "string" ? parsed.session_id.trim() : "";
|
|
1029
|
-
const turnId = typeof parsed.turn_id === "string" ? parsed.turn_id.trim() : "";
|
|
1030
|
-
const taskConclusions = Array.isArray(parsed.task_conclusions)
|
|
1031
|
-
? parsed.task_conclusions.flatMap((entry) => {
|
|
1032
|
-
if (!entry || typeof entry !== "object" || Array.isArray(entry))
|
|
1033
|
-
return [];
|
|
1034
|
-
const item = entry;
|
|
1035
|
-
const itemTurnId = typeof item.turnId === "string" ? item.turnId.trim() : "";
|
|
1036
|
-
const message = typeof item.message === "string" ? item.message.trim() : "";
|
|
1037
|
-
return itemTurnId && message ? [{ turnId: itemTurnId, message }] : [];
|
|
1038
|
-
})
|
|
1039
|
-
: [];
|
|
1040
|
-
if (!sessionId || !turnId) {
|
|
1041
|
-
throw new ClawError("PROJECT_CONFIG_INVALID", "Cindy knowledge claim report input requires session_id and turn_id.");
|
|
1018
|
+
/** Adapter-only registration. The descriptor contains no host history schema. */
|
|
1019
|
+
function runInternalReportCollectorRegister(args) {
|
|
1020
|
+
const projectRoot = path.resolve(readRequiredFlag(args, "--project-root"));
|
|
1021
|
+
const host = readRequiredFlag(args, "--collector-host");
|
|
1022
|
+
const executable = readRequiredFlag(args, "--executable");
|
|
1023
|
+
const collectorArgs = readRepeatedFlag(args, "--arg");
|
|
1024
|
+
assertNoRemainingArgs(args, "internal-report-collector-register");
|
|
1025
|
+
if (host !== "codex" && host !== "dsh" && host !== "cindy") {
|
|
1026
|
+
throw new ClawError("PROJECT_CONFIG_INVALID", "report collector host must be codex, dsh, or cindy.");
|
|
1042
1027
|
}
|
|
1043
|
-
|
|
1028
|
+
registerReportCollector(projectRoot, { host, executable, args: collectorArgs });
|
|
1029
|
+
printJson({ ok: true, command: "internal-report-collector-register", host });
|
|
1044
1030
|
}
|
|
1045
1031
|
async function runKnowledge(args) {
|
|
1046
1032
|
const subcommand = args.shift();
|
|
@@ -1125,8 +1111,6 @@ async function runKnowledge(args) {
|
|
|
1125
1111
|
const explicitJobPath = readOptionalFlag(args, "--job");
|
|
1126
1112
|
const projectRoot = readOptionalFlag(args, "--project-root");
|
|
1127
1113
|
const finalizeId = readOptionalFlag(args, "--finalize-id");
|
|
1128
|
-
const captureCindyReport = readBooleanFlag(args, "--cindy-report-stdin");
|
|
1129
|
-
const cindyCapture = captureCindyReport ? readCindyKnowledgeClaimCaptureInput() : undefined;
|
|
1130
1114
|
if (explicitJobPath && (projectRoot || finalizeId)) {
|
|
1131
1115
|
throw new ClawError("PROJECT_CONFIG_INVALID", "knowledge claim accepts either --job or --project-root with --finalize-id.");
|
|
1132
1116
|
}
|
|
@@ -1139,9 +1123,6 @@ async function runKnowledge(args) {
|
|
|
1139
1123
|
throw new Error(`Knowledge finalization ${finalizeId} is unavailable.`);
|
|
1140
1124
|
}
|
|
1141
1125
|
const queued = readKnowledgeFinalizationJob(jobPath);
|
|
1142
|
-
if (queued.host === "codex" && queued.writer?.executionPolicy === "subagent" && queued.reportCapture?.mode === "claim" && queued.reportCapture.status !== "captured") {
|
|
1143
|
-
await new Promise((resolve) => setTimeout(resolve, 10_000));
|
|
1144
|
-
}
|
|
1145
1126
|
const job = claimKnowledgeFinalizationJob(jobPath, {
|
|
1146
1127
|
prepare: (queued) => {
|
|
1147
1128
|
if (queued.writer?.executionPolicy !== "subagent"
|
|
@@ -1149,103 +1130,22 @@ async function runKnowledge(args) {
|
|
|
1149
1130
|
|| queued.reportCapture.status === "captured") {
|
|
1150
1131
|
return;
|
|
1151
1132
|
}
|
|
1152
|
-
if (queued.host
|
|
1153
|
-
if (!cindyCapture) {
|
|
1154
|
-
throw new Error(`Cindy report capture is unavailable for knowledge session ${queued.sessionId}.`);
|
|
1155
|
-
}
|
|
1156
|
-
if (cindyCapture.sessionId !== queued.sessionId) {
|
|
1157
|
-
throw new Error("Cindy report capture does not match the originating knowledge session.");
|
|
1158
|
-
}
|
|
1159
|
-
const capturedAt = new Date().toISOString();
|
|
1160
|
-
appendKnowledgeTaskConclusions(queued.reportPath, queued.sessionId, cindyCapture.taskConclusions, capturedAt);
|
|
1161
|
-
return {
|
|
1162
|
-
reportCapture: {
|
|
1163
|
-
...queued.reportCapture,
|
|
1164
|
-
status: "captured",
|
|
1165
|
-
capturedAt,
|
|
1166
|
-
messageCount: cindyCapture.taskConclusions.length,
|
|
1167
|
-
},
|
|
1168
|
-
};
|
|
1169
|
-
}
|
|
1170
|
-
if (queued.host === "dsh") {
|
|
1171
|
-
// The dsh-adapter plugin reads the DSH session log at the terminal
|
|
1172
|
-
// plan mutation and writes the extracted final message + task.done
|
|
1173
|
-
// conclusions to a capture file (mirroring the Codex transcript
|
|
1174
|
-
// hand-off). Only conclusions from THIS plan's window are used:
|
|
1175
|
-
// the job's reportCapture.startedAt (registry activeStartedAt) is
|
|
1176
|
-
// the authoritative window start, and each conclusion carries its
|
|
1177
|
-
// event time.
|
|
1178
|
-
const capture = readDshKnowledgeCapture(queued.sessionId);
|
|
1179
|
-
if (!capture || capture.sessionId !== queued.sessionId) {
|
|
1180
|
-
throw new Error(`DSH report capture is unavailable for knowledge session ${queued.sessionId}.`);
|
|
1181
|
-
}
|
|
1182
|
-
const startedAtMs = queued.reportCapture?.startedAt
|
|
1183
|
-
? Date.parse(queued.reportCapture.startedAt)
|
|
1184
|
-
: Number.NaN;
|
|
1185
|
-
const conclusions = (capture.taskConclusions ?? []).filter((conclusion) => {
|
|
1186
|
-
const time = conclusion.time;
|
|
1187
|
-
if (Number.isFinite(startedAtMs) && typeof time === "number") {
|
|
1188
|
-
return time >= startedAtMs;
|
|
1189
|
-
}
|
|
1190
|
-
return true;
|
|
1191
|
-
});
|
|
1192
|
-
const capturedAt = new Date().toISOString();
|
|
1193
|
-
appendKnowledgeTaskConclusions(queued.reportPath, queued.sessionId, conclusions, capturedAt);
|
|
1194
|
-
return {
|
|
1195
|
-
reportCapture: {
|
|
1196
|
-
...queued.reportCapture,
|
|
1197
|
-
status: "captured",
|
|
1198
|
-
capturedAt,
|
|
1199
|
-
messageCount: conclusions.length,
|
|
1200
|
-
},
|
|
1201
|
-
};
|
|
1202
|
-
}
|
|
1203
|
-
if (queued.host == null) {
|
|
1204
|
-
// A job created by a pre-dsh-host build has host null. The
|
|
1205
|
-
// dsh-adapter plugin is the only writer of the dsh-capture file,
|
|
1206
|
-
// so its presence proves this is a DSH-originated session; route it
|
|
1207
|
-
// through the dsh branch instead of failing as "host unknown".
|
|
1208
|
-
const capture = readDshKnowledgeCapture(queued.sessionId);
|
|
1209
|
-
if (capture && capture.sessionId === queued.sessionId) {
|
|
1210
|
-
const startedAtMs = queued.reportCapture?.startedAt
|
|
1211
|
-
? Date.parse(queued.reportCapture.startedAt)
|
|
1212
|
-
: Number.NaN;
|
|
1213
|
-
const conclusions = (capture.taskConclusions ?? []).filter((conclusion) => {
|
|
1214
|
-
const time = conclusion.time;
|
|
1215
|
-
if (Number.isFinite(startedAtMs) && typeof time === "number") {
|
|
1216
|
-
return time >= startedAtMs;
|
|
1217
|
-
}
|
|
1218
|
-
return true;
|
|
1219
|
-
});
|
|
1220
|
-
const capturedAt = new Date().toISOString();
|
|
1221
|
-
appendKnowledgeTaskConclusions(queued.reportPath, queued.sessionId, conclusions, capturedAt);
|
|
1222
|
-
return {
|
|
1223
|
-
reportCapture: {
|
|
1224
|
-
...queued.reportCapture,
|
|
1225
|
-
status: "captured",
|
|
1226
|
-
capturedAt,
|
|
1227
|
-
messageCount: conclusions.length,
|
|
1228
|
-
},
|
|
1229
|
-
};
|
|
1230
|
-
}
|
|
1231
|
-
}
|
|
1232
|
-
if (queued.host !== "codex") {
|
|
1133
|
+
if (queued.host !== "codex" && queued.host !== "dsh" && queued.host !== "cindy") {
|
|
1233
1134
|
throw new Error(`Claim-time report capture is unavailable for host ${queued.host ?? "unknown"}.`);
|
|
1234
1135
|
}
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1136
|
+
collectReport({
|
|
1137
|
+
host: queued.host,
|
|
1138
|
+
sessionId: queued.sessionId,
|
|
1139
|
+
projectRoot: queued.projectRoot,
|
|
1140
|
+
planPath: queued.planPath,
|
|
1141
|
+
canonicalReportPath: queued.reportPath,
|
|
1142
|
+
startedAt: queued.reportCapture.startedAt,
|
|
1143
|
+
});
|
|
1242
1144
|
return {
|
|
1243
1145
|
reportCapture: {
|
|
1244
1146
|
...queued.reportCapture,
|
|
1245
1147
|
status: "captured",
|
|
1246
|
-
capturedAt,
|
|
1247
|
-
transcriptPath,
|
|
1248
|
-
messageCount: conclusions.length,
|
|
1148
|
+
capturedAt: new Date().toISOString(),
|
|
1249
1149
|
},
|
|
1250
1150
|
};
|
|
1251
1151
|
},
|
|
@@ -2237,16 +2137,14 @@ async function runStopHook(effectiveHost) {
|
|
|
2237
2137
|
const hookCwd = resolveHookCwd(payload);
|
|
2238
2138
|
const sessionId = resolveOwnerSessionKey(payload);
|
|
2239
2139
|
const turnId = readHookString(payload, "turn_id");
|
|
2240
|
-
const transcriptPath = readHookString(payload, "transcript_path");
|
|
2241
2140
|
const payloadMessage = readHookString(payload, "message");
|
|
2242
2141
|
if (!hookCwd || !sessionId || !turnId || !containsClawDir(hookCwd)) {
|
|
2243
2142
|
return;
|
|
2244
2143
|
}
|
|
2245
2144
|
try {
|
|
2246
2145
|
const project = resolveProjectContext(hookCwd);
|
|
2247
|
-
//
|
|
2248
|
-
|
|
2249
|
-
const message = payloadMessage ?? (transcriptPath ? extractLatestFinalAssistantMessage(transcriptPath, turnId) : null);
|
|
2146
|
+
// Host adapters own history parsing and pass their current final inline.
|
|
2147
|
+
const message = payloadMessage;
|
|
2250
2148
|
if (!message) {
|
|
2251
2149
|
return;
|
|
2252
2150
|
}
|
|
@@ -2256,7 +2154,7 @@ async function runStopHook(effectiveHost) {
|
|
|
2256
2154
|
turnId,
|
|
2257
2155
|
message,
|
|
2258
2156
|
host: effectiveHost,
|
|
2259
|
-
taskConclusions:
|
|
2157
|
+
taskConclusions: [],
|
|
2260
2158
|
});
|
|
2261
2159
|
// Current named hosts own their runner in their adapters. Keep the CLI
|
|
2262
2160
|
// launcher only for jobs written by pre-adapter releases with no host.
|
|
@@ -3177,7 +3075,11 @@ function compactPlanCommandResult(command, result, effectiveHost, completionRefr
|
|
|
3177
3075
|
const hostActions = hostActionsResult ? buildCodexHostActions(result, { forceProjectionSync, actionIdPrefix: command === "plan.sync" ? `plan.sync:${createHash("sha256").update(result.planPath).digest("hex").slice(0, 16)}` : undefined }) : [];
|
|
3178
3076
|
const nextsteps = [
|
|
3179
3077
|
...result.workflowGuidance.nextsteps,
|
|
3180
|
-
|
|
3078
|
+
// Manual-dispatch instruction for hosts WITHOUT automatic writer
|
|
3079
|
+
// dispatch (codex/cindy/opencode). DSH's adapter auto-dispatches the
|
|
3080
|
+
// writer subagent inside claw_run, so the model must NOT re-dispatch;
|
|
3081
|
+
// injecting this line there would ask it to duplicate the dispatch.
|
|
3082
|
+
...(knowledgeDispatch && effectiveHost !== "dsh"
|
|
3181
3083
|
? ["A knowledgeDispatch is present: dispatch its unchanged prompt through the current Host's designated knowledge-finalizer now, then immediately end the Lead turn; do not wait for or poll that worker."]
|
|
3182
3084
|
: []),
|
|
3183
3085
|
];
|