grix-connector 3.33.2 → 3.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter/acp/acp-adapter.js +6 -6
- package/dist/adapter/agy/agy-adapter.js +9 -9
- package/dist/adapter/agy/model-list.js +2 -2
- package/dist/adapter/agy/quota.js +5 -5
- package/dist/adapter/claude/claude-adapter.js +21 -21
- package/dist/adapter/claude/claude-bridge-server.js +1 -0
- package/dist/adapter/claude/claude-tools.js +1 -0
- package/dist/adapter/claude/claude-worker-client.js +1 -0
- package/dist/adapter/claude/mcp-http-launcher.js +2 -0
- package/dist/adapter/claude/model-list.js +1 -1
- package/dist/adapter/claude/result-timeout.js +1 -0
- package/dist/adapter/codewhale/codewhale-adapter.js +2 -2
- package/dist/adapter/codewhale/model-list.js +2 -2
- package/dist/adapter/codex/codex-bridge.js +9 -9
- package/dist/adapter/cursor/cursor-adapter.js +7 -7
- package/dist/adapter/cursor/fetch-models.js +2 -2
- package/dist/adapter/cursor/resolve-command.js +1 -1
- package/dist/adapter/deepseek/deepseek-adapter.js +6 -0
- package/dist/adapter/deepseek/index.js +1 -0
- package/dist/adapter/deepseek-harness/jsonrpc-adapter.js +2 -2
- package/dist/adapter/opencode/opencode-adapter.js +3 -3
- package/dist/adapter/openhuman/openhuman-adapter.js +3 -3
- package/dist/adapter/qwen/index.js +1 -0
- package/dist/adapter/qwen/qwen-adapter.js +4 -0
- package/dist/aibot/client.js +1 -0
- package/dist/aibot/index.js +1 -0
- package/dist/aibot/types.js +0 -0
- package/dist/assets/dsh-bridge/{grix-dsh-bridge-3.33.2.tgz → grix-dsh-bridge-3.34.0.tgz} +0 -0
- package/dist/assets/dsh-bridge/manifest.json +5 -5
- package/dist/audit/adapters/agy/agy-audit-adapter.js +1 -0
- package/dist/audit/adapters/openclaw/openclaw-audit-adapter.js +1 -1
- package/dist/audit/adapters/pi/pi-transcript-source.js +1 -1
- package/dist/audit/core/audit-state.js +1 -1
- package/dist/audit/core/transcript-fingerprint.js +1 -0
- package/dist/audit/producer/ipc-audit-producer.js +1 -1
- package/dist/audit/worker/audit-recorder-worker-entry.js +1 -1
- package/dist/bridge/adapter-pool.js +1 -1
- package/dist/bridge/bridge.js +9 -9
- package/dist/bridge/cli-install-offer.js +1 -0
- package/dist/bridge/deferred-events.js +1 -1
- package/dist/bridge/lifecycle-barrier.js +1 -0
- package/dist/bridge/pending-event-coordinator.js +1 -0
- package/dist/bridge/respawn-manager.js +1 -1
- package/dist/core/access/allowlist-gate.js +1 -0
- package/dist/core/access/allowlist-store.js +1 -0
- package/dist/core/access/index.js +1 -0
- package/dist/core/aibot/client.js +2 -2
- package/dist/core/file-ops/handler.js +1 -0
- package/dist/core/file-ops/list-files.js +1 -0
- package/dist/core/file-ops/types.js +0 -0
- package/dist/core/files/file-serve.js +1 -1
- package/dist/core/installer/installer.js +6 -6
- package/dist/core/installer/npm-registry.js +3 -3
- package/dist/core/installer/prereq-installer.js +1 -1
- package/dist/core/observability/sentry.js +1 -1
- package/dist/core/persistence/pending-event-store.js +1 -0
- package/dist/core/protocol/interaction-parser.js +1 -1
- package/dist/core/proxy/hermes-profile-relay.js +1 -1
- package/dist/core/proxy/hermes-profile-relay.py +34 -15
- package/dist/core/proxy/relay-state-sync.js +1 -1
- package/dist/core/runtime/spawn.js +2 -3
- package/dist/core/upgrade/npm-upgrader.js +2 -2
- package/dist/core/upgrade/upgrade-checker.js +1 -1
- package/dist/core/util/cli-probe.js +2 -2
- package/dist/core/util/git-project-root.js +1 -1
- package/dist/default-skills/grix-agent-dispatch/SKILL.md +19 -9
- package/dist/default-skills/grix-egg/SKILL.md +2 -2
- package/dist/default-skills/message-send/SKILL.md +1 -1
- package/dist/default-skills/message-unsend/SKILL.md +1 -1
- package/dist/grix.js +0 -0
- package/dist/log.js +3 -0
- package/dist/main.js +31 -0
- package/dist/manager-share-config.js +1 -1
- package/dist/manager.js +2 -2
- package/dist/mcp/stream-http/config.js +1 -0
- package/dist/mcp/stream-http/connection-binding.js +1 -0
- package/dist/mcp/stream-http/event-tool-executor.js +1 -0
- package/dist/mcp/stream-http/gateway.js +1 -0
- package/dist/mcp/stream-http/index.js +1 -0
- package/dist/mcp/stream-http/security.js +1 -0
- package/dist/mcp/stream-http/session-manager.js +1 -0
- package/dist/mcp/stream-http/tool-executor.js +1 -0
- package/dist/mcp/stream-http/tool-registry.js +1 -0
- package/dist/mcp/stream-http/tool-schemas.js +1 -0
- package/dist/service/process-control.js +1 -1
- package/dist/session/index.js +1 -0
- package/dist/session/manager.js +1 -0
- package/dist/transport/index.js +1 -0
- package/dist/transport/json-rpc.js +3 -0
- package/openclaw-plugin/audit-recorder-worker.js +531 -76
- package/openclaw-plugin/index.js +89 -14
- package/package.json +1 -1
|
@@ -1291,7 +1291,7 @@ function groupMessages(job, evidence, anomalies) {
|
|
|
1291
1291
|
});
|
|
1292
1292
|
continue;
|
|
1293
1293
|
}
|
|
1294
|
-
const
|
|
1294
|
+
const timestamp5 = asTimestamp(line.record.timestamp, job.startedAt);
|
|
1295
1295
|
let group = groups.get(messageId);
|
|
1296
1296
|
if (!group) {
|
|
1297
1297
|
group = {
|
|
@@ -1301,14 +1301,14 @@ function groupMessages(job, evidence, anomalies) {
|
|
|
1301
1301
|
sourcePath: line.sourcePath,
|
|
1302
1302
|
isSubagent: line.isSubagent,
|
|
1303
1303
|
promptId: targetPromptId,
|
|
1304
|
-
startedAt:
|
|
1305
|
-
endedAt:
|
|
1304
|
+
startedAt: timestamp5,
|
|
1305
|
+
endedAt: timestamp5,
|
|
1306
1306
|
samples: [],
|
|
1307
1307
|
blocks: []
|
|
1308
1308
|
};
|
|
1309
1309
|
groups.set(messageId, group);
|
|
1310
1310
|
} else {
|
|
1311
|
-
group.endedAt =
|
|
1311
|
+
group.endedAt = timestamp5;
|
|
1312
1312
|
if (typeof line.record.requestId === "string") {
|
|
1313
1313
|
group.requestId = line.record.requestId;
|
|
1314
1314
|
}
|
|
@@ -2299,9 +2299,9 @@ function stableHash(value) {
|
|
|
2299
2299
|
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
2300
2300
|
}
|
|
2301
2301
|
function observedAt(value) {
|
|
2302
|
-
const
|
|
2303
|
-
if (!
|
|
2304
|
-
return
|
|
2302
|
+
const timestamp5 = stringValue2(value);
|
|
2303
|
+
if (!timestamp5 || Number.isNaN(Date.parse(timestamp5))) return void 0;
|
|
2304
|
+
return timestamp5;
|
|
2305
2305
|
}
|
|
2306
2306
|
function captureOptions2(job) {
|
|
2307
2307
|
return job.options?.enabled === true ? job.options.capture : DEFAULT_CAPTURE2;
|
|
@@ -2816,7 +2816,7 @@ function toSpan(job, candidate, modelId) {
|
|
|
2816
2816
|
if (candidate.snapshotKey) {
|
|
2817
2817
|
nativeIds2.usageSnapshotId = stableHash(candidate.snapshotKey);
|
|
2818
2818
|
}
|
|
2819
|
-
const
|
|
2819
|
+
const timestamp5 = candidate.observedAt ?? job.startedAt;
|
|
2820
2820
|
return {
|
|
2821
2821
|
spanId: `codex-llm-${stableHash(`${job.traceId}|${nativeRequestId}`)}`,
|
|
2822
2822
|
traceId: job.traceId,
|
|
@@ -2827,8 +2827,8 @@ function toSpan(job, candidate, modelId) {
|
|
|
2827
2827
|
name: "codex response",
|
|
2828
2828
|
sequence: candidate.sequence,
|
|
2829
2829
|
status: "completed",
|
|
2830
|
-
startedAt:
|
|
2831
|
-
endedAt:
|
|
2830
|
+
startedAt: timestamp5,
|
|
2831
|
+
endedAt: timestamp5,
|
|
2832
2832
|
...modelId ? { modelId } : {},
|
|
2833
2833
|
inputRefs: [],
|
|
2834
2834
|
outputRefs: [],
|
|
@@ -3560,13 +3560,60 @@ var CodexAuditAdapter = class {
|
|
|
3560
3560
|
};
|
|
3561
3561
|
|
|
3562
3562
|
// src/audit/adapters/pi/pi-transcript-source.ts
|
|
3563
|
-
import { open as open3
|
|
3563
|
+
import { open as open3 } from "node:fs/promises";
|
|
3564
|
+
|
|
3565
|
+
// src/audit/core/transcript-fingerprint.ts
|
|
3566
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
3567
|
+
var READ_CHUNK_BYTES = 64 * 1024;
|
|
3568
|
+
async function readAndHashFilePrefixRange(handle, start, end) {
|
|
3569
|
+
if (!Number.isSafeInteger(start) || !Number.isSafeInteger(end) || start < 0 || end < start) {
|
|
3570
|
+
throw new Error("Transcript range must contain safe non-negative offsets");
|
|
3571
|
+
}
|
|
3572
|
+
const digest = createHash3("sha256").update(String(end)).update("\0");
|
|
3573
|
+
const output = Buffer.allocUnsafe(end - start);
|
|
3574
|
+
const chunk = Buffer.allocUnsafe(Math.min(READ_CHUNK_BYTES, Math.max(1, end)));
|
|
3575
|
+
let position = 0;
|
|
3576
|
+
while (position < end) {
|
|
3577
|
+
const requested = Math.min(chunk.length, end - position);
|
|
3578
|
+
const { bytesRead } = await handle.read(chunk, 0, requested, position);
|
|
3579
|
+
if (bytesRead === 0) {
|
|
3580
|
+
throw new Error(`Transcript ended before prefix offset ${end}`);
|
|
3581
|
+
}
|
|
3582
|
+
const value = chunk.subarray(0, bytesRead);
|
|
3583
|
+
digest.update(value);
|
|
3584
|
+
const overlapStart = Math.max(position, start);
|
|
3585
|
+
const overlapEnd = Math.min(position + bytesRead, end);
|
|
3586
|
+
if (overlapStart < overlapEnd) {
|
|
3587
|
+
value.copy(
|
|
3588
|
+
output,
|
|
3589
|
+
overlapStart - start,
|
|
3590
|
+
overlapStart - position,
|
|
3591
|
+
overlapEnd - position
|
|
3592
|
+
);
|
|
3593
|
+
}
|
|
3594
|
+
position += bytesRead;
|
|
3595
|
+
}
|
|
3596
|
+
return { buffer: output, fingerprint: digest.digest("hex") };
|
|
3597
|
+
}
|
|
3598
|
+
|
|
3599
|
+
// src/audit/adapters/pi/pi-transcript-source.ts
|
|
3564
3600
|
function isRecord4(value) {
|
|
3565
3601
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3566
3602
|
}
|
|
3567
3603
|
function finiteOffset3(value, fallback) {
|
|
3568
3604
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : fallback;
|
|
3569
3605
|
}
|
|
3606
|
+
function recordIntegrityFailure(evidence, transcriptPath, detail) {
|
|
3607
|
+
evidence.anomalies.push({
|
|
3608
|
+
code: "pi_transcript_source_changed",
|
|
3609
|
+
message: `${transcriptPath}: ${detail}`
|
|
3610
|
+
});
|
|
3611
|
+
evidence.gaps.push({
|
|
3612
|
+
category: "main_transcript",
|
|
3613
|
+
reason: "correlation_failed",
|
|
3614
|
+
detail: `${transcriptPath}: ${detail}`
|
|
3615
|
+
});
|
|
3616
|
+
}
|
|
3570
3617
|
async function collectPiTranscript(boundary) {
|
|
3571
3618
|
const transcriptPath = typeof boundary.transcriptPath === "string" ? boundary.transcriptPath : void 0;
|
|
3572
3619
|
if (!transcriptPath) {
|
|
@@ -3591,31 +3638,57 @@ async function collectPiTranscript(boundary) {
|
|
|
3591
3638
|
sourcePaths: [transcriptPath]
|
|
3592
3639
|
};
|
|
3593
3640
|
try {
|
|
3594
|
-
const sourceStat = await stat4(transcriptPath);
|
|
3595
|
-
const requestedStart = finiteOffset3(boundary.transcriptStartOffset, 0);
|
|
3596
|
-
const requestedEnd = typeof boundary.transcriptEndOffset === "number" ? finiteOffset3(boundary.transcriptEndOffset, sourceStat.size) : sourceStat.size;
|
|
3597
|
-
if (requestedStart > sourceStat.size) {
|
|
3598
|
-
evidence.anomalies.push({
|
|
3599
|
-
code: "pi_transcript_boundary_out_of_range",
|
|
3600
|
-
message: `${transcriptPath}: start ${requestedStart} exceeds size ${sourceStat.size}`
|
|
3601
|
-
});
|
|
3602
|
-
evidence.gaps.push({
|
|
3603
|
-
category: "main_transcript",
|
|
3604
|
-
reason: "correlation_failed",
|
|
3605
|
-
detail: `${transcriptPath}:${requestedStart}-${requestedEnd}`
|
|
3606
|
-
});
|
|
3607
|
-
return evidence;
|
|
3608
|
-
}
|
|
3609
|
-
const start = requestedStart;
|
|
3610
|
-
const end = Math.min(Math.max(requestedEnd, start), sourceStat.size);
|
|
3611
|
-
const length = end - start;
|
|
3612
|
-
if (length === 0) return evidence;
|
|
3613
3641
|
const handle = await open3(transcriptPath, "r");
|
|
3614
3642
|
let buffer;
|
|
3643
|
+
let start;
|
|
3615
3644
|
try {
|
|
3616
|
-
|
|
3617
|
-
const
|
|
3618
|
-
|
|
3645
|
+
const sourceStat = await handle.stat();
|
|
3646
|
+
const requestedStart = finiteOffset3(boundary.transcriptStartOffset, 0);
|
|
3647
|
+
const requestedEnd = typeof boundary.transcriptEndOffset === "number" ? finiteOffset3(boundary.transcriptEndOffset, sourceStat.size) : sourceStat.size;
|
|
3648
|
+
if (requestedStart > sourceStat.size || requestedEnd > sourceStat.size) {
|
|
3649
|
+
evidence.anomalies.push({
|
|
3650
|
+
code: "pi_transcript_boundary_out_of_range",
|
|
3651
|
+
message: `${transcriptPath}: boundary ${requestedStart}-${requestedEnd} exceeds size ${sourceStat.size}`
|
|
3652
|
+
});
|
|
3653
|
+
evidence.gaps.push({
|
|
3654
|
+
category: "main_transcript",
|
|
3655
|
+
reason: "correlation_failed",
|
|
3656
|
+
detail: `${transcriptPath}:${requestedStart}-${requestedEnd}`
|
|
3657
|
+
});
|
|
3658
|
+
return evidence;
|
|
3659
|
+
}
|
|
3660
|
+
const expectedIdentity = typeof boundary.transcriptFileIdentity === "string" ? boundary.transcriptFileIdentity : void 0;
|
|
3661
|
+
const actualIdentity = `${sourceStat.dev}:${sourceStat.ino}`;
|
|
3662
|
+
if (expectedIdentity && actualIdentity !== expectedIdentity) {
|
|
3663
|
+
recordIntegrityFailure(
|
|
3664
|
+
evidence,
|
|
3665
|
+
transcriptPath,
|
|
3666
|
+
`identity ${actualIdentity} does not match ${expectedIdentity}`
|
|
3667
|
+
);
|
|
3668
|
+
return evidence;
|
|
3669
|
+
}
|
|
3670
|
+
const expectedFingerprint = typeof boundary.transcriptPrefixFingerprint === "string" ? boundary.transcriptPrefixFingerprint : void 0;
|
|
3671
|
+
start = requestedStart;
|
|
3672
|
+
const end = Math.max(requestedEnd, start);
|
|
3673
|
+
const length = end - start;
|
|
3674
|
+
if (expectedFingerprint) {
|
|
3675
|
+
const verified = await readAndHashFilePrefixRange(handle, start, end);
|
|
3676
|
+
if (verified.fingerprint !== expectedFingerprint) {
|
|
3677
|
+
recordIntegrityFailure(
|
|
3678
|
+
evidence,
|
|
3679
|
+
transcriptPath,
|
|
3680
|
+
"closed transcript prefix fingerprint changed"
|
|
3681
|
+
);
|
|
3682
|
+
return evidence;
|
|
3683
|
+
}
|
|
3684
|
+
buffer = verified.buffer;
|
|
3685
|
+
} else {
|
|
3686
|
+
if (length === 0) return evidence;
|
|
3687
|
+
buffer = Buffer.allocUnsafe(length);
|
|
3688
|
+
const { bytesRead } = await handle.read(buffer, 0, length, start);
|
|
3689
|
+
buffer = buffer.subarray(0, bytesRead);
|
|
3690
|
+
}
|
|
3691
|
+
if (length === 0) return evidence;
|
|
3619
3692
|
} finally {
|
|
3620
3693
|
await handle.close();
|
|
3621
3694
|
}
|
|
@@ -4273,7 +4346,7 @@ var PiAuditAdapter = class {
|
|
|
4273
4346
|
};
|
|
4274
4347
|
|
|
4275
4348
|
// src/audit/adapters/acp/generic-acp-audit-adapter.ts
|
|
4276
|
-
import { readFile as readFile3, readdir as readdir2, stat as
|
|
4349
|
+
import { readFile as readFile3, readdir as readdir2, stat as stat4 } from "node:fs/promises";
|
|
4277
4350
|
import { homedir } from "node:os";
|
|
4278
4351
|
import { basename as basename4, join as join2 } from "node:path";
|
|
4279
4352
|
var DEFAULT_CAPTURE4 = Object.freeze({
|
|
@@ -4305,9 +4378,9 @@ function eventTime(value) {
|
|
|
4305
4378
|
}
|
|
4306
4379
|
return void 0;
|
|
4307
4380
|
}
|
|
4308
|
-
function withinTurn(
|
|
4309
|
-
if (!
|
|
4310
|
-
const at = Date.parse(
|
|
4381
|
+
function withinTurn(timestamp5, job) {
|
|
4382
|
+
if (!timestamp5) return false;
|
|
4383
|
+
const at = Date.parse(timestamp5);
|
|
4311
4384
|
return at >= Date.parse(job.startedAt) - 5e3 && at <= Date.parse(job.endedAt) + 3e4;
|
|
4312
4385
|
}
|
|
4313
4386
|
function contentText2(value) {
|
|
@@ -4364,7 +4437,7 @@ async function collectQwenUsage(job, providerSessionId, cwd) {
|
|
|
4364
4437
|
`${providerSessionId}.jsonl`
|
|
4365
4438
|
);
|
|
4366
4439
|
try {
|
|
4367
|
-
await
|
|
4440
|
+
await stat4(sourcePath);
|
|
4368
4441
|
} catch {
|
|
4369
4442
|
return { records: [] };
|
|
4370
4443
|
}
|
|
@@ -4413,7 +4486,7 @@ async function locateGeminiSession(providerSessionId, cwd) {
|
|
|
4413
4486
|
const candidates = names.filter((name) => name.startsWith("session-") && name.includes(shortId) && (name.endsWith(".json") || name.endsWith(".jsonl")));
|
|
4414
4487
|
const ranked = await Promise.all(candidates.map(async (name) => {
|
|
4415
4488
|
const sourcePath = join2(chats, name);
|
|
4416
|
-
return { sourcePath, modifiedAt: (await
|
|
4489
|
+
return { sourcePath, modifiedAt: (await stat4(sourcePath)).mtimeMs };
|
|
4417
4490
|
}));
|
|
4418
4491
|
return ranked.sort((left, right) => right.modifiedAt - left.modifiedAt)[0]?.sourcePath;
|
|
4419
4492
|
} catch {
|
|
@@ -4895,7 +4968,7 @@ var GenericAcpAuditAdapter = class {
|
|
|
4895
4968
|
};
|
|
4896
4969
|
|
|
4897
4970
|
// src/audit/adapters/acp/kimi-audit-adapter.ts
|
|
4898
|
-
import { readFile as readFile4, readdir as readdir3, stat as
|
|
4971
|
+
import { readFile as readFile4, readdir as readdir3, stat as stat5 } from "node:fs/promises";
|
|
4899
4972
|
import { homedir as homedir2 } from "node:os";
|
|
4900
4973
|
import { basename as basename5, dirname, join as join3 } from "node:path";
|
|
4901
4974
|
var DEFAULT_CAPTURE5 = Object.freeze({
|
|
@@ -4950,8 +5023,8 @@ function lineEvent(line) {
|
|
|
4950
5023
|
return line.record.type === "context.append_loop_event" && isRecord7(line.record.event) ? line.record.event : void 0;
|
|
4951
5024
|
}
|
|
4952
5025
|
function withinTurn2(value, job) {
|
|
4953
|
-
const
|
|
4954
|
-
return Number.isFinite(
|
|
5026
|
+
const timestamp5 = Date.parse(isoTime(value, ""));
|
|
5027
|
+
return Number.isFinite(timestamp5) && timestamp5 >= Date.parse(job.startedAt) - 5e3 && timestamp5 <= Date.parse(job.endedAt) + 3e4;
|
|
4955
5028
|
}
|
|
4956
5029
|
async function readJsonl2(sourcePath) {
|
|
4957
5030
|
const raw = await readFile4(sourcePath, "utf8");
|
|
@@ -5027,7 +5100,7 @@ async function locateSessionDirectory(job) {
|
|
|
5027
5100
|
const path = join3(root, workspace.name, providerSessionId);
|
|
5028
5101
|
const wirePath = join3(path, "agents", "main", "wire.jsonl");
|
|
5029
5102
|
try {
|
|
5030
|
-
const wireStat = await
|
|
5103
|
+
const wireStat = await stat5(wirePath);
|
|
5031
5104
|
let cwdMatches = false;
|
|
5032
5105
|
const cwd = stringValue5(job.boundary.cwd);
|
|
5033
5106
|
if (cwd) {
|
|
@@ -5868,7 +5941,7 @@ var KimiAuditAdapter = class {
|
|
|
5868
5941
|
};
|
|
5869
5942
|
|
|
5870
5943
|
// src/audit/adapters/acp/reasonix-transcript-source.ts
|
|
5871
|
-
import { open as open4, stat as
|
|
5944
|
+
import { open as open4, stat as stat6 } from "node:fs/promises";
|
|
5872
5945
|
function isRecord8(value) {
|
|
5873
5946
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5874
5947
|
}
|
|
@@ -5921,7 +5994,7 @@ async function collectReasonixTranscript(boundary) {
|
|
|
5921
5994
|
return evidence;
|
|
5922
5995
|
}
|
|
5923
5996
|
try {
|
|
5924
|
-
const sourceStat = await
|
|
5997
|
+
const sourceStat = await stat6(transcriptPath);
|
|
5925
5998
|
const requestedStart = finiteOffset4(boundary.transcriptStartOffset, 0);
|
|
5926
5999
|
const requestedEnd = typeof boundary.transcriptEndOffset === "number" ? finiteOffset4(boundary.transcriptEndOffset, sourceStat.size) : sourceStat.size;
|
|
5927
6000
|
if (requestedStart > sourceStat.size) {
|
|
@@ -7986,7 +8059,7 @@ var DeepSeekHarnessAuditAdapter = class {
|
|
|
7986
8059
|
const mapped = mapDshSessionEvent(event);
|
|
7987
8060
|
const eventSessionId = String(event.sessionId ?? "");
|
|
7988
8061
|
const isChild = !!eventSessionId && !!rootSessionId && eventSessionId !== rootSessionId;
|
|
7989
|
-
const
|
|
8062
|
+
const timestamp5 = iso(record4.at, job.startedAt);
|
|
7990
8063
|
if (mapped.kind === "thinking") {
|
|
7991
8064
|
if (capture.thinking && mapped.text) {
|
|
7992
8065
|
addContent10(contents, { role: "thinking", format: "text", value: mapped.text, captureLevel: "runtime_exact" });
|
|
@@ -8061,9 +8134,9 @@ var DeepSeekHarnessAuditAdapter = class {
|
|
|
8061
8134
|
continue;
|
|
8062
8135
|
}
|
|
8063
8136
|
tool.span.status = mapped.isError ? "failed" : "completed";
|
|
8064
|
-
tool.span.endedAt =
|
|
8137
|
+
tool.span.endedAt = timestamp5;
|
|
8065
8138
|
const startMs = Date.parse(tool.span.startedAt);
|
|
8066
|
-
const endMs = Date.parse(
|
|
8139
|
+
const endMs = Date.parse(timestamp5);
|
|
8067
8140
|
if (Number.isFinite(startMs) && Number.isFinite(endMs)) {
|
|
8068
8141
|
tool.span.durationMs = Math.max(0, endMs - startMs);
|
|
8069
8142
|
}
|
|
@@ -8161,7 +8234,7 @@ function turnSpan(job, spanId) {
|
|
|
8161
8234
|
};
|
|
8162
8235
|
}
|
|
8163
8236
|
function simpleSpan(job, parentSpanId, sequence, kind, name, at, nativeIds2) {
|
|
8164
|
-
const
|
|
8237
|
+
const timestamp5 = iso(at, job.startedAt);
|
|
8165
8238
|
return {
|
|
8166
8239
|
spanId: `deepseek-harness:${job.turnId}:${sequence}`,
|
|
8167
8240
|
traceId: job.traceId,
|
|
@@ -8172,8 +8245,8 @@ function simpleSpan(job, parentSpanId, sequence, kind, name, at, nativeIds2) {
|
|
|
8172
8245
|
name,
|
|
8173
8246
|
sequence,
|
|
8174
8247
|
status: "completed",
|
|
8175
|
-
startedAt:
|
|
8176
|
-
endedAt:
|
|
8248
|
+
startedAt: timestamp5,
|
|
8249
|
+
endedAt: timestamp5,
|
|
8177
8250
|
inputRefs: [],
|
|
8178
8251
|
outputRefs: [],
|
|
8179
8252
|
provider: { provider: "deepseek-harness", nativeEventType: name, nativeIds: nativeIds2 },
|
|
@@ -8231,31 +8304,412 @@ function usageSpan(job, parentSpanId, sequence, at, raw, requestId2, modelId, pr
|
|
|
8231
8304
|
return span2;
|
|
8232
8305
|
}
|
|
8233
8306
|
|
|
8234
|
-
// src/audit/adapters/
|
|
8307
|
+
// src/audit/adapters/agy/agy-audit-adapter.ts
|
|
8235
8308
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
8236
|
-
|
|
8309
|
+
var DEFAULT_CAPTURE11 = Object.freeze({
|
|
8310
|
+
inputOutput: true,
|
|
8311
|
+
tools: true,
|
|
8312
|
+
subagents: false,
|
|
8313
|
+
thinking: true,
|
|
8314
|
+
rawProviderBody: false
|
|
8315
|
+
});
|
|
8316
|
+
var AGY_LOG_EXCERPT_MAX_CHARS = 256e3;
|
|
8237
8317
|
function isRecord14(value) {
|
|
8238
8318
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8239
8319
|
}
|
|
8240
|
-
|
|
8241
|
-
|
|
8320
|
+
function stringValue10(value) {
|
|
8321
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
8322
|
+
}
|
|
8323
|
+
function offsetValue(value) {
|
|
8324
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
|
|
8325
|
+
}
|
|
8326
|
+
function captureOptions11(job) {
|
|
8327
|
+
return job.options?.enabled === true ? job.options.capture : DEFAULT_CAPTURE11;
|
|
8328
|
+
}
|
|
8329
|
+
function addContent11(contents, seen, content) {
|
|
8330
|
+
const key = [content.role, content.value ?? ""].join("\0");
|
|
8331
|
+
if (seen.has(key)) return seen.get(key);
|
|
8332
|
+
const reference = referenceCaptureContent(content);
|
|
8333
|
+
seen.set(key, reference);
|
|
8334
|
+
contents.push(content);
|
|
8335
|
+
return reference;
|
|
8336
|
+
}
|
|
8337
|
+
function append5(target, reference) {
|
|
8338
|
+
if (reference && !target.some((item) => item.contentId === reference.contentId)) {
|
|
8339
|
+
target.push(reference);
|
|
8340
|
+
}
|
|
8341
|
+
}
|
|
8342
|
+
function timestamp4(value, fallback) {
|
|
8343
|
+
return typeof value === "string" && Number.isFinite(Date.parse(value)) ? value : fallback;
|
|
8344
|
+
}
|
|
8345
|
+
function makeSpan8(input) {
|
|
8346
|
+
const startedAt = input.startedAt ?? input.job.startedAt;
|
|
8347
|
+
const endedAt = input.endedAt ?? input.job.endedAt;
|
|
8348
|
+
const startMs = Date.parse(startedAt);
|
|
8349
|
+
const endMs = Date.parse(endedAt);
|
|
8350
|
+
return {
|
|
8351
|
+
spanId: input.spanId,
|
|
8352
|
+
traceId: input.job.traceId,
|
|
8353
|
+
turnId: input.job.turnId,
|
|
8354
|
+
sessionId: input.job.sessionId,
|
|
8355
|
+
...input.parentSpanId ? { parentSpanId: input.parentSpanId } : {},
|
|
8356
|
+
kind: input.kind,
|
|
8357
|
+
name: input.name,
|
|
8358
|
+
sequence: input.sequence,
|
|
8359
|
+
status: input.status ?? "completed",
|
|
8360
|
+
startedAt,
|
|
8361
|
+
endedAt,
|
|
8362
|
+
...Number.isFinite(startMs) && Number.isFinite(endMs) ? { durationMs: Math.max(0, endMs - startMs) } : {},
|
|
8363
|
+
inputRefs: [],
|
|
8364
|
+
outputRefs: [],
|
|
8365
|
+
provider: {
|
|
8366
|
+
provider: "agy",
|
|
8367
|
+
nativeEventType: input.nativeEventType,
|
|
8368
|
+
nativeIds: Object.fromEntries(
|
|
8369
|
+
Object.entries(input.nativeIds ?? {}).filter(
|
|
8370
|
+
(entry) => typeof entry[1] === "string"
|
|
8371
|
+
)
|
|
8372
|
+
),
|
|
8373
|
+
...input.rawAttributes ? { rawAttributes: input.rawAttributes } : {}
|
|
8374
|
+
},
|
|
8375
|
+
provenance: {
|
|
8376
|
+
source: "connector",
|
|
8377
|
+
accuracy: "runtime_exact"
|
|
8378
|
+
}
|
|
8379
|
+
};
|
|
8380
|
+
}
|
|
8381
|
+
function parseToolInvocation(value) {
|
|
8382
|
+
if (!isRecord14(value) || typeof value.sequence !== "number" || typeof value.observedAt !== "string" || typeof value.action !== "string") {
|
|
8383
|
+
return void 0;
|
|
8384
|
+
}
|
|
8385
|
+
return {
|
|
8386
|
+
sequence: value.sequence,
|
|
8387
|
+
observedAt: value.observedAt,
|
|
8388
|
+
action: value.action,
|
|
8389
|
+
...value.params === void 0 ? {} : { params: value.params },
|
|
8390
|
+
...value.result === void 0 ? {} : { result: value.result },
|
|
8391
|
+
...typeof value.error === "string" ? { error: value.error } : {},
|
|
8392
|
+
...typeof value.completedAt === "string" ? { completedAt: value.completedAt } : {}
|
|
8393
|
+
};
|
|
8394
|
+
}
|
|
8395
|
+
var AgyAuditAdapter = class {
|
|
8396
|
+
provider = "agy";
|
|
8397
|
+
async collect(job) {
|
|
8398
|
+
const evidence = {
|
|
8399
|
+
toolInvocations: [],
|
|
8400
|
+
anomalies: [],
|
|
8401
|
+
gaps: []
|
|
8402
|
+
};
|
|
8403
|
+
const bundle = isRecord14(job.boundary.agyEvidence) ? job.boundary.agyEvidence : void 0;
|
|
8404
|
+
if (!bundle) {
|
|
8405
|
+
evidence.gaps.push({
|
|
8406
|
+
category: "agy_evidence",
|
|
8407
|
+
reason: "source_log_missing",
|
|
8408
|
+
detail: "boundary.agyEvidence is missing"
|
|
8409
|
+
});
|
|
8410
|
+
} else {
|
|
8411
|
+
const prompt = stringValue10(bundle.prompt);
|
|
8412
|
+
if (prompt !== void 0) evidence.prompt = prompt;
|
|
8413
|
+
const stdout = stringValue10(bundle.stdout);
|
|
8414
|
+
if (stdout !== void 0) evidence.stdout = stdout;
|
|
8415
|
+
const stderr = stringValue10(bundle.stderr);
|
|
8416
|
+
if (stderr !== void 0) evidence.stderr = stderr;
|
|
8417
|
+
if (typeof bundle.exitCode === "number" || bundle.exitCode === null) {
|
|
8418
|
+
evidence.exitCode = bundle.exitCode;
|
|
8419
|
+
}
|
|
8420
|
+
const response = stringValue10(bundle.response);
|
|
8421
|
+
if (response !== void 0) evidence.response = response;
|
|
8422
|
+
if (Array.isArray(bundle.toolInvocations)) {
|
|
8423
|
+
for (const value of bundle.toolInvocations) {
|
|
8424
|
+
const invocation = parseToolInvocation(value);
|
|
8425
|
+
if (!invocation) {
|
|
8426
|
+
evidence.anomalies.push({
|
|
8427
|
+
code: "agy_tool_invocation_malformed",
|
|
8428
|
+
message: "agy tool invocation row is malformed"
|
|
8429
|
+
});
|
|
8430
|
+
evidence.gaps.push({
|
|
8431
|
+
category: "agy_tool_invocation",
|
|
8432
|
+
reason: "correlation_failed"
|
|
8433
|
+
});
|
|
8434
|
+
continue;
|
|
8435
|
+
}
|
|
8436
|
+
evidence.toolInvocations.push(invocation);
|
|
8437
|
+
}
|
|
8438
|
+
evidence.toolInvocations.sort(
|
|
8439
|
+
(left, right) => left.sequence - right.sequence
|
|
8440
|
+
);
|
|
8441
|
+
}
|
|
8442
|
+
}
|
|
8443
|
+
const logPath = stringValue10(job.boundary.transcriptPath);
|
|
8444
|
+
const logStart = offsetValue(job.boundary.transcriptStartOffset);
|
|
8445
|
+
const logEnd = offsetValue(job.boundary.transcriptEndOffset);
|
|
8446
|
+
if (logPath) {
|
|
8447
|
+
evidence.logPath = logPath;
|
|
8448
|
+
try {
|
|
8449
|
+
const raw = await readFile5(logPath);
|
|
8450
|
+
const start = logStart !== void 0 && logStart <= raw.length ? logStart : 0;
|
|
8451
|
+
const end = logEnd !== void 0 && logEnd >= start && logEnd <= raw.length ? logEnd : raw.length;
|
|
8452
|
+
evidence.logStartOffset = start;
|
|
8453
|
+
evidence.logEndOffset = end;
|
|
8454
|
+
const excerpt = raw.subarray(start, end).toString("utf-8");
|
|
8455
|
+
evidence.logExcerpt = excerpt.length > AGY_LOG_EXCERPT_MAX_CHARS ? excerpt.slice(0, AGY_LOG_EXCERPT_MAX_CHARS) : excerpt;
|
|
8456
|
+
} catch (error) {
|
|
8457
|
+
evidence.anomalies.push({
|
|
8458
|
+
code: "agy_log_unreadable",
|
|
8459
|
+
message: error instanceof Error ? error.message : String(error)
|
|
8460
|
+
});
|
|
8461
|
+
evidence.gaps.push({
|
|
8462
|
+
category: "agy_log",
|
|
8463
|
+
reason: "source_log_missing",
|
|
8464
|
+
detail: logPath
|
|
8465
|
+
});
|
|
8466
|
+
}
|
|
8467
|
+
}
|
|
8468
|
+
return evidence;
|
|
8469
|
+
}
|
|
8470
|
+
async normalize(job, rawEvidence) {
|
|
8471
|
+
const collection = rawEvidence;
|
|
8472
|
+
const capture = captureOptions11(job);
|
|
8473
|
+
const spans = [];
|
|
8474
|
+
const contents = [];
|
|
8475
|
+
const seen = /* @__PURE__ */ new Map();
|
|
8476
|
+
let sequence = 0;
|
|
8477
|
+
const turnSpanId = `agy:${job.turnId}:turn`;
|
|
8478
|
+
const turn = makeSpan8({
|
|
8479
|
+
job,
|
|
8480
|
+
spanId: turnSpanId,
|
|
8481
|
+
kind: "turn",
|
|
8482
|
+
name: "agy audited turn",
|
|
8483
|
+
sequence: sequence++,
|
|
8484
|
+
status: job.outcome === "completed" ? "completed" : job.outcome === "cancelled" ? "cancelled" : "failed",
|
|
8485
|
+
nativeEventType: "print_turn",
|
|
8486
|
+
nativeIds: {
|
|
8487
|
+
providerSessionId: stringValue10(job.boundary.providerSessionId)
|
|
8488
|
+
}
|
|
8489
|
+
});
|
|
8490
|
+
spans.push(turn);
|
|
8491
|
+
const runtimeInput = capture.inputOutput && job.input ? addContent11(contents, seen, {
|
|
8492
|
+
...job.input,
|
|
8493
|
+
captureLevel: job.input.captureLevel ?? "runtime_exact"
|
|
8494
|
+
}) : void 0;
|
|
8495
|
+
append5(turn.inputRefs, runtimeInput);
|
|
8496
|
+
if (capture.inputOutput && job.finalOutput) {
|
|
8497
|
+
append5(turn.outputRefs, addContent11(contents, seen, {
|
|
8498
|
+
...job.finalOutput,
|
|
8499
|
+
captureLevel: job.finalOutput.captureLevel ?? "runtime_exact"
|
|
8500
|
+
}));
|
|
8501
|
+
}
|
|
8502
|
+
const request = makeSpan8({
|
|
8503
|
+
job,
|
|
8504
|
+
spanId: `agy:${job.sessionId}:request:${job.turnId}`,
|
|
8505
|
+
parentSpanId: turnSpanId,
|
|
8506
|
+
kind: "llm_request",
|
|
8507
|
+
name: "agy print request",
|
|
8508
|
+
sequence: sequence++,
|
|
8509
|
+
status: job.outcome === "completed" ? "completed" : "failed",
|
|
8510
|
+
nativeEventType: "print_process",
|
|
8511
|
+
nativeIds: {
|
|
8512
|
+
providerSessionId: stringValue10(job.boundary.providerSessionId)
|
|
8513
|
+
},
|
|
8514
|
+
rawAttributes: {
|
|
8515
|
+
...collection.exitCode === void 0 ? {} : { exitCode: collection.exitCode },
|
|
8516
|
+
...collection.logPath ? { logPath: collection.logPath } : {},
|
|
8517
|
+
...collection.logStartOffset === void 0 ? {} : { logStartOffset: collection.logStartOffset },
|
|
8518
|
+
...collection.logEndOffset === void 0 ? {} : { logEndOffset: collection.logEndOffset },
|
|
8519
|
+
...collection.stderr ? { stderr: collection.stderr.slice(0, 2e3) } : {}
|
|
8520
|
+
}
|
|
8521
|
+
});
|
|
8522
|
+
append5(request.inputRefs, runtimeInput);
|
|
8523
|
+
if (capture.inputOutput && collection.prompt) {
|
|
8524
|
+
append5(request.inputRefs, addContent11(contents, seen, {
|
|
8525
|
+
role: "model_request",
|
|
8526
|
+
format: "text",
|
|
8527
|
+
value: collection.prompt,
|
|
8528
|
+
captureLevel: "provider_exact"
|
|
8529
|
+
}));
|
|
8530
|
+
}
|
|
8531
|
+
const outputText2 = collection.response ?? collection.stdout;
|
|
8532
|
+
if (capture.inputOutput && outputText2) {
|
|
8533
|
+
append5(request.outputRefs, addContent11(contents, seen, {
|
|
8534
|
+
role: "assistant_text",
|
|
8535
|
+
format: "text",
|
|
8536
|
+
value: outputText2,
|
|
8537
|
+
captureLevel: "provider_exact"
|
|
8538
|
+
}));
|
|
8539
|
+
}
|
|
8540
|
+
if (capture.rawProviderBody && collection.logExcerpt) {
|
|
8541
|
+
append5(request.outputRefs, addContent11(contents, seen, {
|
|
8542
|
+
role: "model_response",
|
|
8543
|
+
format: "text",
|
|
8544
|
+
value: collection.logExcerpt,
|
|
8545
|
+
sourcePath: collection.logPath,
|
|
8546
|
+
sourceOffset: collection.logStartOffset,
|
|
8547
|
+
captureLevel: "provider_exact"
|
|
8548
|
+
}));
|
|
8549
|
+
}
|
|
8550
|
+
spans.push(request);
|
|
8551
|
+
if (capture.tools) {
|
|
8552
|
+
for (const invocation of collection.toolInvocations) {
|
|
8553
|
+
const tool = makeSpan8({
|
|
8554
|
+
job,
|
|
8555
|
+
spanId: `agy:${job.sessionId}:tool:${invocation.sequence}`,
|
|
8556
|
+
parentSpanId: request.spanId,
|
|
8557
|
+
kind: "tool_call",
|
|
8558
|
+
name: invocation.action,
|
|
8559
|
+
sequence: sequence++,
|
|
8560
|
+
status: invocation.error ? "failed" : invocation.completedAt ? "completed" : "running",
|
|
8561
|
+
startedAt: timestamp4(invocation.observedAt, job.startedAt),
|
|
8562
|
+
endedAt: timestamp4(invocation.completedAt, job.endedAt),
|
|
8563
|
+
nativeEventType: "grix_tool_invoke",
|
|
8564
|
+
nativeIds: { toolSequence: String(invocation.sequence) },
|
|
8565
|
+
rawAttributes: { toolInvocation: invocation }
|
|
8566
|
+
});
|
|
8567
|
+
if (invocation.params !== void 0) {
|
|
8568
|
+
append5(tool.inputRefs, addContent11(contents, seen, {
|
|
8569
|
+
role: "tool_arguments",
|
|
8570
|
+
format: "json",
|
|
8571
|
+
value: typeof invocation.params === "string" ? invocation.params : JSON.stringify(invocation.params),
|
|
8572
|
+
captureLevel: "runtime_exact"
|
|
8573
|
+
}));
|
|
8574
|
+
}
|
|
8575
|
+
const result = invocation.result ?? invocation.error;
|
|
8576
|
+
if (result !== void 0) {
|
|
8577
|
+
append5(tool.outputRefs, addContent11(contents, seen, {
|
|
8578
|
+
role: "tool_result",
|
|
8579
|
+
format: typeof result === "string" ? "text" : "json",
|
|
8580
|
+
value: typeof result === "string" ? result : JSON.stringify(result),
|
|
8581
|
+
captureLevel: "runtime_exact"
|
|
8582
|
+
}));
|
|
8583
|
+
}
|
|
8584
|
+
spans.push(tool);
|
|
8585
|
+
}
|
|
8586
|
+
}
|
|
8587
|
+
collection.gaps.push({
|
|
8588
|
+
category: "provider_usage",
|
|
8589
|
+
reason: "provider_usage_missing",
|
|
8590
|
+
detail: "agy print mode does not report token usage"
|
|
8591
|
+
});
|
|
8592
|
+
return {
|
|
8593
|
+
spans,
|
|
8594
|
+
contents,
|
|
8595
|
+
anomalies: collection.anomalies,
|
|
8596
|
+
collection,
|
|
8597
|
+
capture
|
|
8598
|
+
};
|
|
8599
|
+
}
|
|
8600
|
+
async correlate(_job, evidence) {
|
|
8601
|
+
return evidence;
|
|
8602
|
+
}
|
|
8603
|
+
validate(job, normalized) {
|
|
8604
|
+
const evidence = normalized;
|
|
8605
|
+
const requests = evidence.spans.filter(
|
|
8606
|
+
(item) => item.kind === "llm_request"
|
|
8607
|
+
);
|
|
8608
|
+
const tools = evidence.spans.filter((item) => item.kind === "tool_call");
|
|
8609
|
+
const inputComplete = !evidence.capture.inputOutput || job.input !== void 0 || evidence.collection.prompt !== void 0;
|
|
8610
|
+
const outputComplete = !evidence.capture.inputOutput || job.finalOutput !== void 0 || requests.some((request) => request.outputRefs.length > 0);
|
|
8611
|
+
const toolCallsComplete = !evidence.capture.tools || tools.every((tool) => tool.status !== "running");
|
|
8612
|
+
const usageComplete = false;
|
|
8613
|
+
const gaps = [...evidence.collection.gaps];
|
|
8614
|
+
if (evidence.capture.rawProviderBody) {
|
|
8615
|
+
gaps.push({
|
|
8616
|
+
category: "raw_provider_body",
|
|
8617
|
+
reason: "raw_capture_disabled",
|
|
8618
|
+
detail: "agy print mode exposes prompt/stdout and the CLI log, not raw model HTTP bodies"
|
|
8619
|
+
});
|
|
8620
|
+
}
|
|
8621
|
+
const complete = inputComplete && outputComplete && toolCallsComplete && usageComplete && gaps.length === 0;
|
|
8622
|
+
return {
|
|
8623
|
+
status: requests.length === 0 ? "failed" : complete ? "complete" : "partial",
|
|
8624
|
+
inputComplete,
|
|
8625
|
+
outputComplete,
|
|
8626
|
+
toolCallsComplete,
|
|
8627
|
+
subagentsComplete: true,
|
|
8628
|
+
usageComplete,
|
|
8629
|
+
rawRequestsComplete: false,
|
|
8630
|
+
gaps
|
|
8631
|
+
};
|
|
8632
|
+
}
|
|
8633
|
+
};
|
|
8634
|
+
|
|
8635
|
+
// src/audit/adapters/openclaw/openclaw-audit-adapter.ts
|
|
8636
|
+
import { readFile as readFile6, readdir as readdir4, stat as stat7 } from "node:fs/promises";
|
|
8637
|
+
import { basename as basename6, dirname as dirname2, join as join4 } from "node:path";
|
|
8638
|
+
function isRecord15(value) {
|
|
8639
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8640
|
+
}
|
|
8641
|
+
function replaceTranscriptPath(boundary, transcriptPath) {
|
|
8642
|
+
const next = { ...boundary, transcriptPath };
|
|
8643
|
+
delete next.transcriptStartOffset;
|
|
8644
|
+
delete next.transcriptEndOffset;
|
|
8645
|
+
delete next.transcriptFileIdentity;
|
|
8646
|
+
delete next.transcriptPrefixFingerprint;
|
|
8647
|
+
return next;
|
|
8648
|
+
}
|
|
8649
|
+
async function fileIdentity(path) {
|
|
8650
|
+
try {
|
|
8651
|
+
const source = await stat7(path);
|
|
8652
|
+
return `${source.dev}:${source.ino}`;
|
|
8653
|
+
} catch {
|
|
8654
|
+
return void 0;
|
|
8655
|
+
}
|
|
8656
|
+
}
|
|
8657
|
+
async function resolveResetTranscriptPath(transcriptPath, expectedIdentity) {
|
|
8658
|
+
if (!expectedIdentity) return void 0;
|
|
8659
|
+
try {
|
|
8660
|
+
const directory = dirname2(transcriptPath);
|
|
8661
|
+
const prefix = `${basename6(transcriptPath)}.reset`;
|
|
8662
|
+
const candidates = (await readdir4(directory)).filter((entry) => entry.startsWith(prefix)).sort().reverse();
|
|
8663
|
+
for (const entry of candidates) {
|
|
8664
|
+
const candidate = join4(directory, entry);
|
|
8665
|
+
if (await fileIdentity(candidate) === expectedIdentity) return candidate;
|
|
8666
|
+
}
|
|
8667
|
+
} catch {
|
|
8668
|
+
}
|
|
8669
|
+
return void 0;
|
|
8670
|
+
}
|
|
8671
|
+
async function resolveCurrentTranscriptPath(boundary) {
|
|
8242
8672
|
const storePath = typeof boundary.sessionStorePath === "string" ? boundary.sessionStorePath : void 0;
|
|
8243
8673
|
const sessionKey = typeof boundary.routeSessionKey === "string" ? boundary.routeSessionKey : void 0;
|
|
8244
|
-
if (!storePath || !sessionKey) return
|
|
8674
|
+
if (!storePath || !sessionKey) return void 0;
|
|
8245
8675
|
try {
|
|
8246
|
-
const parsed = JSON.parse(await
|
|
8247
|
-
if (!
|
|
8676
|
+
const parsed = JSON.parse(await readFile6(storePath, "utf8"));
|
|
8677
|
+
if (!isRecord15(parsed) || !isRecord15(parsed[sessionKey])) return void 0;
|
|
8248
8678
|
const session = parsed[sessionKey];
|
|
8249
|
-
|
|
8250
|
-
return sessionFile ? { ...boundary, transcriptPath: sessionFile } : boundary;
|
|
8679
|
+
return typeof session.sessionFile === "string" ? session.sessionFile : typeof session.sessionId === "string" ? join4(dirname2(storePath), `${session.sessionId}.jsonl`) : void 0;
|
|
8251
8680
|
} catch {
|
|
8681
|
+
return void 0;
|
|
8682
|
+
}
|
|
8683
|
+
}
|
|
8684
|
+
async function resolveTranscriptBoundary(boundary) {
|
|
8685
|
+
const transcriptPath = typeof boundary.transcriptPath === "string" ? boundary.transcriptPath : void 0;
|
|
8686
|
+
if (!transcriptPath) {
|
|
8687
|
+
const currentTranscriptPath = await resolveCurrentTranscriptPath(boundary);
|
|
8688
|
+
return currentTranscriptPath ? replaceTranscriptPath(boundary, currentTranscriptPath) : boundary;
|
|
8689
|
+
}
|
|
8690
|
+
try {
|
|
8691
|
+
await stat7(transcriptPath);
|
|
8692
|
+
return boundary;
|
|
8693
|
+
} catch {
|
|
8694
|
+
const expectedIdentity = typeof boundary.transcriptFileIdentity === "string" ? boundary.transcriptFileIdentity : void 0;
|
|
8695
|
+
const resetTranscriptPath = await resolveResetTranscriptPath(
|
|
8696
|
+
transcriptPath,
|
|
8697
|
+
expectedIdentity
|
|
8698
|
+
);
|
|
8699
|
+
if (resetTranscriptPath) {
|
|
8700
|
+
return { ...boundary, transcriptPath: resetTranscriptPath };
|
|
8701
|
+
}
|
|
8702
|
+
const currentTranscriptPath = await resolveCurrentTranscriptPath(boundary);
|
|
8703
|
+
if (currentTranscriptPath && expectedIdentity && await fileIdentity(currentTranscriptPath) === expectedIdentity) {
|
|
8704
|
+
return { ...boundary, transcriptPath: currentTranscriptPath };
|
|
8705
|
+
}
|
|
8252
8706
|
return boundary;
|
|
8253
8707
|
}
|
|
8254
8708
|
}
|
|
8255
8709
|
function recordTimestamp(record4) {
|
|
8256
8710
|
const direct = typeof record4.timestamp === "string" ? Date.parse(record4.timestamp) : Number(record4.timestamp);
|
|
8257
8711
|
if (Number.isFinite(direct) && direct > 0) return direct;
|
|
8258
|
-
const message =
|
|
8712
|
+
const message = isRecord15(record4.message) ? record4.message : void 0;
|
|
8259
8713
|
const nested = Number(message?.timestamp);
|
|
8260
8714
|
return Number.isFinite(nested) && nested > 0 ? nested : void 0;
|
|
8261
8715
|
}
|
|
@@ -8317,20 +8771,20 @@ var OpenClawAuditAdapter = class {
|
|
|
8317
8771
|
|
|
8318
8772
|
// src/audit/storage/file-audit-replay-store.ts
|
|
8319
8773
|
import {
|
|
8320
|
-
createHash as
|
|
8774
|
+
createHash as createHash4,
|
|
8321
8775
|
randomUUID
|
|
8322
8776
|
} from "node:crypto";
|
|
8323
8777
|
import {
|
|
8324
8778
|
access,
|
|
8325
8779
|
open as open5,
|
|
8326
8780
|
mkdir,
|
|
8327
|
-
readFile as
|
|
8328
|
-
readdir as
|
|
8781
|
+
readFile as readFile7,
|
|
8782
|
+
readdir as readdir5,
|
|
8329
8783
|
rename,
|
|
8330
8784
|
rm,
|
|
8331
8785
|
writeFile
|
|
8332
8786
|
} from "node:fs/promises";
|
|
8333
|
-
import { basename as
|
|
8787
|
+
import { basename as basename7, dirname as dirname3, join as join5, relative, resolve as resolve3, sep as sep3 } from "node:path";
|
|
8334
8788
|
var SHA256_PATTERN = /^[a-f0-9]{64}$/;
|
|
8335
8789
|
var NO_CAPTURE = Object.freeze({
|
|
8336
8790
|
inputOutput: false,
|
|
@@ -8573,7 +9027,7 @@ var FileAuditReplayStore = class {
|
|
|
8573
9027
|
if (!SHA256_PATTERN.test(contentId)) {
|
|
8574
9028
|
throw new Error("Invalid audit content id");
|
|
8575
9029
|
}
|
|
8576
|
-
const plaintext = await
|
|
9030
|
+
const plaintext = await readFile7(this.blobPath(contentId));
|
|
8577
9031
|
if (sha256(plaintext) !== contentId) {
|
|
8578
9032
|
throw new Error("Audit blob content hash mismatch");
|
|
8579
9033
|
}
|
|
@@ -8714,7 +9168,7 @@ var FileAuditReplayStore = class {
|
|
|
8714
9168
|
}
|
|
8715
9169
|
async storePlaintextBlob(path, contentId, plaintext) {
|
|
8716
9170
|
if (await pathExists(path)) {
|
|
8717
|
-
const existing = await
|
|
9171
|
+
const existing = await readFile7(path);
|
|
8718
9172
|
if (sha256(existing) === contentId) return;
|
|
8719
9173
|
}
|
|
8720
9174
|
await this.atomicWrite(path, plaintext);
|
|
@@ -8728,7 +9182,7 @@ var FileAuditReplayStore = class {
|
|
|
8728
9182
|
await mkdir(directory, { recursive: true, mode: 448 });
|
|
8729
9183
|
const temporary = join5(
|
|
8730
9184
|
directory,
|
|
8731
|
-
`.${
|
|
9185
|
+
`.${basename7(path)}.${process.pid}.${randomUUID()}.tmp`
|
|
8732
9186
|
);
|
|
8733
9187
|
try {
|
|
8734
9188
|
await writeFile(temporary, body, { mode: 384, flag: "wx" });
|
|
@@ -8796,7 +9250,7 @@ var FileAuditReplayStore = class {
|
|
|
8796
9250
|
}
|
|
8797
9251
|
async readReplay(manifest) {
|
|
8798
9252
|
const path = this.resolveStoredPath(manifest.replayPath);
|
|
8799
|
-
const bytes = await
|
|
9253
|
+
const bytes = await readFile7(path);
|
|
8800
9254
|
if (sha256(bytes) !== manifest.replaySha256) {
|
|
8801
9255
|
throw new Error("Audit replay document hash mismatch");
|
|
8802
9256
|
}
|
|
@@ -8860,7 +9314,7 @@ function encodeJson(value) {
|
|
|
8860
9314
|
`, "utf8");
|
|
8861
9315
|
}
|
|
8862
9316
|
function sha256(value) {
|
|
8863
|
-
return
|
|
9317
|
+
return createHash4("sha256").update(value).digest("hex");
|
|
8864
9318
|
}
|
|
8865
9319
|
function idKey(id) {
|
|
8866
9320
|
return sha256(Buffer.from(id, "utf8"));
|
|
@@ -8876,7 +9330,7 @@ async function pathExists(path) {
|
|
|
8876
9330
|
}
|
|
8877
9331
|
async function readDirectory(path) {
|
|
8878
9332
|
try {
|
|
8879
|
-
return await
|
|
9333
|
+
return await readdir5(path);
|
|
8880
9334
|
} catch (error) {
|
|
8881
9335
|
if (isNotFound(error)) return [];
|
|
8882
9336
|
throw error;
|
|
@@ -8884,7 +9338,7 @@ async function readDirectory(path) {
|
|
|
8884
9338
|
}
|
|
8885
9339
|
async function readJsonIfPresent(path) {
|
|
8886
9340
|
try {
|
|
8887
|
-
return JSON.parse(await
|
|
9341
|
+
return JSON.parse(await readFile7(path, "utf8"));
|
|
8888
9342
|
} catch (error) {
|
|
8889
9343
|
if (isNotFound(error)) return void 0;
|
|
8890
9344
|
throw error;
|
|
@@ -8897,12 +9351,12 @@ function isNotFound(error) {
|
|
|
8897
9351
|
// src/audit/worker/audit-recorder-ipc-protocol.ts
|
|
8898
9352
|
var AUDIT_RECORDER_PROTOCOL_VERSION = 3;
|
|
8899
9353
|
function isAuditRecorderParentMessage(value) {
|
|
8900
|
-
if (!
|
|
9354
|
+
if (!isRecord16(value) || typeof value.type !== "string") return false;
|
|
8901
9355
|
switch (value.type) {
|
|
8902
9356
|
case "audit_recorder_initialize":
|
|
8903
9357
|
return value.protocolVersion === AUDIT_RECORDER_PROTOCOL_VERSION && isProcessConfig(value.config);
|
|
8904
9358
|
case "audit_recorder_job":
|
|
8905
|
-
return typeof value.deliveryId === "string" &&
|
|
9359
|
+
return typeof value.deliveryId === "string" && isRecord16(value.job);
|
|
8906
9360
|
case "audit_recorder_flush":
|
|
8907
9361
|
case "audit_recorder_stop":
|
|
8908
9362
|
return typeof value.requestId === "string";
|
|
@@ -8911,10 +9365,10 @@ function isAuditRecorderParentMessage(value) {
|
|
|
8911
9365
|
}
|
|
8912
9366
|
}
|
|
8913
9367
|
function isProcessConfig(value) {
|
|
8914
|
-
if (!
|
|
9368
|
+
if (!isRecord16(value)) return false;
|
|
8915
9369
|
return typeof value.storageRootDir === "string" && (value.maxWorkerQueueSize === void 0 || typeof value.maxWorkerQueueSize === "number" && Number.isSafeInteger(value.maxWorkerQueueSize) && value.maxWorkerQueueSize > 0);
|
|
8916
9370
|
}
|
|
8917
|
-
function
|
|
9371
|
+
function isRecord16(value) {
|
|
8918
9372
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8919
9373
|
}
|
|
8920
9374
|
|
|
@@ -9067,6 +9521,7 @@ function createJobFinalizer(config) {
|
|
|
9067
9521
|
registry.register(new CursorAuditAdapter());
|
|
9068
9522
|
registry.register(new OpenCodeAuditAdapter());
|
|
9069
9523
|
registry.register(new DeepSeekHarnessAuditAdapter());
|
|
9524
|
+
registry.register(new AgyAuditAdapter());
|
|
9070
9525
|
registry.register(new OpenClawAuditAdapter());
|
|
9071
9526
|
return {
|
|
9072
9527
|
finalizer: new ReplayFinalizer(registry, store),
|