bazilion 0.17.0 → 0.18.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/cli.js +336 -67
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +1770 -151
- package/dist/daemon.js.map +1 -1
- package/dist/migrations/0001_init.sql +107 -0
- package/dist/web/client/assets/{ChatPane-BI3QVX2A.js → ChatPane-CAYS_fIQ.js} +1 -1
- package/dist/web/client/assets/ConfirmDialog-BzIiABOP.js +1 -0
- package/dist/web/client/assets/{FieldRow-swJ5qn2h.js → FieldRow-W_54rw5c.js} +1 -1
- package/dist/web/client/assets/{ProductionTeamPolicyEditor-LGw1UuF-.js → ProductionTeamPolicyEditor-DNXVX8Lz.js} +2 -2
- package/dist/web/client/assets/{ProfileCommunicationEditor-raoau_YB.js → ProfileCommunicationEditor-DN0fOzqn.js} +1 -1
- package/dist/web/client/assets/{ResultSourceConversation-BEwkhFog.js → ResultSourceConversation-DoU4tOWc.js} +1 -1
- package/dist/web/client/assets/TeamTabs-BmTZRI4T.js +1 -0
- package/dist/web/client/assets/{TemplatesTabs-BX5hhEJ7.js → TemplatesTabs-Bs_OXKwx.js} +1 -1
- package/dist/web/client/assets/{UnsavedChangesGuard-CVJtmR1D.js → UnsavedChangesGuard-CPRtFReU.js} +1 -1
- package/dist/web/client/assets/{_id-DmEVZIlx.js → _id-CxAB4TDr.js} +1 -1
- package/dist/web/client/assets/{_id-DHqq2W34.js → _id-DL4tJFQB.js} +1 -1
- package/dist/web/client/assets/{_id-BQPOE3gj.js → _id-DR9eFC17.js} +1 -1
- package/dist/web/client/assets/{_id-BkYrUP0R.js → _id-Dbmei5tg.js} +1 -1
- package/dist/web/client/assets/{_id-CriixlZD.js → _id-ybF-pqmr.js} +1 -1
- package/dist/web/client/assets/{activity-Bzr8R18n.js → activity-oUyy77jD.js} +1 -1
- package/dist/web/client/assets/{agents-13oafeOA.js → agents-D_TrEqAg.js} +1 -1
- package/dist/web/client/assets/{agents-DF4NALmJ.js → agents-DkjJp7JP.js} +1 -1
- package/dist/web/client/assets/{approvals-DsG0Ijls.js → approvals-DhOerWdt.js} +1 -1
- package/dist/web/client/assets/{attention-DG7K25mz.js → attention-DGwiF-Jy.js} +1 -1
- package/dist/web/client/assets/chevron-right-DSa4xPTs.js +1 -0
- package/dist/web/client/assets/{config-DAaDbFhS.js → config-BJ2ZzHPR.js} +1 -1
- package/dist/web/client/assets/{inbox-C9e7QjsX.js → inbox-BUElnGep.js} +1 -1
- package/dist/web/client/assets/{index-Dsstm2hf.js → index-Bi-HxcPG.js} +2 -2
- package/dist/web/client/assets/{learning-23arTd21.js → learning-BiTHNwB3.js} +1 -1
- package/dist/web/client/assets/login-BmcZvAH2.js +1 -0
- package/dist/web/client/assets/{mcp-Cdx9qAl8.js → mcp-Cwk9V82W.js} +1 -1
- package/dist/web/client/assets/{members-fotOz4rR.js → members-CHDNabFh.js} +1 -1
- package/dist/web/client/assets/{memory-C7UznVot.js → memory-Cx_Fpd4e.js} +1 -1
- package/dist/web/client/assets/{policy-CactLW1X.js → policy-C0nMdwcG.js} +1 -1
- package/dist/web/client/assets/{results-DqEuYnQH.js → results-Bz3jASs-.js} +1 -1
- package/dist/web/client/assets/{review-CnBSYclb.js → review-AK9WGmpv.js} +1 -1
- package/dist/web/client/assets/routes-DsMY_6oy.js +1 -0
- package/dist/web/client/assets/{services-xEANwZAu.js → services-DItA6fJ7.js} +1 -1
- package/dist/web/client/assets/{skills-CamV6wYM.js → skills-DbNV2vgL.js} +1 -1
- package/dist/web/client/assets/{teams-B12dMSjW.js → teams-D83scDxw.js} +1 -1
- package/dist/web/client/assets/{teams-CbH43zSG.js → teams-DAny1ypN.js} +1 -1
- package/dist/web/client/assets/{telegram-muIql4u-.js → telegram-BOmf9vUh.js} +1 -1
- package/dist/web/client/assets/{tokens-DGFmApdF.js → tokens-DBGH6Bw5.js} +1 -1
- package/dist/web/client/assets/{triggers-D8n3sCBW.js → triggers-D1_pseI3.js} +1 -1
- package/dist/web/client/assets/verifications-CBTo-FyV.js +2 -0
- package/dist/web/client/assets/{welcome-CMHWRZhs.js → welcome-DAfPOm15.js} +1 -1
- package/dist/web/client/assets/{x-BGCHwZOH.js → x-CWY-gUaM.js} +1 -1
- package/dist/web/server/assets/{TeamTabs-DQXh-3ij.js → TeamTabs-Dg4v6x0-.js} +4 -0
- package/dist/web/server/assets/{_id-DDyA9CGX.js → _id--onriuvj.js} +1 -1
- package/dist/web/server/assets/{_id-XkxlX036.js → _id--zoh1vv7.js} +1 -1
- package/dist/web/server/assets/{_id-Dw3gKOGv.js → _id-6p-mDmI8.js} +1 -1
- package/dist/web/server/assets/{_id-CPfILjMa.js → _id-DptBl3X8.js} +1 -1
- package/dist/web/server/assets/{_id-DtJn-yzu.js → _id-EAjRXNbD.js} +2 -2
- package/dist/web/server/assets/{_id-DSPFJMzf.js → _id-dUnXL-My2.js} +1 -1
- package/dist/web/server/assets/{_tanstack-start-manifest_v-vOXRfKJD.js → _tanstack-start-manifest_v-B3M-dfRO.js} +90 -79
- package/dist/web/server/assets/{activity-pYQPT3QT.js → activity-C5jpoEQI.js} +1 -1
- package/dist/web/server/assets/{activity-BX1jZBPQ.js → activity-Cu7zKPGD.js} +1 -1
- package/dist/web/server/assets/{activity-bozPMU2v.js → activity-Dn50vkQP.js} +2 -2
- package/dist/web/server/assets/{agents-BKBfW700.js → agents-RE6aYOb-.js} +1 -1
- package/dist/web/server/assets/{agents-CVCfxnE2.js → agents-nAOx_H7s.js} +1 -1
- package/dist/web/server/assets/{approvals-C3ya6B6U.js → approvals-DhHxIDrL.js} +1 -1
- package/dist/web/server/assets/{attention-l28hGCHS.js → attention-CBWzWRni.js} +1 -1
- package/dist/web/server/assets/{auth-AvDFNeOv.js → auth-tB3i6cFd.js} +1 -1
- package/dist/web/server/assets/{config-BWKn4XII.js → config-D1k_tTAw.js} +1 -1
- package/dist/web/server/assets/{daemon-client-Cgx-YW4l.js → daemon-client-C7qjQ2iO.js} +15 -0
- package/dist/web/server/assets/{git-review-f_uta4Mx.js → git-review-Bf5ABFJg.js} +1 -1
- package/dist/web/server/assets/{inbox-BBZiOOQs.js → inbox-Dw4pTevh.js} +1 -1
- package/dist/web/server/assets/{learning-CheVay1i.js → learning-CF8ZzFVD.js} +1 -1
- package/dist/web/server/assets/{mcp-DCBDmNtQ.js → mcp-D5dmBT82.js} +1 -1
- package/dist/web/server/assets/{members-C5FQruRZ.js → members-Bd0OtiTr.js} +1 -1
- package/dist/web/server/assets/{members-C2He8mrU.js → members-CvwEN9pm.js} +1 -1
- package/dist/web/server/assets/{members-C_2xB9pr.js → members-xSXoYUOd.js} +2 -2
- package/dist/web/server/assets/{memory-rmiFNj7T.js → memory-CcPK7um7.js} +1 -1
- package/dist/web/server/assets/{memory-BTcmf0sD.js → memory-UP6AsRkO.js} +2 -2
- package/dist/web/server/assets/{memory-4tI-UbOf.js → memory-lo2vHRNw.js} +1 -1
- package/dist/web/server/assets/{policy-C3D2Q1EA.js → policy-B62WXIFo.js} +1 -1
- package/dist/web/server/assets/{policy-BGILKGHz.js → policy-Bze9Krhg.js} +2 -2
- package/dist/web/server/assets/{policy-DS7LGe--.js → policy-Dh6wd2wN.js} +1 -1
- package/dist/web/server/assets/{results-_6K_zXQS.js → results-BFqs2iOu.js} +1 -1
- package/dist/web/server/assets/{results-C6H42tjq.js → results-BWnu3gXP.js} +1 -1
- package/dist/web/server/assets/{results-Cgx7SrFt.js → results-CzZk50Fu.js} +2 -2
- package/dist/web/server/assets/{review-DHhiL-JQ.js → review-DUe3vHPU.js} +2 -2
- package/dist/web/server/assets/{review-DSTMCwP4.js → review-c_-cFi7H.js} +1 -1
- package/dist/web/server/assets/{router-ElARvZzI.js → router-Deq94UJQ.js} +33 -26
- package/dist/web/server/assets/{routes-BgMvLvS-.js → routes-CVKkvFVv.js} +1 -1
- package/dist/web/server/assets/{services-yHZroxsi.js → services-CEr61xb5.js} +1 -1
- package/dist/web/server/assets/{skills--bIKID1Q.js → skills-BImC3LTO.js} +1 -1
- package/dist/web/server/assets/{teams-BbRfuVXY.js → teams-8zEIo08E.js} +1 -1
- package/dist/web/server/assets/{teams--a956vWL.js → teams-D-yaAWLV.js} +1 -1
- package/dist/web/server/assets/{telegram-4kMxRtVZ.js → telegram-CGl_LFtJ.js} +1 -1
- package/dist/web/server/assets/{tokens-BYwTN9JZ.js → tokens-cB-uf7qm.js} +1 -1
- package/dist/web/server/assets/{triggers-BM6mzLuH.js → triggers-CtSj79L0.js} +1 -1
- package/dist/web/server/assets/verification-B5QjcpIo.js +97 -0
- package/dist/web/server/assets/verifications-BfQsfwSE.js +268 -0
- package/dist/web/server/assets/verifications-CUq_6ZqL.js +26 -0
- package/dist/web/server/server.js +51 -35
- package/dist/worker.js +178 -4
- package/dist/worker.js.map +1 -1
- package/package.json +3 -3
- package/dist/web/client/assets/ConfirmDialog-Qam6Ut08.js +0 -1
- package/dist/web/client/assets/TeamTabs-BDdTLGIf.js +0 -1
- package/dist/web/client/assets/chevron-right-DFqFHtLy.js +0 -1
- package/dist/web/client/assets/login-BIXnBsuj.js +0 -1
- package/dist/web/client/assets/routes-COxMuwVz.js +0 -1
package/dist/daemon.js
CHANGED
|
@@ -21833,6 +21833,7 @@ __export(communicationApprovals_exports, {
|
|
|
21833
21833
|
get: () => get9,
|
|
21834
21834
|
getByAttempt: () => getByAttempt,
|
|
21835
21835
|
grantSchedulerTrigger: () => grantSchedulerTrigger,
|
|
21836
|
+
grantVerificationRequest: () => grantVerificationRequest,
|
|
21836
21837
|
list: () => list6,
|
|
21837
21838
|
request: () => request
|
|
21838
21839
|
});
|
|
@@ -22093,6 +22094,29 @@ function claimDelivery(db, id, actor, revalidate, now = Date.now()) {
|
|
|
22093
22094
|
return outcome.detail;
|
|
22094
22095
|
}
|
|
22095
22096
|
function grantSchedulerTrigger(db, id, actor, revalidate, validateDelivery, now = Date.now()) {
|
|
22097
|
+
return grantDurableApproval(
|
|
22098
|
+
db,
|
|
22099
|
+
id,
|
|
22100
|
+
actor,
|
|
22101
|
+
{ operation: "scheduler_trigger", payloadKind: "scheduler_trigger" },
|
|
22102
|
+
revalidate,
|
|
22103
|
+
validateDelivery,
|
|
22104
|
+
now
|
|
22105
|
+
);
|
|
22106
|
+
}
|
|
22107
|
+
function grantVerificationRequest(db, id, actor, revalidate, validateDelivery, onGranted, now = Date.now()) {
|
|
22108
|
+
return grantDurableApproval(
|
|
22109
|
+
db,
|
|
22110
|
+
id,
|
|
22111
|
+
actor,
|
|
22112
|
+
{ operation: "request_verification", payloadKind: "verification_request" },
|
|
22113
|
+
revalidate,
|
|
22114
|
+
validateDelivery,
|
|
22115
|
+
now,
|
|
22116
|
+
onGranted
|
|
22117
|
+
);
|
|
22118
|
+
}
|
|
22119
|
+
function grantDurableApproval(db, id, actor, expected, revalidate, validateDelivery, now, onGranted) {
|
|
22096
22120
|
expirePending(db, now);
|
|
22097
22121
|
return db.raw.transaction(() => {
|
|
22098
22122
|
const current = raw(db, id);
|
|
@@ -22100,8 +22124,10 @@ function grantSchedulerTrigger(db, id, actor, revalidate, validateDelivery, now
|
|
|
22100
22124
|
const detail3 = detailFromRow(db, current);
|
|
22101
22125
|
if (detail3.status !== "pending")
|
|
22102
22126
|
throw new Error(`approval_state_conflict: current ${detail3.status}`);
|
|
22103
|
-
if (detail3.operation !==
|
|
22104
|
-
throw new Error(
|
|
22127
|
+
if (detail3.operation !== expected.operation || detail3.payloadKind !== expected.payloadKind) {
|
|
22128
|
+
throw new Error(
|
|
22129
|
+
`approval_payload_conflict: not a ${expected.operation}/${expected.payloadKind} approval`
|
|
22130
|
+
);
|
|
22105
22131
|
}
|
|
22106
22132
|
const authorization = revalidate(detail3);
|
|
22107
22133
|
const refsMatch = JSON.stringify(authorization.policyRefs) === JSON.stringify(detail3.policyRefs) && JSON.stringify(authorization.requiredEdgeIds) === JSON.stringify(detail3.requiredEdgeIds);
|
|
@@ -22154,6 +22180,7 @@ function grantSchedulerTrigger(db, id, actor, revalidate, validateDelivery, now
|
|
|
22154
22180
|
[now, actor, now, id]
|
|
22155
22181
|
).changes;
|
|
22156
22182
|
if (changed !== 1) throw new Error("approval_state_conflict: concurrent approval");
|
|
22183
|
+
onGranted?.(detail3);
|
|
22157
22184
|
appendEvent(db, id, "approved", actor, null, now);
|
|
22158
22185
|
appendEvent(db, id, "delivery_started", actor, null, now);
|
|
22159
22186
|
appendEvent(db, id, "delivered", actor, null, now);
|
|
@@ -25957,6 +25984,356 @@ function approvalReference(db, agentId, id) {
|
|
|
25957
25984
|
return { agentId, itemId: id, inputDigest: row.input_digest };
|
|
25958
25985
|
}
|
|
25959
25986
|
|
|
25987
|
+
// ../daemon/src/core/repos/verification-requests.ts
|
|
25988
|
+
import { randomUUID as randomUUID21 } from "crypto";
|
|
25989
|
+
var VERIFICATION_REQUEST_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
25990
|
+
var VERIFICATION_MAX_CHECKS = 8;
|
|
25991
|
+
var VERIFICATION_LIMITS = {
|
|
25992
|
+
command: 2e3,
|
|
25993
|
+
cwd: 1e3,
|
|
25994
|
+
purpose: 500,
|
|
25995
|
+
summary: 2e3,
|
|
25996
|
+
error: 2e3,
|
|
25997
|
+
minTimeoutMs: 1e3,
|
|
25998
|
+
maxTimeoutMs: 3e5
|
|
25999
|
+
};
|
|
26000
|
+
var VERIFICATION_TERMINAL_REQUEST_STATES = [
|
|
26001
|
+
"completed",
|
|
26002
|
+
"failed",
|
|
26003
|
+
"cancelled",
|
|
26004
|
+
"uncertain"
|
|
26005
|
+
];
|
|
26006
|
+
var REQUEST_COLUMNS = "id, team_id, requester_kind, requester_agent_id, recipient_agent_id, message_id, source_session_id, snapshot_id, snapshot_complete, head, base_oid, environment_json, summary, state, created_at, expires_at";
|
|
26007
|
+
var CHECK_COLUMNS = "request_id, ordinal, command, cwd, purpose, timeout_ms";
|
|
26008
|
+
var OUTCOME_COLUMNS = "attempt_id, ordinal, state, command_id, exit_code, started_at, finished_at";
|
|
26009
|
+
var ATTEMPT_COLUMNS = "id, request_id, attempt_number, supersedes_attempt_id, state, lease_owner, lease_expires_at, started_at, finished_at, error, created_at";
|
|
26010
|
+
function toRequest(row) {
|
|
26011
|
+
return {
|
|
26012
|
+
id: row.id,
|
|
26013
|
+
teamId: row.team_id,
|
|
26014
|
+
requesterKind: row.requester_kind === "agent" ? "agent" : "operator",
|
|
26015
|
+
requesterAgentId: row.requester_agent_id,
|
|
26016
|
+
recipientAgentId: row.recipient_agent_id,
|
|
26017
|
+
messageId: row.message_id,
|
|
26018
|
+
sourceSessionId: row.source_session_id,
|
|
26019
|
+
snapshotId: row.snapshot_id,
|
|
26020
|
+
snapshotComplete: row.snapshot_complete === 1,
|
|
26021
|
+
head: row.head,
|
|
26022
|
+
baseOid: row.base_oid,
|
|
26023
|
+
environment: JSON.parse(row.environment_json),
|
|
26024
|
+
summary: row.summary,
|
|
26025
|
+
state: row.state,
|
|
26026
|
+
createdAt: row.created_at,
|
|
26027
|
+
expiresAt: row.expires_at
|
|
26028
|
+
};
|
|
26029
|
+
}
|
|
26030
|
+
function toCheck(row) {
|
|
26031
|
+
return {
|
|
26032
|
+
requestId: row.request_id,
|
|
26033
|
+
ordinal: row.ordinal,
|
|
26034
|
+
command: row.command,
|
|
26035
|
+
cwd: row.cwd,
|
|
26036
|
+
purpose: row.purpose,
|
|
26037
|
+
timeoutMs: row.timeout_ms
|
|
26038
|
+
};
|
|
26039
|
+
}
|
|
26040
|
+
function toOutcome(row) {
|
|
26041
|
+
return {
|
|
26042
|
+
attemptId: row.attempt_id,
|
|
26043
|
+
ordinal: row.ordinal,
|
|
26044
|
+
state: row.state,
|
|
26045
|
+
commandId: row.command_id,
|
|
26046
|
+
exitCode: row.exit_code,
|
|
26047
|
+
startedAt: row.started_at,
|
|
26048
|
+
finishedAt: row.finished_at
|
|
26049
|
+
};
|
|
26050
|
+
}
|
|
26051
|
+
function toAttempt(row) {
|
|
26052
|
+
return {
|
|
26053
|
+
id: row.id,
|
|
26054
|
+
requestId: row.request_id,
|
|
26055
|
+
attemptNumber: row.attempt_number,
|
|
26056
|
+
supersedesAttemptId: row.supersedes_attempt_id,
|
|
26057
|
+
state: row.state,
|
|
26058
|
+
leaseOwner: row.lease_owner,
|
|
26059
|
+
leaseExpiresAt: row.lease_expires_at,
|
|
26060
|
+
startedAt: row.started_at,
|
|
26061
|
+
finishedAt: row.finished_at,
|
|
26062
|
+
error: row.error,
|
|
26063
|
+
createdAt: row.created_at
|
|
26064
|
+
};
|
|
26065
|
+
}
|
|
26066
|
+
var VerificationRequestError = class extends Error {
|
|
26067
|
+
status = 400;
|
|
26068
|
+
};
|
|
26069
|
+
function createVerificationRequest(db, input) {
|
|
26070
|
+
const now = input.now ?? Date.now();
|
|
26071
|
+
const id = input.id ?? randomUUID21();
|
|
26072
|
+
if (input.checks.length < 1)
|
|
26073
|
+
throw new VerificationRequestError("a request needs at least one check");
|
|
26074
|
+
if (input.checks.length > VERIFICATION_MAX_CHECKS) {
|
|
26075
|
+
throw new VerificationRequestError(
|
|
26076
|
+
`a request captures at most ${VERIFICATION_MAX_CHECKS} checks`
|
|
26077
|
+
);
|
|
26078
|
+
}
|
|
26079
|
+
for (const check of input.checks) validateCheck(check);
|
|
26080
|
+
validateEnvironment(input.environment);
|
|
26081
|
+
if (input.summary != null) {
|
|
26082
|
+
if (!input.summary.trim()) throw new VerificationRequestError("a summary must not be empty");
|
|
26083
|
+
assertLength(input.summary, VERIFICATION_LIMITS.summary, "summary");
|
|
26084
|
+
}
|
|
26085
|
+
if (!input.snapshotId)
|
|
26086
|
+
throw new VerificationRequestError("a request requires a captured snapshot");
|
|
26087
|
+
if (!input.baseOid) throw new VerificationRequestError("a request requires a captured base");
|
|
26088
|
+
if (input.requesterKind === "agent") {
|
|
26089
|
+
if (!input.requesterAgentId)
|
|
26090
|
+
throw new VerificationRequestError("an Agent request names its requester");
|
|
26091
|
+
if (input.requesterAgentId === input.recipientAgentId) {
|
|
26092
|
+
throw new VerificationRequestError("a specialist cannot verify its own request");
|
|
26093
|
+
}
|
|
26094
|
+
} else if (input.requesterAgentId) {
|
|
26095
|
+
throw new VerificationRequestError("an operator request has no requester Agent");
|
|
26096
|
+
}
|
|
26097
|
+
return inTx(db, () => {
|
|
26098
|
+
db.raw.run(
|
|
26099
|
+
`INSERT INTO verification_requests (${REQUEST_COLUMNS})
|
|
26100
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'pending', ?, ?)`,
|
|
26101
|
+
[
|
|
26102
|
+
id,
|
|
26103
|
+
input.teamId,
|
|
26104
|
+
input.requesterKind,
|
|
26105
|
+
input.requesterAgentId,
|
|
26106
|
+
input.recipientAgentId,
|
|
26107
|
+
input.messageId ?? null,
|
|
26108
|
+
input.sourceSessionId ?? null,
|
|
26109
|
+
input.snapshotId,
|
|
26110
|
+
input.snapshotComplete ? 1 : 0,
|
|
26111
|
+
input.head,
|
|
26112
|
+
input.baseOid,
|
|
26113
|
+
JSON.stringify(input.environment),
|
|
26114
|
+
input.summary ?? null,
|
|
26115
|
+
now,
|
|
26116
|
+
now + VERIFICATION_REQUEST_TTL_MS
|
|
26117
|
+
]
|
|
26118
|
+
);
|
|
26119
|
+
input.checks.forEach((check, ordinal) => {
|
|
26120
|
+
db.raw.run(
|
|
26121
|
+
`INSERT INTO verification_checks (request_id, ordinal, command, cwd, purpose, timeout_ms)
|
|
26122
|
+
VALUES (?, ?, ?, ?, ?, ?)`,
|
|
26123
|
+
[id, ordinal, check.command, check.cwd, check.purpose, check.timeoutMs]
|
|
26124
|
+
);
|
|
26125
|
+
});
|
|
26126
|
+
const request2 = getVerificationRequest(db, input.teamId, id, now);
|
|
26127
|
+
if (!request2) throw new VerificationRequestError("request was not stored");
|
|
26128
|
+
return request2;
|
|
26129
|
+
});
|
|
26130
|
+
}
|
|
26131
|
+
function getVerificationRequest(db, teamId, id, now = Date.now()) {
|
|
26132
|
+
const row = db.raw.query(
|
|
26133
|
+
`SELECT ${REQUEST_COLUMNS} FROM verification_requests
|
|
26134
|
+
WHERE team_id = ? AND id = ? AND expires_at > ?`
|
|
26135
|
+
).get(teamId, id, now);
|
|
26136
|
+
return row ? toRequest(row) : null;
|
|
26137
|
+
}
|
|
26138
|
+
function getVerificationRequestById(db, id, now = Date.now()) {
|
|
26139
|
+
const row = db.raw.query(
|
|
26140
|
+
`SELECT ${REQUEST_COLUMNS} FROM verification_requests WHERE id = ? AND expires_at > ?`
|
|
26141
|
+
).get(id, now);
|
|
26142
|
+
return row ? toRequest(row) : null;
|
|
26143
|
+
}
|
|
26144
|
+
function listVerificationRequests(db, teamId, limit = 50, now = Date.now()) {
|
|
26145
|
+
return db.raw.query(
|
|
26146
|
+
`SELECT ${REQUEST_COLUMNS} FROM verification_requests
|
|
26147
|
+
WHERE team_id = ? AND expires_at > ?
|
|
26148
|
+
ORDER BY created_at DESC, id LIMIT ?`
|
|
26149
|
+
).all(teamId, now, limit).map(toRequest);
|
|
26150
|
+
}
|
|
26151
|
+
function listVerificationChecks(db, requestId2) {
|
|
26152
|
+
return db.raw.query(
|
|
26153
|
+
`SELECT ${CHECK_COLUMNS} FROM verification_checks WHERE request_id = ? ORDER BY ordinal`
|
|
26154
|
+
).all(requestId2).map(toCheck);
|
|
26155
|
+
}
|
|
26156
|
+
function listVerificationCheckOutcomes(db, attemptId) {
|
|
26157
|
+
return db.raw.query(
|
|
26158
|
+
`SELECT ${OUTCOME_COLUMNS} FROM verification_check_outcomes WHERE attempt_id = ?
|
|
26159
|
+
ORDER BY ordinal`
|
|
26160
|
+
).all(attemptId).map(toOutcome);
|
|
26161
|
+
}
|
|
26162
|
+
function listVerificationAttempts(db, requestId2) {
|
|
26163
|
+
return db.raw.query(
|
|
26164
|
+
`SELECT ${ATTEMPT_COLUMNS} FROM verification_attempts WHERE request_id = ?
|
|
26165
|
+
ORDER BY attempt_number`
|
|
26166
|
+
).all(requestId2).map(toAttempt);
|
|
26167
|
+
}
|
|
26168
|
+
function claimVerificationAttempt(db, input) {
|
|
26169
|
+
const now = input.now ?? Date.now();
|
|
26170
|
+
if (!input.leaseOwner) throw new VerificationRequestError("a claim requires an owner");
|
|
26171
|
+
if (input.leaseMs <= 0) throw new VerificationRequestError("a claim requires a positive lease");
|
|
26172
|
+
return inTx(db, () => {
|
|
26173
|
+
const row = db.raw.query(
|
|
26174
|
+
`SELECT ${REQUEST_COLUMNS} FROM verification_requests WHERE id = ? AND expires_at > ?`
|
|
26175
|
+
).get(input.requestId, now);
|
|
26176
|
+
if (!row) return null;
|
|
26177
|
+
const request2 = toRequest(row);
|
|
26178
|
+
const terminal = VERIFICATION_TERMINAL_REQUEST_STATES.includes(request2.state);
|
|
26179
|
+
if (!terminal && request2.state !== "pending") return null;
|
|
26180
|
+
if (terminal && !input.rerun) return null;
|
|
26181
|
+
const open = db.raw.query(
|
|
26182
|
+
"SELECT id FROM verification_attempts WHERE request_id = ? AND finished_at IS NULL"
|
|
26183
|
+
).get(input.requestId);
|
|
26184
|
+
if (open) return null;
|
|
26185
|
+
const previous = db.raw.query(
|
|
26186
|
+
`SELECT id, attempt_number FROM verification_attempts WHERE request_id = ?
|
|
26187
|
+
ORDER BY attempt_number DESC LIMIT 1`
|
|
26188
|
+
).get(input.requestId);
|
|
26189
|
+
const attemptId = randomUUID21();
|
|
26190
|
+
db.raw.run(
|
|
26191
|
+
`INSERT INTO verification_attempts
|
|
26192
|
+
(id, request_id, attempt_number, supersedes_attempt_id, state, lease_owner,
|
|
26193
|
+
lease_expires_at, created_at)
|
|
26194
|
+
VALUES (?, ?, ?, ?, 'claimed', ?, ?, ?)`,
|
|
26195
|
+
[
|
|
26196
|
+
attemptId,
|
|
26197
|
+
input.requestId,
|
|
26198
|
+
(previous?.attempt_number ?? 0) + 1,
|
|
26199
|
+
previous?.id ?? null,
|
|
26200
|
+
input.leaseOwner,
|
|
26201
|
+
now + input.leaseMs,
|
|
26202
|
+
now
|
|
26203
|
+
]
|
|
26204
|
+
);
|
|
26205
|
+
db.raw.run(
|
|
26206
|
+
`INSERT INTO verification_check_outcomes (attempt_id, ordinal, state)
|
|
26207
|
+
SELECT ?, ordinal, 'not_executed' FROM verification_checks WHERE request_id = ?`,
|
|
26208
|
+
[attemptId, input.requestId]
|
|
26209
|
+
);
|
|
26210
|
+
setRequestState(db, input.requestId, "running");
|
|
26211
|
+
const attempt = db.raw.query(
|
|
26212
|
+
`SELECT ${ATTEMPT_COLUMNS} FROM verification_attempts WHERE id = ?`
|
|
26213
|
+
).get(attemptId);
|
|
26214
|
+
if (!attempt) throw new VerificationRequestError("attempt was not stored");
|
|
26215
|
+
return { attempt: toAttempt(attempt), state: "running" };
|
|
26216
|
+
});
|
|
26217
|
+
}
|
|
26218
|
+
function finishVerificationAttempt(db, input) {
|
|
26219
|
+
const now = input.now ?? Date.now();
|
|
26220
|
+
if (input.error != null) assertLength(input.error, VERIFICATION_LIMITS.error, "error");
|
|
26221
|
+
return inTx(db, () => {
|
|
26222
|
+
const row = db.raw.query(
|
|
26223
|
+
`SELECT ${ATTEMPT_COLUMNS} FROM verification_attempts WHERE id = ? AND lease_owner = ?`
|
|
26224
|
+
).get(input.attemptId, input.leaseOwner);
|
|
26225
|
+
if (!row) return false;
|
|
26226
|
+
const attempt = toAttempt(row);
|
|
26227
|
+
if (attempt.finishedAt !== null) return false;
|
|
26228
|
+
db.raw.run(
|
|
26229
|
+
`UPDATE verification_attempts
|
|
26230
|
+
SET state = ?, finished_at = ?, lease_owner = NULL, lease_expires_at = NULL, error = ?
|
|
26231
|
+
WHERE id = ?`,
|
|
26232
|
+
[input.state, now, input.error ?? null, input.attemptId]
|
|
26233
|
+
);
|
|
26234
|
+
setRequestState(db, attempt.requestId, input.state === "uncertain" ? "uncertain" : input.state);
|
|
26235
|
+
return true;
|
|
26236
|
+
});
|
|
26237
|
+
}
|
|
26238
|
+
function setRequestState(db, requestId2, state3) {
|
|
26239
|
+
db.raw.run("UPDATE verification_requests SET state = ? WHERE id = ?", [state3, requestId2]);
|
|
26240
|
+
}
|
|
26241
|
+
function recordVerificationCheckOutcome(db, input) {
|
|
26242
|
+
if (input.state === "not_executed") {
|
|
26243
|
+
throw new VerificationRequestError("a settled outcome cannot return to not_executed");
|
|
26244
|
+
}
|
|
26245
|
+
const executed = ["succeeded", "failed", "timed_out", "cancelled"].includes(input.state);
|
|
26246
|
+
if (executed && !input.commandId) {
|
|
26247
|
+
throw new VerificationRequestError(`${input.state} requires the receipt that produced it`);
|
|
26248
|
+
}
|
|
26249
|
+
if (!executed && input.commandId) {
|
|
26250
|
+
throw new VerificationRequestError(`${input.state} cannot claim a command receipt`);
|
|
26251
|
+
}
|
|
26252
|
+
if (input.exitCode != null && input.state !== "succeeded" && input.state !== "failed") {
|
|
26253
|
+
throw new VerificationRequestError("only an executed check records an exit code");
|
|
26254
|
+
}
|
|
26255
|
+
const attempt = db.raw.query(
|
|
26256
|
+
"SELECT request_id FROM verification_attempts WHERE id = ?"
|
|
26257
|
+
).get(input.attemptId);
|
|
26258
|
+
if (!attempt) return false;
|
|
26259
|
+
const result = db.raw.run(
|
|
26260
|
+
`UPDATE verification_check_outcomes
|
|
26261
|
+
SET state = ?, command_id = ?, exit_code = ?, started_at = ?, finished_at = ?
|
|
26262
|
+
WHERE attempt_id = ? AND ordinal = ? AND state = 'not_executed'
|
|
26263
|
+
AND EXISTS (SELECT 1 FROM verification_checks
|
|
26264
|
+
WHERE request_id = ? AND ordinal = ?)`,
|
|
26265
|
+
[
|
|
26266
|
+
input.state,
|
|
26267
|
+
input.commandId ?? null,
|
|
26268
|
+
input.exitCode ?? null,
|
|
26269
|
+
input.startedAt ?? null,
|
|
26270
|
+
input.finishedAt ?? Date.now(),
|
|
26271
|
+
input.attemptId,
|
|
26272
|
+
input.ordinal,
|
|
26273
|
+
attempt.request_id,
|
|
26274
|
+
input.ordinal
|
|
26275
|
+
]
|
|
26276
|
+
);
|
|
26277
|
+
return Number(result.changes) === 1;
|
|
26278
|
+
}
|
|
26279
|
+
function recoverInterruptedVerificationAttempts(db, daemonIdentity, now = Date.now()) {
|
|
26280
|
+
return inTx(db, () => {
|
|
26281
|
+
const rows = db.raw.query(
|
|
26282
|
+
`SELECT id, request_id, lease_owner FROM verification_attempts WHERE finished_at IS NULL`
|
|
26283
|
+
).all();
|
|
26284
|
+
const recovered = [];
|
|
26285
|
+
for (const row of rows) {
|
|
26286
|
+
if (row.lease_owner === daemonIdentity) continue;
|
|
26287
|
+
db.raw.run(
|
|
26288
|
+
`UPDATE verification_attempts
|
|
26289
|
+
SET state = 'uncertain', finished_at = ?, lease_owner = NULL, lease_expires_at = NULL,
|
|
26290
|
+
error = 'execution was interrupted before it reported an outcome'
|
|
26291
|
+
WHERE id = ?`,
|
|
26292
|
+
[now, row.id]
|
|
26293
|
+
);
|
|
26294
|
+
db.raw.run(
|
|
26295
|
+
`UPDATE verification_check_outcomes SET state = 'unknown', finished_at = ?
|
|
26296
|
+
WHERE attempt_id = ? AND state = 'not_executed'`,
|
|
26297
|
+
[now, row.id]
|
|
26298
|
+
);
|
|
26299
|
+
setRequestState(db, row.request_id, "uncertain");
|
|
26300
|
+
recovered.push(row.request_id);
|
|
26301
|
+
}
|
|
26302
|
+
return recovered;
|
|
26303
|
+
});
|
|
26304
|
+
}
|
|
26305
|
+
function pruneVerificationRequests(db, now = Date.now()) {
|
|
26306
|
+
const result = db.raw.run("DELETE FROM verification_requests WHERE expires_at <= ?", [now]);
|
|
26307
|
+
return Number(result.changes);
|
|
26308
|
+
}
|
|
26309
|
+
function validateCheck(check) {
|
|
26310
|
+
if (!check.command.trim()) throw new VerificationRequestError("a check requires a command");
|
|
26311
|
+
assertLength(check.command, VERIFICATION_LIMITS.command, "command");
|
|
26312
|
+
if (check.cwd.length > VERIFICATION_LIMITS.cwd) {
|
|
26313
|
+
throw new VerificationRequestError("cwd is outside its bounded contract");
|
|
26314
|
+
}
|
|
26315
|
+
if (!check.purpose.trim()) throw new VerificationRequestError("a check requires a purpose");
|
|
26316
|
+
assertLength(check.purpose, VERIFICATION_LIMITS.purpose, "purpose");
|
|
26317
|
+
if (!Number.isInteger(check.timeoutMs) || check.timeoutMs < VERIFICATION_LIMITS.minTimeoutMs || check.timeoutMs > VERIFICATION_LIMITS.maxTimeoutMs) {
|
|
26318
|
+
throw new VerificationRequestError("timeout is outside its bounded contract");
|
|
26319
|
+
}
|
|
26320
|
+
}
|
|
26321
|
+
function validateEnvironment(environment) {
|
|
26322
|
+
if (!environment.image)
|
|
26323
|
+
throw new VerificationRequestError("the admitted environment has no image");
|
|
26324
|
+
if (environment.sandbox !== "off" && environment.sandbox !== "docker") {
|
|
26325
|
+
throw new VerificationRequestError("the admitted environment has an unknown shell backend");
|
|
26326
|
+
}
|
|
26327
|
+
if (environment.env && Object.keys(environment.env).length > 32) {
|
|
26328
|
+
throw new VerificationRequestError("the admitted environment carries too many variables");
|
|
26329
|
+
}
|
|
26330
|
+
}
|
|
26331
|
+
function assertLength(value, limit, field) {
|
|
26332
|
+
if (Buffer.byteLength(value) > limit) {
|
|
26333
|
+
throw new VerificationRequestError(`${field} is outside its bounded contract`);
|
|
26334
|
+
}
|
|
26335
|
+
}
|
|
26336
|
+
|
|
25960
26337
|
// ../daemon/src/lib/agent-cancel.ts
|
|
25961
26338
|
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("bazilion.agent-cancel.registry");
|
|
25962
26339
|
var AgentTurnActiveError = class extends Error {
|
|
@@ -26054,14 +26431,14 @@ function reconcilePrivateResults(db, options = {}) {
|
|
|
26054
26431
|
}
|
|
26055
26432
|
|
|
26056
26433
|
// ../daemon/src/lib/coding-environment/lifecycle.ts
|
|
26057
|
-
import { randomUUID as
|
|
26434
|
+
import { randomUUID as randomUUID25 } from "crypto";
|
|
26058
26435
|
|
|
26059
26436
|
// ../daemon/src/lib/coding-environment/resources.ts
|
|
26060
|
-
import { randomUUID as
|
|
26437
|
+
import { randomUUID as randomUUID23 } from "crypto";
|
|
26061
26438
|
|
|
26062
26439
|
// ../daemon/src/runtime/shell/docker.ts
|
|
26063
26440
|
import { spawn } from "child_process";
|
|
26064
|
-
import { randomUUID as
|
|
26441
|
+
import { randomUUID as randomUUID22 } from "crypto";
|
|
26065
26442
|
import { closeSync as closeSync2, constants as constants2, mkdtempSync as mkdtempSync2, openSync as openSync2, rmSync as rmSync9, writeFileSync as writeFileSync6 } from "fs";
|
|
26066
26443
|
import { access, lstat, realpath, stat } from "fs/promises";
|
|
26067
26444
|
import { tmpdir as tmpdir2 } from "os";
|
|
@@ -26551,7 +26928,7 @@ function createPreparedDockerBashOperations(runtime, lifecycle) {
|
|
|
26551
26928
|
}
|
|
26552
26929
|
await assertDockerExecutableIdentity(runtime.dockerPath, runtime.executableIdentity);
|
|
26553
26930
|
if (signal?.aborted) throw new Error("aborted");
|
|
26554
|
-
const containerName = lifecycle?.name("bash") ?? `bazilion-bash-${process.pid}-${
|
|
26931
|
+
const containerName = lifecycle?.name("bash") ?? `bazilion-bash-${process.pid}-${randomUUID22().replaceAll("-", "")}`;
|
|
26555
26932
|
const spec = buildDockerRunSpec({
|
|
26556
26933
|
image: runtime.image,
|
|
26557
26934
|
resolvedImage: runtime.imageId,
|
|
@@ -26600,7 +26977,7 @@ async function preflightProtectedDockerEngine(input) {
|
|
|
26600
26977
|
}
|
|
26601
26978
|
async function proveProtectedContainerCreation(engine, workspace, readOnlyMounts, lifecycle, signal) {
|
|
26602
26979
|
if (signal?.aborted) throw new Error("aborted");
|
|
26603
|
-
const containerName = lifecycle?.name("preflight") ?? `bazilion-preflight-${process.pid}-${
|
|
26980
|
+
const containerName = lifecycle?.name("preflight") ?? `bazilion-preflight-${process.pid}-${randomUUID22().replaceAll("-", "")}`;
|
|
26604
26981
|
const dockerClientEnv = { DOCKER_HOST: engine.endpoint };
|
|
26605
26982
|
const spec = buildDockerRunSpec({
|
|
26606
26983
|
image: engine.image,
|
|
@@ -26932,7 +27309,7 @@ function createDockerBashOperations(options) {
|
|
|
26932
27309
|
const dockerClientEnv = await resolveLocalDockerClientEnv(dockerPath, hostEnv);
|
|
26933
27310
|
const resolvedImage = await inspectSandboxImage(dockerPath, image, dockerClientEnv);
|
|
26934
27311
|
if (signal?.aborted) throw new Error("aborted");
|
|
26935
|
-
const containerName = options.lifecycle?.name("bash") ?? `bazilion-bash-${process.pid}-${
|
|
27312
|
+
const containerName = options.lifecycle?.name("bash") ?? `bazilion-bash-${process.pid}-${randomUUID22().replaceAll("-", "")}`;
|
|
26936
27313
|
const spec = buildDockerRunSpec({
|
|
26937
27314
|
image,
|
|
26938
27315
|
env,
|
|
@@ -27588,7 +27965,7 @@ var WorkspaceResources = class {
|
|
|
27588
27965
|
}
|
|
27589
27966
|
register(lease, resource) {
|
|
27590
27967
|
return inTx(this.db, () => {
|
|
27591
|
-
const id =
|
|
27968
|
+
const id = randomUUID23();
|
|
27592
27969
|
lease.attach({ id, kind: resource.kind });
|
|
27593
27970
|
this.db.raw.run(
|
|
27594
27971
|
"INSERT INTO workspace_resources (id, writer_id, kind, identity_json) VALUES (?, ?, ?, ?)",
|
|
@@ -27626,7 +28003,7 @@ var WorkspaceResources = class {
|
|
|
27626
28003
|
};
|
|
27627
28004
|
|
|
27628
28005
|
// ../daemon/src/lib/coding-environment/workspace.ts
|
|
27629
|
-
import { randomUUID as
|
|
28006
|
+
import { randomUUID as randomUUID24 } from "crypto";
|
|
27630
28007
|
import { realpathSync as realpathSync3 } from "fs";
|
|
27631
28008
|
import { isAbsolute as isAbsolute3, relative as relative2 } from "path";
|
|
27632
28009
|
var WorkspaceBusyError = class extends Error {
|
|
@@ -27670,7 +28047,7 @@ var WorkspaceCoordinator = class {
|
|
|
27670
28047
|
this.db = db;
|
|
27671
28048
|
}
|
|
27672
28049
|
db;
|
|
27673
|
-
identity =
|
|
28050
|
+
identity = randomUUID24();
|
|
27674
28051
|
leases = /* @__PURE__ */ new Set();
|
|
27675
28052
|
issued = /* @__PURE__ */ new WeakSet();
|
|
27676
28053
|
claim(teamId, registeredRoot, kind) {
|
|
@@ -27684,7 +28061,7 @@ var WorkspaceCoordinator = class {
|
|
|
27684
28061
|
const recovery = row.daemon_identity !== this.identity || row.state === "recovery";
|
|
27685
28062
|
if (recovery || exclusive || row.exclusive === 1) throw new WorkspaceBusyError(recovery);
|
|
27686
28063
|
}
|
|
27687
|
-
const id =
|
|
28064
|
+
const id = randomUUID24();
|
|
27688
28065
|
this.db.raw.run(
|
|
27689
28066
|
`INSERT INTO workspace_writers
|
|
27690
28067
|
(id, team_id, root_path, root_identity, daemon_identity, kind, exclusive, state, created_at)
|
|
@@ -27803,7 +28180,7 @@ var WorkspaceLifecycle = class {
|
|
|
27803
28180
|
const prefix = `bazilion-${lease.writer.id}-`;
|
|
27804
28181
|
const records2 = /* @__PURE__ */ new Map();
|
|
27805
28182
|
return {
|
|
27806
|
-
name: (kind) => `${prefix}${kind}-${
|
|
28183
|
+
name: (kind) => `${prefix}${kind}-${randomUUID25()}`,
|
|
27807
28184
|
beforeCreate: async (identity2) => {
|
|
27808
28185
|
if (!identity2.containerName.startsWith(prefix) || !/^bazilion-[a-z0-9-]{1,160}$/.test(identity2.containerName) || records2.has(identity2.containerName))
|
|
27809
28186
|
throw new Error("Invalid turn container identity");
|
|
@@ -27838,7 +28215,7 @@ var WorkspaceLifecycle = class {
|
|
|
27838
28215
|
};
|
|
27839
28216
|
|
|
27840
28217
|
// ../daemon/src/lib/conversation-target.ts
|
|
27841
|
-
import { randomUUID as
|
|
28218
|
+
import { randomUUID as randomUUID27 } from "crypto";
|
|
27842
28219
|
|
|
27843
28220
|
// ../daemon/src/core/repos/conversations.ts
|
|
27844
28221
|
var columns = "id, agent_id AS agentId, title, title_revision AS titleRevision, created_at AS createdAt, updated_at AS updatedAt";
|
|
@@ -27960,7 +28337,7 @@ function rename(db, agentId, id, value, expectedRevision) {
|
|
|
27960
28337
|
}
|
|
27961
28338
|
|
|
27962
28339
|
// ../daemon/src/lib/conversation-file.ts
|
|
27963
|
-
import { randomUUID as
|
|
28340
|
+
import { randomUUID as randomUUID26 } from "crypto";
|
|
27964
28341
|
import {
|
|
27965
28342
|
closeSync as closeSync4,
|
|
27966
28343
|
constants as constants4,
|
|
@@ -28025,7 +28402,7 @@ function createConversationFile(paths, agentId, conversationId, cwd) {
|
|
|
28025
28402
|
if (realpathSync5(directory) !== directory) throw new Error("Conversation escaped its Agent");
|
|
28026
28403
|
const filename2 = `${conversationId}.jsonl`;
|
|
28027
28404
|
const destination = join16(directory, filename2);
|
|
28028
|
-
const staging = join16(directory, `.conversation-${
|
|
28405
|
+
const staging = join16(directory, `.conversation-${randomUUID26()}.tmp`);
|
|
28029
28406
|
const header = SessionManager.inMemory(cwd, { id: conversationId }).getHeader();
|
|
28030
28407
|
const fd = openSync4(staging, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL, 384);
|
|
28031
28408
|
try {
|
|
@@ -28063,7 +28440,7 @@ function resolveConversationTarget(db, paths, agentId, pinnedId) {
|
|
|
28063
28440
|
db,
|
|
28064
28441
|
agentId,
|
|
28065
28442
|
{
|
|
28066
|
-
requestId:
|
|
28443
|
+
requestId: randomUUID27(),
|
|
28067
28444
|
expectedSelection: { conversationId: null, revision: 0 }
|
|
28068
28445
|
},
|
|
28069
28446
|
(newId) => createConversationFile(paths, agentId, newId, agent.team.path)
|
|
@@ -28130,7 +28507,7 @@ async function runAgentLifecycleMutation(agentId, mutation) {
|
|
|
28130
28507
|
}
|
|
28131
28508
|
|
|
28132
28509
|
// ../daemon/src/lib/agent-loop-guard.ts
|
|
28133
|
-
import { randomUUID as
|
|
28510
|
+
import { randomUUID as randomUUID28 } from "crypto";
|
|
28134
28511
|
var DEFAULT_MAX_HOPS = 8;
|
|
28135
28512
|
function toEvent(row) {
|
|
28136
28513
|
return {
|
|
@@ -28182,8 +28559,8 @@ function enforceMessageCausality(db, input) {
|
|
|
28182
28559
|
const target = agents_exports.get(db, input.to);
|
|
28183
28560
|
if (!source || !target) return null;
|
|
28184
28561
|
const event2 = {
|
|
28185
|
-
id:
|
|
28186
|
-
causalChainId: input.causality.causalChainId ?? input.causality.parentMessageId ??
|
|
28562
|
+
id: randomUUID28(),
|
|
28563
|
+
causalChainId: input.causality.causalChainId ?? input.causality.parentMessageId ?? randomUUID28(),
|
|
28187
28564
|
parentMessageId: input.causality.parentMessageId,
|
|
28188
28565
|
fromAgentId: input.from,
|
|
28189
28566
|
toAgentId: input.to,
|
|
@@ -29610,8 +29987,8 @@ function assertRepositoryContext(value, teamId) {
|
|
|
29610
29987
|
]) && string(candidate.source) && digest3(candidate.sha256) && string(candidate.location) && string(candidate.cwd) && string(candidate.command) && ["script", "excerpt"].includes(String(candidate.kind)) && [null, "npm", "pnpm", "yarn"].includes(candidate.packageManager)
|
|
29611
29988
|
) || !["available", "unavailable", "not_repository"].includes(String(git.state)) || ![null, "branch", "detached", "unborn"].includes(git.headState) || ![git.root, git.branch, git.head].every((value2) => value2 === null || string(value2)) || ![git.staged, git.unstaged, git.untracked, git.conflicted].every(count2) || !list15(git.issues, 128, issue))
|
|
29612
29989
|
throw new Error("Invalid repository context report");
|
|
29613
|
-
const
|
|
29614
|
-
if (
|
|
29990
|
+
const report2 = value;
|
|
29991
|
+
if (report2.instructions.files.reduce((bytes, file) => bytes + Buffer.byteLength(file.content), 0) > 128 * 1024 || report2.instructions.state === "complete" && (report2.rootIdentity === null || report2.instructions.issues.length > 0))
|
|
29615
29992
|
throw new Error("Invalid repository instruction completeness");
|
|
29616
29993
|
}
|
|
29617
29994
|
|
|
@@ -31192,6 +31569,16 @@ var PROTECTED_REQUIRED_KEYS = new Set(
|
|
|
31192
31569
|
(key3) => key3 !== "images" && key3 !== "questionEnabled" && key3 !== "containerNamespace"
|
|
31193
31570
|
)
|
|
31194
31571
|
);
|
|
31572
|
+
var VERIFICATION_KEYS = /* @__PURE__ */ new Set([
|
|
31573
|
+
"kind",
|
|
31574
|
+
"agentId",
|
|
31575
|
+
"message",
|
|
31576
|
+
"turnId",
|
|
31577
|
+
"runtime",
|
|
31578
|
+
"verification",
|
|
31579
|
+
"apiKeyRefreshEnabled",
|
|
31580
|
+
"scratch"
|
|
31581
|
+
]);
|
|
31195
31582
|
var REVIEW_KEYS = /* @__PURE__ */ new Set([
|
|
31196
31583
|
"kind",
|
|
31197
31584
|
"agentId",
|
|
@@ -31326,6 +31713,27 @@ function parseWorkerInput(value) {
|
|
|
31326
31713
|
assertMinimalWorkerScratch(input.scratch);
|
|
31327
31714
|
return value;
|
|
31328
31715
|
}
|
|
31716
|
+
if (kind === "specialist_verification") {
|
|
31717
|
+
assertExactKeys(input, VERIFICATION_KEYS, "verification worker input", VERIFICATION_KEYS);
|
|
31718
|
+
requireString(input.agentId, "agentId");
|
|
31719
|
+
requireString(input.message, "message");
|
|
31720
|
+
requireString(input.turnId, "turnId");
|
|
31721
|
+
assertProtectedProviderRuntime(input.runtime);
|
|
31722
|
+
if (input.apiKeyRefreshEnabled !== true) {
|
|
31723
|
+
throw new Error("worker: verification input requires bound API key refresh");
|
|
31724
|
+
}
|
|
31725
|
+
assertMinimalWorkerScratch(input.scratch);
|
|
31726
|
+
const verification = objectRecord(input.verification, "verification metadata");
|
|
31727
|
+
assertExactKeys(
|
|
31728
|
+
verification,
|
|
31729
|
+
/* @__PURE__ */ new Set(["requestId", "attemptId"]),
|
|
31730
|
+
"verification metadata",
|
|
31731
|
+
/* @__PURE__ */ new Set(["requestId", "attemptId"])
|
|
31732
|
+
);
|
|
31733
|
+
requireString(verification.requestId, "requestId");
|
|
31734
|
+
requireString(verification.attemptId, "attemptId");
|
|
31735
|
+
return value;
|
|
31736
|
+
}
|
|
31329
31737
|
if (kind === "restricted_review") {
|
|
31330
31738
|
assertExactKeys(input, REVIEW_KEYS, "restricted review worker input", REVIEW_KEYS);
|
|
31331
31739
|
requireString(input.agentId, "agentId");
|
|
@@ -33766,6 +34174,9 @@ async function spawnReviewWorker(spec, opts) {
|
|
|
33766
34174
|
}
|
|
33767
34175
|
throw new Error("review worker exited without a result");
|
|
33768
34176
|
}
|
|
34177
|
+
function spawnVerificationWorker(spec, opts) {
|
|
34178
|
+
return spawnWorker(spec, opts);
|
|
34179
|
+
}
|
|
33769
34180
|
function spawnWorkerTurn(spec, opts) {
|
|
33770
34181
|
return spawnWorker(spec, opts);
|
|
33771
34182
|
}
|
|
@@ -33813,7 +34224,7 @@ async function* spawnWorker(spec, opts) {
|
|
|
33813
34224
|
}
|
|
33814
34225
|
const accessTokens = spec.kind === "configured_operator_http" ? spec.apiKey ? [spec.apiKey] : [] : protectedRuntimeSecrets(spec.runtime);
|
|
33815
34226
|
const stderrRedactor = accessTokens.length > 0 ? new ExactValueStreamRedactor(accessTokens) : void 0;
|
|
33816
|
-
const resourceLifecycle = spec
|
|
34227
|
+
const resourceLifecycle = isRestrictedWorkerKind(spec) ? void 0 : opts.resourceLifecycle;
|
|
33817
34228
|
let resourceCleanup;
|
|
33818
34229
|
const cleanupResources = () => resourceCleanup ??= resourceLifecycle?.afterExit(child.exitCode !== null && child.signalCode === null).catch(() => false) ?? Promise.resolve(true);
|
|
33819
34230
|
let child;
|
|
@@ -33989,9 +34400,12 @@ async function* spawnWorker(spec, opts) {
|
|
|
33989
34400
|
throw new Error("Worker cleanup could not be confirmed; workspace recovery required");
|
|
33990
34401
|
}
|
|
33991
34402
|
}
|
|
34403
|
+
function isRestrictedWorkerKind(spec) {
|
|
34404
|
+
return spec.kind === "restricted_review" || spec.kind === "specialist_verification";
|
|
34405
|
+
}
|
|
33992
34406
|
function assertSpawnCombination(spec, opts) {
|
|
33993
34407
|
const record3 = opts;
|
|
33994
|
-
if (spec
|
|
34408
|
+
if (!isRestrictedWorkerKind(spec) && (Boolean(spec.questionEnabled) !== Boolean(record3.questionHost) || record3.questionHost && !hostHasMethods(record3.questionHost, ["ask", "close", "subscribe", "consumed"])))
|
|
33995
34409
|
throw new Error("Question capability requires its bound host");
|
|
33996
34410
|
if (spec.kind === "configured_operator_http") {
|
|
33997
34411
|
if (!("env" in record3) || !record3.env || typeof record3.env !== "object") {
|
|
@@ -34025,9 +34439,20 @@ function assertSpawnCombination(spec, opts) {
|
|
|
34025
34439
|
"userMdHost",
|
|
34026
34440
|
"bashApprovalHost",
|
|
34027
34441
|
"browserHost",
|
|
34028
|
-
"mcpHost"
|
|
34442
|
+
"mcpHost",
|
|
34443
|
+
"codingHost",
|
|
34444
|
+
"containerHost",
|
|
34445
|
+
"repositoryContextHost",
|
|
34446
|
+
"resultHost",
|
|
34447
|
+
"resourceLifecycle"
|
|
34029
34448
|
]) {
|
|
34030
|
-
if (forbidden in record3) throw new Error(
|
|
34449
|
+
if (forbidden in record3) throw new Error(`${spec.kind} rejects ${forbidden}`);
|
|
34450
|
+
}
|
|
34451
|
+
const wantsCapability = spec.kind === "specialist_verification";
|
|
34452
|
+
if (wantsCapability !== "verificationHost" in record3) {
|
|
34453
|
+
throw new Error(
|
|
34454
|
+
wantsCapability ? "verification turn requires its bound capability host" : `${spec.kind} rejects verificationHost`
|
|
34455
|
+
);
|
|
34031
34456
|
}
|
|
34032
34457
|
}
|
|
34033
34458
|
}
|
|
@@ -34054,16 +34479,20 @@ function spawnHosts(spec, opts, signal, onBashApproval, onQuestion, onApiKeyRefr
|
|
|
34054
34479
|
);
|
|
34055
34480
|
if (signal.aborted) questionHost.close();
|
|
34056
34481
|
}
|
|
34482
|
+
const restricted = isRestrictedWorkerKind(spec);
|
|
34057
34483
|
return {
|
|
34058
|
-
questionHost,
|
|
34059
|
-
containerHost:
|
|
34060
|
-
codingHost:
|
|
34061
|
-
repositoryContextHost:
|
|
34062
|
-
resultHost:
|
|
34063
|
-
|
|
34064
|
-
|
|
34065
|
-
|
|
34066
|
-
|
|
34484
|
+
questionHost: restricted ? void 0 : questionHost,
|
|
34485
|
+
containerHost: restricted ? void 0 : opts.containerHost,
|
|
34486
|
+
codingHost: restricted ? void 0 : opts.codingHost,
|
|
34487
|
+
repositoryContextHost: restricted ? void 0 : opts.repositoryContextHost,
|
|
34488
|
+
resultHost: restricted ? void 0 : opts.resultHost,
|
|
34489
|
+
// A verification turn reads its request and runs captured checks; it does not message peers,
|
|
34490
|
+
// edit USER.md, drive a browser or call MCP. Cleared here rather than trusting the caller.
|
|
34491
|
+
messagingHost: restricted ? void 0 : configuredOpts?.messagingHost ?? protectedOpts?.messagingHost,
|
|
34492
|
+
userMdHost: restricted ? void 0 : configuredOpts?.userMdHost ?? protectedOpts?.userMdHost,
|
|
34493
|
+
browserHost: restricted ? void 0 : configuredOpts?.browserHost,
|
|
34494
|
+
mcpHost: restricted ? void 0 : configuredOpts?.mcpHost,
|
|
34495
|
+
verificationHost: spec.kind === "specialist_verification" ? opts.verificationHost : void 0,
|
|
34067
34496
|
bashApprovalHost: configuredOpts?.bashApprovalHost ?? protectedOpts?.bashApprovalHost,
|
|
34068
34497
|
apiKeyRefreshHost: opts.apiKeyRefreshHost,
|
|
34069
34498
|
apiKeyRefreshContext: {
|
|
@@ -34216,6 +34645,19 @@ async function dispatch(req, hosts) {
|
|
|
34216
34645
|
req.args.args
|
|
34217
34646
|
);
|
|
34218
34647
|
break;
|
|
34648
|
+
case "verificationRead":
|
|
34649
|
+
result = await require2(hosts.verificationHost, "verification", req.method).read(
|
|
34650
|
+
req.args.requestId,
|
|
34651
|
+
req.args.attemptId
|
|
34652
|
+
);
|
|
34653
|
+
break;
|
|
34654
|
+
case "verificationRun":
|
|
34655
|
+
result = await require2(hosts.verificationHost, "verification", req.method).run(
|
|
34656
|
+
req.args.requestId,
|
|
34657
|
+
req.args.attemptId,
|
|
34658
|
+
req.args.ordinal
|
|
34659
|
+
);
|
|
34660
|
+
break;
|
|
34219
34661
|
case "refreshApiKey":
|
|
34220
34662
|
result = await refreshApiKeyForTurn(
|
|
34221
34663
|
req.args,
|
|
@@ -35058,7 +35500,7 @@ function createBrowserHost(config2) {
|
|
|
35058
35500
|
}
|
|
35059
35501
|
|
|
35060
35502
|
// ../daemon/src/lib/coding-environment/agent-host.ts
|
|
35061
|
-
import { createHash as createHash10, randomUUID as
|
|
35503
|
+
import { createHash as createHash10, randomUUID as randomUUID31 } from "crypto";
|
|
35062
35504
|
|
|
35063
35505
|
// ../daemon/src/core/repos/coding-command-logs.ts
|
|
35064
35506
|
var CODING_LOG_BYTES = 2 * 1024 * 1024;
|
|
@@ -35278,7 +35720,7 @@ function pruneCodingCommandLogs(db, now = Date.now(), budgetBytes = CODING_LOG_H
|
|
|
35278
35720
|
}
|
|
35279
35721
|
|
|
35280
35722
|
// ../daemon/src/lib/communication.ts
|
|
35281
|
-
import { randomUUID as
|
|
35723
|
+
import { randomUUID as randomUUID30 } from "crypto";
|
|
35282
35724
|
|
|
35283
35725
|
// ../daemon/src/lib/question-approval.ts
|
|
35284
35726
|
function questionApprovalReference(snapshot, kind) {
|
|
@@ -35373,7 +35815,7 @@ function questionVisible(db, item) {
|
|
|
35373
35815
|
}
|
|
35374
35816
|
|
|
35375
35817
|
// ../daemon/src/core/repos/results.ts
|
|
35376
|
-
import { createHash as createHash9, randomUUID as
|
|
35818
|
+
import { createHash as createHash9, randomUUID as randomUUID29 } from "crypto";
|
|
35377
35819
|
var MAX_RESULT_BYTES = 25 * 1024 * 1024;
|
|
35378
35820
|
var MAX_RETAINED_RESULT_BYTES = 1024 * 1024 * 1024;
|
|
35379
35821
|
var columns2 = `id, team_id AS teamId, agent_id AS agentId, session_id AS sessionId,
|
|
@@ -35420,7 +35862,7 @@ function publish(db, input) {
|
|
|
35420
35862
|
"Result storage is full (1 GiB). Delete saved results before delivering more files."
|
|
35421
35863
|
);
|
|
35422
35864
|
}
|
|
35423
|
-
const id =
|
|
35865
|
+
const id = randomUUID29();
|
|
35424
35866
|
db.raw.run(
|
|
35425
35867
|
`INSERT INTO agent_results
|
|
35426
35868
|
(id, team_id, agent_id, session_id, tool_call_id, name, mime_type, byte_length, sha256, created_at, bytes)
|
|
@@ -35649,6 +36091,39 @@ function authorizeAgentEgress(db, agentId, attempt) {
|
|
|
35649
36091
|
"agent_to_user"
|
|
35650
36092
|
);
|
|
35651
36093
|
}
|
|
36094
|
+
function authorizeOperatorVerification(db, input) {
|
|
36095
|
+
const agent = agents_exports.get(db, input.agentId);
|
|
36096
|
+
return authorizeBoundary(
|
|
36097
|
+
db,
|
|
36098
|
+
{
|
|
36099
|
+
source: { kind: "user", teamId: agent?.teamId ?? "__missing__" },
|
|
36100
|
+
target: { kind: "agent", id: input.agentId },
|
|
36101
|
+
origin: "verification_request",
|
|
36102
|
+
attemptKind: "verification_request",
|
|
36103
|
+
attemptId: input.requestId,
|
|
36104
|
+
approvalPayloadKind: "verification_request",
|
|
36105
|
+
approvalPayload: { requestId: input.requestId },
|
|
36106
|
+
requester: "user"
|
|
36107
|
+
},
|
|
36108
|
+
"request_verification"
|
|
36109
|
+
);
|
|
36110
|
+
}
|
|
36111
|
+
function authorizeVerificationRequest(db, input) {
|
|
36112
|
+
return authorizeBoundary(
|
|
36113
|
+
db,
|
|
36114
|
+
{
|
|
36115
|
+
source: { kind: "agent", id: input.from },
|
|
36116
|
+
target: { kind: "agent", id: input.to },
|
|
36117
|
+
origin: "verification_request",
|
|
36118
|
+
attemptKind: "verification_request",
|
|
36119
|
+
attemptId: input.requestId,
|
|
36120
|
+
approvalPayloadKind: "verification_request",
|
|
36121
|
+
approvalPayload: { requestId: input.requestId },
|
|
36122
|
+
requester: input.from
|
|
36123
|
+
},
|
|
36124
|
+
"request_verification"
|
|
36125
|
+
);
|
|
36126
|
+
}
|
|
35652
36127
|
function authorizeHttpChatFrame(db, agentId, requestAttemptId, frameIndex, frame) {
|
|
35653
36128
|
if (frame.kind === "event" && frame.event.type === "agent_question") {
|
|
35654
36129
|
const current = get18(db, agentId, frame.event.question.id);
|
|
@@ -35687,7 +36162,7 @@ function isUserFacingFrame(frame) {
|
|
|
35687
36162
|
}
|
|
35688
36163
|
function sendAgentMessage(db, input) {
|
|
35689
36164
|
const attemptKind = input.attemptKind ?? "agent_tool";
|
|
35690
|
-
const attemptId = input.attemptId ??
|
|
36165
|
+
const attemptId = input.attemptId ?? randomUUID30();
|
|
35691
36166
|
const outcome = db.raw.transaction(
|
|
35692
36167
|
() => {
|
|
35693
36168
|
const causality = resolveMessageCausality(db, input);
|
|
@@ -36555,11 +37030,11 @@ async function readChangePatch(captured, base, change, patchBytes = REVIEW_LIMIT
|
|
|
36555
37030
|
omitted: null
|
|
36556
37031
|
};
|
|
36557
37032
|
}
|
|
36558
|
-
async function attachPatches(captured,
|
|
37033
|
+
async function attachPatches(captured, report2, limits = REVIEW_LIMITS, onlyPath) {
|
|
36559
37034
|
let total = 0;
|
|
36560
37035
|
let tooLarge = 0;
|
|
36561
37036
|
const changes = [];
|
|
36562
|
-
for (const change of
|
|
37037
|
+
for (const change of report2.changes) {
|
|
36563
37038
|
if (onlyPath !== void 0 && change.path !== onlyPath) {
|
|
36564
37039
|
changes.push(change);
|
|
36565
37040
|
continue;
|
|
@@ -36572,7 +37047,7 @@ async function attachPatches(captured, report, limits = REVIEW_LIMITS, onlyPath)
|
|
|
36572
37047
|
changes.push({ ...change, contentOmitted: "total_limit" });
|
|
36573
37048
|
continue;
|
|
36574
37049
|
}
|
|
36575
|
-
const read = await readChangePatch(captured,
|
|
37050
|
+
const read = await readChangePatch(captured, report2.base, change, limits.patchBytes);
|
|
36576
37051
|
const bytes = read.patch ? Buffer.byteLength(read.patch) : 0;
|
|
36577
37052
|
if (bytes > limits.fileBytes && !read.truncated) {
|
|
36578
37053
|
tooLarge++;
|
|
@@ -36587,7 +37062,7 @@ async function attachPatches(captured, report, limits = REVIEW_LIMITS, onlyPath)
|
|
|
36587
37062
|
contentOmitted: read.omitted
|
|
36588
37063
|
});
|
|
36589
37064
|
}
|
|
36590
|
-
return { ...
|
|
37065
|
+
return { ...report2, changes, withheld: { ...report2.withheld, tooLarge } };
|
|
36591
37066
|
}
|
|
36592
37067
|
async function readDiff(captured, base, args) {
|
|
36593
37068
|
return captured.runGit(["diff", base.resolvedOid, ...args]);
|
|
@@ -37103,13 +37578,13 @@ var emptyGit = () => ({
|
|
|
37103
37578
|
issues: []
|
|
37104
37579
|
});
|
|
37105
37580
|
async function inspectGit(ancestry) {
|
|
37106
|
-
const
|
|
37581
|
+
const report2 = emptyGit();
|
|
37107
37582
|
let capture2 = null;
|
|
37108
37583
|
try {
|
|
37109
37584
|
const root = findRepositoryRoot(ancestry);
|
|
37110
|
-
if (!root) return
|
|
37111
|
-
|
|
37112
|
-
|
|
37585
|
+
if (!root) return report2;
|
|
37586
|
+
report2.root = root.label;
|
|
37587
|
+
report2.state = "unavailable";
|
|
37113
37588
|
capture2 = await captureRepositoryGit(root);
|
|
37114
37589
|
const output = await capture2.runGit([
|
|
37115
37590
|
"status",
|
|
@@ -37125,32 +37600,32 @@ async function inspectGit(ancestry) {
|
|
|
37125
37600
|
const line = records2[i] ?? "";
|
|
37126
37601
|
if (line.startsWith("# branch.oid ")) {
|
|
37127
37602
|
const oid = line.slice(13);
|
|
37128
|
-
|
|
37603
|
+
report2.head = /^[0-9a-f]{40,64}$/.test(oid) ? oid : null;
|
|
37129
37604
|
} else if (line.startsWith("# branch.head ")) {
|
|
37130
37605
|
const branch = line.slice(14);
|
|
37131
37606
|
if (branch.length > 4096) throw new ContextReadError("git_output_limit");
|
|
37132
|
-
|
|
37133
|
-
} else if (line.startsWith("? "))
|
|
37134
|
-
else if (line.startsWith("u "))
|
|
37607
|
+
report2.branch = branch === "(detached)" ? null : branch;
|
|
37608
|
+
} else if (line.startsWith("? ")) report2.untracked++;
|
|
37609
|
+
else if (line.startsWith("u ")) report2.conflicted++;
|
|
37135
37610
|
else if (line.startsWith("1 ") || line.startsWith("2 ")) {
|
|
37136
|
-
if (line[2] !== ".")
|
|
37137
|
-
if (line[3] !== ".")
|
|
37611
|
+
if (line[2] !== ".") report2.staged++;
|
|
37612
|
+
if (line[3] !== ".") report2.unstaged++;
|
|
37138
37613
|
if (line.startsWith("2 ")) i++;
|
|
37139
37614
|
}
|
|
37140
37615
|
}
|
|
37141
|
-
|
|
37142
|
-
|
|
37616
|
+
report2.headState = report2.head ? report2.branch ? "branch" : "detached" : "unborn";
|
|
37617
|
+
report2.state = "available";
|
|
37143
37618
|
} catch (error2) {
|
|
37144
|
-
|
|
37619
|
+
report2.state = "unavailable";
|
|
37145
37620
|
const code = error2 instanceof ContextReadError ? error2.code : error2.code === "ENOENT" ? "git_missing" : error2.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER" ? "git_output_limit" : error2.killed || error2.code === "ETIMEDOUT" ? "git_timeout" : "git_inspection_failed";
|
|
37146
|
-
|
|
37621
|
+
report2.issues.push({
|
|
37147
37622
|
code,
|
|
37148
37623
|
message: `Git inspection is unavailable (${code.replaceAll("_", " ")}); repository instructions are evaluated separately.`
|
|
37149
37624
|
});
|
|
37150
37625
|
} finally {
|
|
37151
37626
|
capture2?.cleanup();
|
|
37152
37627
|
}
|
|
37153
|
-
return
|
|
37628
|
+
return report2;
|
|
37154
37629
|
}
|
|
37155
37630
|
|
|
37156
37631
|
// ../daemon/src/lib/repository-context/index.ts
|
|
@@ -37176,7 +37651,7 @@ function issue2(error2, path) {
|
|
|
37176
37651
|
};
|
|
37177
37652
|
}
|
|
37178
37653
|
async function resolveRepositoryContext(input) {
|
|
37179
|
-
const
|
|
37654
|
+
const report2 = {
|
|
37180
37655
|
version: 1,
|
|
37181
37656
|
teamId: input.teamId,
|
|
37182
37657
|
rootIdentity: null,
|
|
@@ -37190,9 +37665,9 @@ async function resolveRepositoryContext(input) {
|
|
|
37190
37665
|
let root;
|
|
37191
37666
|
try {
|
|
37192
37667
|
root = new ContextDirectory(input.root);
|
|
37193
|
-
|
|
37668
|
+
report2.rootIdentity = root.identity;
|
|
37194
37669
|
const parts = relativeParts(input.target ?? ".");
|
|
37195
|
-
|
|
37670
|
+
report2.target = parts.join("/") || ".";
|
|
37196
37671
|
if (input.expectedRootIdentity && root.identity !== input.expectedRootIdentity)
|
|
37197
37672
|
throw new ContextReadError("root_changed");
|
|
37198
37673
|
const ancestry = [root];
|
|
@@ -37220,17 +37695,17 @@ async function resolveRepositoryContext(input) {
|
|
|
37220
37695
|
instructionBytes += bytes.length;
|
|
37221
37696
|
if (instructionBytes > CONTEXT_LIMITS.instructionTotal)
|
|
37222
37697
|
throw new ContextReadError("instruction_total_limit");
|
|
37223
|
-
|
|
37698
|
+
report2.instructions.files.push({
|
|
37224
37699
|
path,
|
|
37225
37700
|
scope: directory.label,
|
|
37226
|
-
precedence:
|
|
37701
|
+
precedence: report2.instructions.files.length,
|
|
37227
37702
|
content: decode3(bytes),
|
|
37228
37703
|
sha256: hash3(bytes)
|
|
37229
37704
|
});
|
|
37230
37705
|
}
|
|
37231
37706
|
} catch (error2) {
|
|
37232
|
-
|
|
37233
|
-
|
|
37707
|
+
report2.instructions.state = "incomplete";
|
|
37708
|
+
report2.instructions.issues.push(issue2(error2, path));
|
|
37234
37709
|
}
|
|
37235
37710
|
const memory = input.memoryPath ?? "memory";
|
|
37236
37711
|
if (directory.label === memory || directory.label.startsWith(`${memory}/`) || directory.label.split("/").some((part) => discoveryExcluded.has(part)))
|
|
@@ -37247,14 +37722,14 @@ async function resolveRepositoryContext(input) {
|
|
|
37247
37722
|
if (sourceBytes > CONTEXT_LIMITS.sourceTotal)
|
|
37248
37723
|
throw new ContextReadError("source_total_limit");
|
|
37249
37724
|
const sha256 = hash3(bytes);
|
|
37250
|
-
|
|
37725
|
+
report2.commands.sources.push({ path: path2, sha256 });
|
|
37251
37726
|
const content = decode3(bytes);
|
|
37252
37727
|
const add2 = (candidate) => {
|
|
37253
|
-
if (
|
|
37728
|
+
if (report2.commands.candidates.length >= CONTEXT_LIMITS.candidates)
|
|
37254
37729
|
throw new ContextReadError("candidate_limit");
|
|
37255
37730
|
if (candidate.command.length > 4096 || candidate.location.length > 4096)
|
|
37256
37731
|
throw new ContextReadError("command_limit");
|
|
37257
|
-
|
|
37732
|
+
report2.commands.candidates.push({
|
|
37258
37733
|
...candidate,
|
|
37259
37734
|
source: path2,
|
|
37260
37735
|
sha256,
|
|
@@ -37301,50 +37776,50 @@ async function resolveRepositoryContext(input) {
|
|
|
37301
37776
|
}
|
|
37302
37777
|
}
|
|
37303
37778
|
} catch (error2) {
|
|
37304
|
-
|
|
37305
|
-
|
|
37779
|
+
report2.commands.state = "incomplete";
|
|
37780
|
+
report2.commands.issues.push(issue2(error2, path2));
|
|
37306
37781
|
}
|
|
37307
37782
|
}
|
|
37308
37783
|
}
|
|
37309
|
-
|
|
37784
|
+
report2.git = await inspectGit(ancestry);
|
|
37310
37785
|
root.validate(true, /* @__PURE__ */ new Set(["AGENTS.md"]));
|
|
37311
37786
|
try {
|
|
37312
37787
|
root.validate(true, new Set(sourceNames));
|
|
37313
37788
|
} catch (error2) {
|
|
37314
|
-
|
|
37789
|
+
report2.commands = { state: "incomplete", sources: [], candidates: [], issues: [issue2(error2)] };
|
|
37315
37790
|
}
|
|
37316
37791
|
} catch (error2) {
|
|
37317
|
-
|
|
37318
|
-
|
|
37319
|
-
|
|
37320
|
-
|
|
37321
|
-
|
|
37322
|
-
|
|
37323
|
-
|
|
37324
|
-
|
|
37792
|
+
report2.instructions.state = "incomplete";
|
|
37793
|
+
report2.instructions.files = [];
|
|
37794
|
+
report2.instructions.issues.push(issue2(error2));
|
|
37795
|
+
report2.commands.state = "incomplete";
|
|
37796
|
+
report2.commands.sources = [];
|
|
37797
|
+
report2.commands.candidates = [];
|
|
37798
|
+
report2.commands.issues.push(issue2(error2));
|
|
37799
|
+
report2.git = { ...emptyGit(), state: "unavailable", issues: [issue2(error2)] };
|
|
37325
37800
|
} finally {
|
|
37326
37801
|
root?.close();
|
|
37327
37802
|
}
|
|
37328
|
-
if (Buffer.byteLength(JSON.stringify(
|
|
37329
|
-
|
|
37803
|
+
if (Buffer.byteLength(JSON.stringify(report2)) > CONTEXT_LIMITS.report - 128) {
|
|
37804
|
+
report2.instructions = {
|
|
37330
37805
|
state: "incomplete",
|
|
37331
37806
|
files: [],
|
|
37332
37807
|
issues: [issue2(new ContextReadError("report_limit"))]
|
|
37333
37808
|
};
|
|
37334
|
-
|
|
37809
|
+
report2.commands = {
|
|
37335
37810
|
state: "incomplete",
|
|
37336
37811
|
sources: [],
|
|
37337
37812
|
candidates: [],
|
|
37338
37813
|
issues: [issue2(new ContextReadError("report_limit"))]
|
|
37339
37814
|
};
|
|
37340
37815
|
}
|
|
37341
|
-
|
|
37342
|
-
return
|
|
37816
|
+
report2.fingerprint = hash3(JSON.stringify({ ...report2, capturedAt: 0, fingerprint: "" }));
|
|
37817
|
+
return report2;
|
|
37343
37818
|
}
|
|
37344
|
-
function requireCompleteRepositoryContext(
|
|
37345
|
-
if (
|
|
37819
|
+
function requireCompleteRepositoryContext(report2) {
|
|
37820
|
+
if (report2.instructions.state !== "complete") {
|
|
37346
37821
|
throw new Error(
|
|
37347
|
-
`Repository instructions incomplete (${
|
|
37822
|
+
`Repository instructions incomplete (${report2.instructions.issues.map((i) => i.code).join(", ")}). Inspect Team repository context before coding.`
|
|
37348
37823
|
);
|
|
37349
37824
|
}
|
|
37350
37825
|
}
|
|
@@ -37371,14 +37846,14 @@ function createCodingHost(input) {
|
|
|
37371
37846
|
input.assertActive();
|
|
37372
37847
|
codingRelativePath(target);
|
|
37373
37848
|
resolveCodingDirectory(input.root, target);
|
|
37374
|
-
const
|
|
37375
|
-
requireCompleteRepositoryContext(
|
|
37849
|
+
const report2 = await input.context(target);
|
|
37850
|
+
requireCompleteRepositoryContext(report2);
|
|
37376
37851
|
let fingerprint2 = null;
|
|
37377
37852
|
const dir = new ContextDirectory(input.root);
|
|
37378
37853
|
try {
|
|
37379
37854
|
const sources2 = [
|
|
37380
|
-
|
|
37381
|
-
|
|
37855
|
+
report2.instructions.files.map((file) => [file.path, file.sha256]),
|
|
37856
|
+
report2.commands.sources,
|
|
37382
37857
|
input.values
|
|
37383
37858
|
];
|
|
37384
37859
|
let current = dir;
|
|
@@ -37406,7 +37881,7 @@ function createCodingHost(input) {
|
|
|
37406
37881
|
posture: input.posture,
|
|
37407
37882
|
imageId: input.imageId,
|
|
37408
37883
|
cwd: target,
|
|
37409
|
-
rootIdentity:
|
|
37884
|
+
rootIdentity: report2.rootIdentity ?? "unavailable",
|
|
37410
37885
|
inputFingerprint: fingerprint2,
|
|
37411
37886
|
capturedAt: Date.now(),
|
|
37412
37887
|
restrictions: input.posture === "host" ? [
|
|
@@ -37463,7 +37938,7 @@ function createCodingHost(input) {
|
|
|
37463
37938
|
try {
|
|
37464
37939
|
const environment = await snapshot(command.cwd);
|
|
37465
37940
|
const receipt = {
|
|
37466
|
-
id:
|
|
37941
|
+
id: randomUUID31(),
|
|
37467
37942
|
agentId: input.agentId,
|
|
37468
37943
|
teamId: input.teamId,
|
|
37469
37944
|
turnId: input.turnId,
|
|
@@ -37798,7 +38273,7 @@ function createDbMessagingHost(db, opts = {}) {
|
|
|
37798
38273
|
}
|
|
37799
38274
|
|
|
37800
38275
|
// ../daemon/src/lib/question-service.ts
|
|
37801
|
-
import { randomUUID as
|
|
38276
|
+
import { randomUUID as randomUUID33 } from "crypto";
|
|
37802
38277
|
|
|
37803
38278
|
// ../daemon/src/lib/question-consumption.ts
|
|
37804
38279
|
import { isDeepStrictEqual } from "util";
|
|
@@ -38326,7 +38801,7 @@ function parseTelegramQuestionReply(db, authToken, update3) {
|
|
|
38326
38801
|
}
|
|
38327
38802
|
|
|
38328
38803
|
// ../daemon/src/lib/attachments.ts
|
|
38329
|
-
import { randomUUID as
|
|
38804
|
+
import { randomUUID as randomUUID32 } from "crypto";
|
|
38330
38805
|
import { closeSync as closeSync9, constants as constants10, fstatSync as fstatSync7, openSync as openSync9, writeFileSync as writeFileSync13 } from "fs";
|
|
38331
38806
|
import { join as join26, posix } from "path";
|
|
38332
38807
|
var MAX_FILE_BYTES = 25 * 1024 * 1024;
|
|
@@ -38353,7 +38828,7 @@ function saveInputFiles(agentDir, files, options = {}) {
|
|
|
38353
38828
|
lines.push(`[attachment "${label}" skipped: too large (${fmtBytes(buf.byteLength)} > 25 MB)]`);
|
|
38354
38829
|
continue;
|
|
38355
38830
|
}
|
|
38356
|
-
const filename2 = `${
|
|
38831
|
+
const filename2 = `${randomUUID32().slice(0, 8)}-${safeName(label)}`;
|
|
38357
38832
|
const path = join26(dir, filename2);
|
|
38358
38833
|
let fd;
|
|
38359
38834
|
try {
|
|
@@ -38685,9 +39160,11 @@ function deepFreezePreparedProtectedExecution(value, seen = /* @__PURE__ */ new
|
|
|
38685
39160
|
// ../daemon/src/lib/turn-invocation.ts
|
|
38686
39161
|
var trustedTurnBrand = /* @__PURE__ */ Symbol("bazilion.trusted-turn-invocation");
|
|
38687
39162
|
var trustedReviewBrand = /* @__PURE__ */ Symbol("bazilion.trusted-review-invocation");
|
|
39163
|
+
var trustedVerificationBrand = /* @__PURE__ */ Symbol("bazilion.trusted-verification-invocation");
|
|
38688
39164
|
var preclaimedTurnBrand = /* @__PURE__ */ Symbol("bazilion.preclaimed-turn");
|
|
38689
39165
|
var trustedTurns = /* @__PURE__ */ new WeakSet();
|
|
38690
39166
|
var trustedReviews = /* @__PURE__ */ new WeakSet();
|
|
39167
|
+
var trustedVerifications = /* @__PURE__ */ new WeakSet();
|
|
38691
39168
|
var trustedClaims = /* @__PURE__ */ new WeakSet();
|
|
38692
39169
|
var consumedClaims = /* @__PURE__ */ new WeakSet();
|
|
38693
39170
|
function createPreclaimedTurn(input) {
|
|
@@ -38722,6 +39199,32 @@ function createTrustedReviewInvocation(value) {
|
|
|
38722
39199
|
trustedReviews.add(candidate);
|
|
38723
39200
|
return Object.freeze(candidate);
|
|
38724
39201
|
}
|
|
39202
|
+
function createTrustedVerificationInvocation(value) {
|
|
39203
|
+
validateVerificationInvocation(value);
|
|
39204
|
+
const candidate = {
|
|
39205
|
+
...value,
|
|
39206
|
+
authorization: Object.freeze({ ...value.authorization })
|
|
39207
|
+
};
|
|
39208
|
+
validateVerificationInvocation(candidate);
|
|
39209
|
+
Object.defineProperty(candidate, trustedVerificationBrand, { value: true });
|
|
39210
|
+
trustedVerifications.add(candidate);
|
|
39211
|
+
return Object.freeze(candidate);
|
|
39212
|
+
}
|
|
39213
|
+
function assertTrustedVerificationInvocation(value) {
|
|
39214
|
+
if (!isRecord2(value) || !trustedVerifications.has(value)) throw invalidInvocation();
|
|
39215
|
+
validateVerificationInvocation(value);
|
|
39216
|
+
}
|
|
39217
|
+
function validateVerificationInvocation(value) {
|
|
39218
|
+
if (!isRecord2(value)) throw invalidInvocation();
|
|
39219
|
+
assertExactKeys2(value, ["kind", "authorization", "bashApprovalMode"]);
|
|
39220
|
+
if (value.kind !== "restricted_verification" || value.bashApprovalMode !== "auto_deny" || !isRecord2(value.authorization)) {
|
|
39221
|
+
throw invalidInvocation();
|
|
39222
|
+
}
|
|
39223
|
+
assertExactKeys2(value.authorization, ["kind", "requestId", "attemptId"]);
|
|
39224
|
+
if (value.authorization.kind !== "request" || !isNonEmptyString2(value.authorization.requestId) || !isNonEmptyString2(value.authorization.attemptId)) {
|
|
39225
|
+
throw invalidInvocation();
|
|
39226
|
+
}
|
|
39227
|
+
}
|
|
38725
39228
|
function executionSurfaceForInvocation(invocation) {
|
|
38726
39229
|
return invocation.kind === "operator_http" && !process.env.BAZILION_PUBLIC_ORIGIN ? "configured_operator_http" : "protected";
|
|
38727
39230
|
}
|
|
@@ -39170,7 +39673,7 @@ var QuestionService = class {
|
|
|
39170
39673
|
turn.conversation.id
|
|
39171
39674
|
).length;
|
|
39172
39675
|
this.#attached.add(turn);
|
|
39173
|
-
const turnId =
|
|
39676
|
+
const turnId = randomUUID33();
|
|
39174
39677
|
const listeners = /* @__PURE__ */ new Set();
|
|
39175
39678
|
if (onQuestion) listeners.add(onQuestion);
|
|
39176
39679
|
this.#turns.set(turnId, {
|
|
@@ -41445,7 +41948,7 @@ async function* runAgentTurn(turn) {
|
|
|
41445
41948
|
throw new Error("Repository context unavailable for this turn");
|
|
41446
41949
|
contextBusy = true;
|
|
41447
41950
|
try {
|
|
41448
|
-
const
|
|
41951
|
+
const report2 = await resolveRepositoryContext({
|
|
41449
41952
|
teamId: agent.team.id,
|
|
41450
41953
|
root: agent.team.path,
|
|
41451
41954
|
target,
|
|
@@ -41454,7 +41957,7 @@ async function* runAgentTurn(turn) {
|
|
|
41454
41957
|
turn.controller.signal.throwIfAborted();
|
|
41455
41958
|
if (!ownsActiveAgent(agent.agent.id, turn.controller))
|
|
41456
41959
|
throw new Error("Repository context turn ended");
|
|
41457
|
-
return
|
|
41960
|
+
return report2;
|
|
41458
41961
|
} finally {
|
|
41459
41962
|
contextBusy = false;
|
|
41460
41963
|
}
|
|
@@ -42003,46 +42506,809 @@ async function dispatchClaimableReviews(now = Date.now()) {
|
|
|
42003
42506
|
);
|
|
42004
42507
|
}
|
|
42005
42508
|
|
|
42006
|
-
// ../daemon/src/lib/
|
|
42007
|
-
|
|
42008
|
-
var
|
|
42009
|
-
|
|
42010
|
-
|
|
42011
|
-
|
|
42012
|
-
if (!
|
|
42013
|
-
|
|
42014
|
-
|
|
42015
|
-
|
|
42016
|
-
|
|
42017
|
-
|
|
42018
|
-
|
|
42019
|
-
|
|
42020
|
-
|
|
42021
|
-
|
|
42022
|
-
|
|
42023
|
-
|
|
42024
|
-
|
|
42025
|
-
|
|
42026
|
-
|
|
42027
|
-
|
|
42028
|
-
}
|
|
42029
|
-
if (t.kind === "cron") {
|
|
42030
|
-
if (!t.cronExpr) return false;
|
|
42031
|
-
let parsed = cronCache.get(t.cronExpr);
|
|
42032
|
-
if (!parsed) {
|
|
42033
|
-
try {
|
|
42034
|
-
parsed = parseCron(t.cronExpr);
|
|
42035
|
-
} catch {
|
|
42036
|
-
return false;
|
|
42037
|
-
}
|
|
42038
|
-
cronCache.set(t.cronExpr, parsed);
|
|
42509
|
+
// ../daemon/src/lib/verification/admission.ts
|
|
42510
|
+
import { randomUUID as randomUUID34 } from "crypto";
|
|
42511
|
+
var VERIFICATION_LEASE_MS = 10 * 60 * 1e3;
|
|
42512
|
+
var VERIFICATION_DISPATCH_OWNER = randomUUID34();
|
|
42513
|
+
async function admitVerificationRequest(db, paths, requestId2, now = Date.now()) {
|
|
42514
|
+
const request2 = getVerificationRequestById(db, requestId2, now);
|
|
42515
|
+
if (!request2) return { kind: "deferred", requestId: requestId2, reason: "unknown_or_expired" };
|
|
42516
|
+
const blockedReason = async () => {
|
|
42517
|
+
const team = safeTeam(db, paths, request2.teamId);
|
|
42518
|
+
if (!team) return blocker("unsupported", "the request no longer names a known Team");
|
|
42519
|
+
const recipient = get(db, request2.recipientAgentId);
|
|
42520
|
+
if (!recipient || recipient.status === "archived") {
|
|
42521
|
+
return blocker("recipient_unavailable", "the selected specialist is missing or archived");
|
|
42522
|
+
}
|
|
42523
|
+
if (recipient.teamId !== team.id) {
|
|
42524
|
+
return blocker("recipient_not_same_team", "the selected specialist left this Team");
|
|
42525
|
+
}
|
|
42526
|
+
if (!getSourceSnapshot(db, team.id, request2.snapshotId, now)) {
|
|
42527
|
+
return blocker(
|
|
42528
|
+
"snapshot_evidence_gone",
|
|
42529
|
+
"the captured change is no longer inside its retention window"
|
|
42530
|
+
);
|
|
42039
42531
|
}
|
|
42040
|
-
|
|
42041
|
-
|
|
42042
|
-
|
|
42532
|
+
return null;
|
|
42533
|
+
};
|
|
42534
|
+
const refusal = await blockedReason();
|
|
42535
|
+
if (refusal) {
|
|
42536
|
+
setRequestState(db, requestId2, "blocked");
|
|
42537
|
+
return { kind: "blocked", requestId: requestId2, blocker: refusal };
|
|
42538
|
+
}
|
|
42539
|
+
const decision = teamPolicyEnforcementEnabled() ? authorizeCommunication(db, authorizationFor(request2, requestId2)) : { decision: "allow" };
|
|
42540
|
+
if (decision.decision === "deny") {
|
|
42541
|
+
setRequestState(db, requestId2, "blocked");
|
|
42542
|
+
return {
|
|
42543
|
+
kind: "blocked",
|
|
42544
|
+
requestId: requestId2,
|
|
42545
|
+
blocker: blocker("policy_denied", "the current Team policy no longer permits this request")
|
|
42546
|
+
};
|
|
42043
42547
|
}
|
|
42044
|
-
|
|
42045
|
-
|
|
42548
|
+
if (decision.decision === "approval_required") {
|
|
42549
|
+
try {
|
|
42550
|
+
if (request2.requesterKind === "agent" && request2.requesterAgentId) {
|
|
42551
|
+
authorizeVerificationRequest(db, {
|
|
42552
|
+
from: request2.requesterAgentId,
|
|
42553
|
+
to: request2.recipientAgentId,
|
|
42554
|
+
requestId: requestId2
|
|
42555
|
+
});
|
|
42556
|
+
} else {
|
|
42557
|
+
authorizeOperatorVerification(db, {
|
|
42558
|
+
agentId: request2.recipientAgentId,
|
|
42559
|
+
requestId: requestId2
|
|
42560
|
+
});
|
|
42561
|
+
}
|
|
42562
|
+
setRequestState(db, requestId2, "blocked");
|
|
42563
|
+
return {
|
|
42564
|
+
kind: "blocked",
|
|
42565
|
+
requestId: requestId2,
|
|
42566
|
+
blocker: blocker("approval_required", "the request was not captured for approval")
|
|
42567
|
+
};
|
|
42568
|
+
} catch {
|
|
42569
|
+
setRequestState(db, requestId2, "awaiting_approval");
|
|
42570
|
+
return { kind: "held", requestId: requestId2 };
|
|
42571
|
+
}
|
|
42572
|
+
}
|
|
42573
|
+
let workspace;
|
|
42574
|
+
try {
|
|
42575
|
+
const team = requireTeam(db, paths, request2.teamId);
|
|
42576
|
+
workspace = await workspaceLifecycle(db).claim(team.id, team.path, "agent");
|
|
42577
|
+
} catch (error2) {
|
|
42578
|
+
if (error2 instanceof WorkspaceBusyError) {
|
|
42579
|
+
return { kind: "deferred", requestId: requestId2, reason: "workspace_busy" };
|
|
42580
|
+
}
|
|
42581
|
+
throw error2;
|
|
42582
|
+
}
|
|
42583
|
+
const claim5 = claimVerificationAttempt(db, {
|
|
42584
|
+
requestId: requestId2,
|
|
42585
|
+
leaseOwner: VERIFICATION_DISPATCH_OWNER,
|
|
42586
|
+
leaseMs: VERIFICATION_LEASE_MS,
|
|
42587
|
+
now
|
|
42588
|
+
});
|
|
42589
|
+
if (!claim5) {
|
|
42590
|
+
await workspaceLifecycle(db).release(workspace);
|
|
42591
|
+
return { kind: "deferred", requestId: requestId2, reason: "already_owned" };
|
|
42592
|
+
}
|
|
42593
|
+
const applicability = await readSnapshotApplicability(
|
|
42594
|
+
db,
|
|
42595
|
+
paths,
|
|
42596
|
+
request2.teamId,
|
|
42597
|
+
request2.snapshotId
|
|
42598
|
+
);
|
|
42599
|
+
if (applicability.comparison !== "identical") {
|
|
42600
|
+
await workspaceLifecycle(db).release(workspace);
|
|
42601
|
+
const reason = applicability.comparison === "changed" ? "source_changed" : "source_unverifiable";
|
|
42602
|
+
const detail3 = applicability.comparison === "changed" ? "the workspace changed after the capture, so a fresh capture is required" : "the workspace could not be shown to match the captured change";
|
|
42603
|
+
settleUnstarted(db, claim5, detail3);
|
|
42604
|
+
setRequestState(db, requestId2, "blocked");
|
|
42605
|
+
return { kind: "blocked", requestId: requestId2, blocker: blocker(reason, detail3) };
|
|
42606
|
+
}
|
|
42607
|
+
return { kind: "admitted", requestId: requestId2, claim: claim5, workspace };
|
|
42608
|
+
}
|
|
42609
|
+
function authorizationFor(request2, requestId2) {
|
|
42610
|
+
const attempt = {
|
|
42611
|
+
origin: "verification_request",
|
|
42612
|
+
attemptKind: "verification_request",
|
|
42613
|
+
attemptId: requestId2
|
|
42614
|
+
};
|
|
42615
|
+
return request2.requesterKind === "agent" && request2.requesterAgentId ? {
|
|
42616
|
+
source: { kind: "agent", id: request2.requesterAgentId },
|
|
42617
|
+
target: { kind: "agent", id: request2.recipientAgentId },
|
|
42618
|
+
...attempt
|
|
42619
|
+
} : {
|
|
42620
|
+
source: { kind: "user", teamId: request2.teamId },
|
|
42621
|
+
target: { kind: "agent", id: request2.recipientAgentId },
|
|
42622
|
+
...attempt
|
|
42623
|
+
};
|
|
42624
|
+
}
|
|
42625
|
+
function settleUnstarted(db, claim5, error2) {
|
|
42626
|
+
db.raw.run(
|
|
42627
|
+
`UPDATE verification_attempts
|
|
42628
|
+
SET state = 'failed', finished_at = ?, lease_owner = NULL, lease_expires_at = NULL, error = ?
|
|
42629
|
+
WHERE id = ? AND lease_owner IS NOT NULL AND finished_at IS NULL`,
|
|
42630
|
+
[Date.now(), error2, claim5.attempt.id]
|
|
42631
|
+
);
|
|
42632
|
+
db.raw.run(
|
|
42633
|
+
`UPDATE verification_check_outcomes SET state = 'blocked', finished_at = ?
|
|
42634
|
+
WHERE attempt_id = ? AND state = 'not_executed'`,
|
|
42635
|
+
[Date.now(), claim5.attempt.id]
|
|
42636
|
+
);
|
|
42637
|
+
}
|
|
42638
|
+
function blocker(reason, detail3) {
|
|
42639
|
+
return { reason, detail: detail3 };
|
|
42640
|
+
}
|
|
42641
|
+
function safeTeam(db, paths, teamId) {
|
|
42642
|
+
try {
|
|
42643
|
+
return requireTeam(db, paths, teamId);
|
|
42644
|
+
} catch {
|
|
42645
|
+
return null;
|
|
42646
|
+
}
|
|
42647
|
+
}
|
|
42648
|
+
|
|
42649
|
+
// ../daemon/src/lib/verification/executor.ts
|
|
42650
|
+
import { randomUUID as randomUUID35 } from "crypto";
|
|
42651
|
+
import { createLocalBashOperations as createLocalBashOperations3 } from "@earendil-works/pi-coding-agent";
|
|
42652
|
+
function createProtectedCheckExecutor(input) {
|
|
42653
|
+
const env = input.env ?? process.env;
|
|
42654
|
+
return {
|
|
42655
|
+
async run({ command, cwd, timeoutMs }) {
|
|
42656
|
+
const config2 = resolveShellSecurityConfig(env);
|
|
42657
|
+
const wantsContainer = input.request.environment.sandbox === "docker";
|
|
42658
|
+
const isContainer = config2.sandboxMode === "docker";
|
|
42659
|
+
if (wantsContainer !== isContainer) {
|
|
42660
|
+
return blocked(
|
|
42661
|
+
"environment_unavailable",
|
|
42662
|
+
wantsContainer ? "this request was captured against a container, but shell isolation is not active" : "this request was captured for host execution, but shell isolation is active"
|
|
42663
|
+
);
|
|
42664
|
+
}
|
|
42665
|
+
if (config2.approvalMode === "dangerous" && classifyBashCommand(command).length > 0) {
|
|
42666
|
+
return blocked(
|
|
42667
|
+
"approval_required",
|
|
42668
|
+
"this check needs a command approval that an unattended verification turn cannot obtain"
|
|
42669
|
+
);
|
|
42670
|
+
}
|
|
42671
|
+
const relative8 = codingRelativePath(cwd || ".");
|
|
42672
|
+
const { path: absoluteCwd } = resolveCodingDirectory(input.teamPath, relative8);
|
|
42673
|
+
const secrets = input.secrets();
|
|
42674
|
+
if (secrets.some((secret) => secret && command.includes(secret))) {
|
|
42675
|
+
return blocked("unsupported", "the captured command contains protected credential material");
|
|
42676
|
+
}
|
|
42677
|
+
const commandId = randomUUID35();
|
|
42678
|
+
const startedAt = Date.now();
|
|
42679
|
+
const receipt = {
|
|
42680
|
+
id: commandId,
|
|
42681
|
+
agentId: input.request.recipientAgentId,
|
|
42682
|
+
teamId: input.request.teamId,
|
|
42683
|
+
turnId: input.attemptId,
|
|
42684
|
+
toolCallId: `verification:${input.attemptId}:${randomUUID35()}`,
|
|
42685
|
+
input: {
|
|
42686
|
+
command,
|
|
42687
|
+
cwd: relative8,
|
|
42688
|
+
purpose: "verification",
|
|
42689
|
+
timeoutSeconds: Math.max(1, Math.round(timeoutMs / 1e3))
|
|
42690
|
+
},
|
|
42691
|
+
environment: {
|
|
42692
|
+
posture: "protected",
|
|
42693
|
+
imageId: isContainer ? input.request.environment.image : null,
|
|
42694
|
+
cwd: relative8,
|
|
42695
|
+
rootIdentity: workspaceIdentity(input.teamPath).rootIdentity,
|
|
42696
|
+
// No repository-context fingerprint is computed for a verification check, so it is absent
|
|
42697
|
+
// rather than invented. Unknown applicability is reported as unknown.
|
|
42698
|
+
inputFingerprint: null,
|
|
42699
|
+
capturedAt: startedAt,
|
|
42700
|
+
// Declared output paths name where a check is expected to write; they do not confine it in
|
|
42701
|
+
// host mode, and the receipt must not imply otherwise. Any write still makes the tree differ
|
|
42702
|
+
// from the captured snapshot, which is reported as `changed` rather than as a pass.
|
|
42703
|
+
restrictions: [
|
|
42704
|
+
...isContainer ? ["network_disabled", "read_only_memory"] : [],
|
|
42705
|
+
"declared_output_paths_are_advisory"
|
|
42706
|
+
]
|
|
42707
|
+
},
|
|
42708
|
+
startedAt,
|
|
42709
|
+
finishedAt: null,
|
|
42710
|
+
state: "running",
|
|
42711
|
+
exitCode: null,
|
|
42712
|
+
diagnostic: "",
|
|
42713
|
+
truncated: false,
|
|
42714
|
+
reason: null,
|
|
42715
|
+
sourceBefore: {
|
|
42716
|
+
id: input.request.snapshotId,
|
|
42717
|
+
complete: input.request.snapshotComplete,
|
|
42718
|
+
capturedAt: input.request.createdAt
|
|
42719
|
+
},
|
|
42720
|
+
sourceAfter: null
|
|
42721
|
+
};
|
|
42722
|
+
saveCodingCommand(input.db, receipt);
|
|
42723
|
+
let observed = "";
|
|
42724
|
+
let observedBytes = 0;
|
|
42725
|
+
let truncatedStream = false;
|
|
42726
|
+
const operations = buildOperations(input, env, config2.envAllowlist);
|
|
42727
|
+
const hostEnv = {
|
|
42728
|
+
...buildScrubbedShellEnv(env, config2.envAllowlist),
|
|
42729
|
+
...input.request.environment.env ?? {}
|
|
42730
|
+
};
|
|
42731
|
+
let exitCode = null;
|
|
42732
|
+
let failure;
|
|
42733
|
+
try {
|
|
42734
|
+
const result = await operations.exec(command, absoluteCwd, {
|
|
42735
|
+
signal: input.signal,
|
|
42736
|
+
timeout: timeoutMs,
|
|
42737
|
+
// Host mode runs with the scrubbed environment above; container mode supplies its own.
|
|
42738
|
+
...isContainer ? {} : { env: hostEnv },
|
|
42739
|
+
onData: (chunk) => {
|
|
42740
|
+
if (observedBytes >= CODING_OUTPUT_BYTES * 4) return;
|
|
42741
|
+
const text3 = chunk.toString("utf8");
|
|
42742
|
+
observed += text3;
|
|
42743
|
+
observedBytes += Buffer.byteLength(text3);
|
|
42744
|
+
}
|
|
42745
|
+
});
|
|
42746
|
+
exitCode = result.exitCode;
|
|
42747
|
+
if (observedBytes > CODING_OUTPUT_BYTES) truncatedStream = true;
|
|
42748
|
+
} catch (error2) {
|
|
42749
|
+
failure = error2;
|
|
42750
|
+
}
|
|
42751
|
+
const finishedAt = Date.now();
|
|
42752
|
+
const redaction = redactJsonValue(observed, secrets);
|
|
42753
|
+
const redacted = redaction !== observed;
|
|
42754
|
+
const tail = diagnosticTail(redaction, CODING_OUTPUT_BYTES);
|
|
42755
|
+
const state3 = resolveState(exitCode, failure, input.signal);
|
|
42756
|
+
receipt.finishedAt = finishedAt;
|
|
42757
|
+
receipt.state = state3;
|
|
42758
|
+
receipt.exitCode = state3 === "succeeded" || state3 === "failed" ? exitCode : null;
|
|
42759
|
+
receipt.diagnostic = tail.text;
|
|
42760
|
+
receipt.truncated = truncatedStream || tail.truncated;
|
|
42761
|
+
receipt.reason = state3 === "blocked" ? "check could not start" : state3 === "timed_out" ? "check exceeded its captured timeout" : state3 === "cancelled" ? "check was cancelled with its turn" : null;
|
|
42762
|
+
saveCodingCommand(input.db, receipt);
|
|
42763
|
+
saveCodingCommandLog(input.db, {
|
|
42764
|
+
commandId,
|
|
42765
|
+
teamId: input.request.teamId,
|
|
42766
|
+
agentId: input.request.recipientAgentId,
|
|
42767
|
+
turnId: input.attemptId,
|
|
42768
|
+
toolCallId: receipt.toolCallId,
|
|
42769
|
+
diagnostic: redaction,
|
|
42770
|
+
observedBytes,
|
|
42771
|
+
redacted,
|
|
42772
|
+
truncated: receipt.truncated
|
|
42773
|
+
});
|
|
42774
|
+
if (state3 === "blocked") {
|
|
42775
|
+
return blocked(
|
|
42776
|
+
"unsupported",
|
|
42777
|
+
failure instanceof Error ? failure.message : "the captured check could not start"
|
|
42778
|
+
);
|
|
42779
|
+
}
|
|
42780
|
+
return {
|
|
42781
|
+
commandId,
|
|
42782
|
+
state: state3,
|
|
42783
|
+
exitCode: state3 === "succeeded" || state3 === "failed" ? exitCode : null,
|
|
42784
|
+
output: tail.text,
|
|
42785
|
+
truncated: receipt.truncated
|
|
42786
|
+
};
|
|
42787
|
+
}
|
|
42788
|
+
};
|
|
42789
|
+
}
|
|
42790
|
+
function buildOperations(input, env, envAllowlist) {
|
|
42791
|
+
if (input.request.environment.sandbox !== "docker") return createLocalBashOperations3();
|
|
42792
|
+
return createDockerBashOperations({
|
|
42793
|
+
image: input.request.environment.image,
|
|
42794
|
+
env: buildSandboxContainerEnv(env, envAllowlist)
|
|
42795
|
+
});
|
|
42796
|
+
}
|
|
42797
|
+
function resolveState(exitCode, failure, signal) {
|
|
42798
|
+
if (signal?.aborted) return "cancelled";
|
|
42799
|
+
if (failure) return "blocked";
|
|
42800
|
+
if (exitCode === null) return "timed_out";
|
|
42801
|
+
return exitCode === 0 ? "succeeded" : "failed";
|
|
42802
|
+
}
|
|
42803
|
+
function blocked(reason, detail3) {
|
|
42804
|
+
return {
|
|
42805
|
+
commandId: null,
|
|
42806
|
+
state: "blocked",
|
|
42807
|
+
exitCode: null,
|
|
42808
|
+
output: detail3,
|
|
42809
|
+
truncated: false,
|
|
42810
|
+
blocker: { reason, detail: detail3 }
|
|
42811
|
+
};
|
|
42812
|
+
}
|
|
42813
|
+
|
|
42814
|
+
// ../daemon/src/lib/verification/preparation.ts
|
|
42815
|
+
async function prepareVerificationTurn(input) {
|
|
42816
|
+
const { db, paths, authToken } = getCtx();
|
|
42817
|
+
const resolved = resolveAgent(db, paths, input.request.recipientAgentId);
|
|
42818
|
+
if (resolved.agent.id !== input.request.recipientAgentId) {
|
|
42819
|
+
throw new Error("verification request does not match the resolved specialist");
|
|
42820
|
+
}
|
|
42821
|
+
const invocation = createTrustedVerificationInvocation({
|
|
42822
|
+
kind: "restricted_verification",
|
|
42823
|
+
authorization: {
|
|
42824
|
+
kind: "request",
|
|
42825
|
+
requestId: input.request.id,
|
|
42826
|
+
attemptId: input.attemptId
|
|
42827
|
+
},
|
|
42828
|
+
bashApprovalMode: "auto_deny"
|
|
42829
|
+
});
|
|
42830
|
+
assertTrustedVerificationInvocation(invocation);
|
|
42831
|
+
const provider = await resolveProtectedProviderRuntime(
|
|
42832
|
+
db,
|
|
42833
|
+
authToken,
|
|
42834
|
+
resolved,
|
|
42835
|
+
resolved.agent.reasoningLevel
|
|
42836
|
+
);
|
|
42837
|
+
return {
|
|
42838
|
+
invocation,
|
|
42839
|
+
spec: {
|
|
42840
|
+
kind: "specialist_verification",
|
|
42841
|
+
agentId: input.request.recipientAgentId,
|
|
42842
|
+
message: verificationPrompt(input.request),
|
|
42843
|
+
turnId: input.attemptId,
|
|
42844
|
+
runtime: provider.runtime,
|
|
42845
|
+
verification: { requestId: input.request.id, attemptId: input.attemptId }
|
|
42846
|
+
},
|
|
42847
|
+
refreshApiKey: provider.refreshApiKey
|
|
42848
|
+
};
|
|
42849
|
+
}
|
|
42850
|
+
function verificationPrompt(request2) {
|
|
42851
|
+
return `Verify the captured change for verification request ${request2.id}.
|
|
42852
|
+
|
|
42853
|
+
Call verification_request to read the captured change, its environment and the checks your requester selected. Then run each declared check with verification_check, using its ordinal. Each check runs once; report failures as failures and blockers as blockers.`;
|
|
42854
|
+
}
|
|
42855
|
+
function bindVerificationCapability(host2, identity2) {
|
|
42856
|
+
const assertBound = (requestId2, attemptId) => {
|
|
42857
|
+
if (requestId2 !== identity2.requestId || attemptId !== identity2.attemptId) {
|
|
42858
|
+
throw new Error("verification capability is bound to a different request attempt");
|
|
42859
|
+
}
|
|
42860
|
+
};
|
|
42861
|
+
return {
|
|
42862
|
+
read: async (requestId2, attemptId) => {
|
|
42863
|
+
assertBound(requestId2, attemptId);
|
|
42864
|
+
return host2.read();
|
|
42865
|
+
},
|
|
42866
|
+
run: async (requestId2, attemptId, ordinal) => {
|
|
42867
|
+
assertBound(requestId2, attemptId);
|
|
42868
|
+
return host2.invoke(ordinal);
|
|
42869
|
+
}
|
|
42870
|
+
};
|
|
42871
|
+
}
|
|
42872
|
+
function executePreparedVerification(prepared, opts) {
|
|
42873
|
+
assertTrustedVerificationInvocation(prepared.invocation);
|
|
42874
|
+
return spawnVerificationWorker(prepared.spec, {
|
|
42875
|
+
signal: opts.signal,
|
|
42876
|
+
apiKeyRefreshHost: { refresh: prepared.refreshApiKey },
|
|
42877
|
+
verificationHost: opts.verificationHost,
|
|
42878
|
+
...opts.workerEntryPath ? { workerEntryPath: opts.workerEntryPath } : {}
|
|
42879
|
+
});
|
|
42880
|
+
}
|
|
42881
|
+
|
|
42882
|
+
// ../daemon/src/lib/verification/result.ts
|
|
42883
|
+
var MAX_RESULT_CHARACTERS = 4e3;
|
|
42884
|
+
function deliverVerificationResult(input) {
|
|
42885
|
+
const { request: request2 } = input;
|
|
42886
|
+
if (request2.requesterKind !== "agent" || !request2.requesterAgentId) return false;
|
|
42887
|
+
const payload = renderResult(input);
|
|
42888
|
+
try {
|
|
42889
|
+
sendAgentMessage(input.db, {
|
|
42890
|
+
from: request2.recipientAgentId,
|
|
42891
|
+
to: request2.requesterAgentId,
|
|
42892
|
+
payload,
|
|
42893
|
+
origin: "verification_result",
|
|
42894
|
+
attemptKind: "verification_result",
|
|
42895
|
+
// Per attempt, not per request: a rerun's result is its own delivery, and reusing the request id
|
|
42896
|
+
// would collide with the first attempt's approval identity if the edge requires approval.
|
|
42897
|
+
attemptId: `${request2.id}:${input.attempt.id}`
|
|
42898
|
+
});
|
|
42899
|
+
return true;
|
|
42900
|
+
} catch (error2) {
|
|
42901
|
+
console.warn(
|
|
42902
|
+
JSON.stringify({
|
|
42903
|
+
event: "verification_result_not_delivered",
|
|
42904
|
+
requestId: request2.id,
|
|
42905
|
+
errorName: error2 instanceof Error ? error2.name : "unknown"
|
|
42906
|
+
})
|
|
42907
|
+
);
|
|
42908
|
+
return false;
|
|
42909
|
+
}
|
|
42910
|
+
}
|
|
42911
|
+
function renderResult(input) {
|
|
42912
|
+
const { request: request2, attempt } = input;
|
|
42913
|
+
const checks = listVerificationChecks(input.db, request2.id);
|
|
42914
|
+
const outcomes = new Map(
|
|
42915
|
+
listVerificationCheckOutcomes(input.db, attempt.id).map((outcome) => [
|
|
42916
|
+
outcome.ordinal,
|
|
42917
|
+
outcome
|
|
42918
|
+
])
|
|
42919
|
+
);
|
|
42920
|
+
const lines = [
|
|
42921
|
+
`Verification ${request2.id}: ${input.outcome}.`,
|
|
42922
|
+
`Change: snapshot ${request2.snapshotId} (base ${request2.baseOid.slice(0, 12)}${request2.snapshotComplete ? "" : ", INCOMPLETE COVERAGE"}).`,
|
|
42923
|
+
`Environment: image ${request2.environment.image}, shell ${request2.environment.sandbox}.`,
|
|
42924
|
+
input.applicability === null ? "Applicability: not checked." : `Applicability: ${input.applicability === "identical" ? "unchanged since capture" : input.applicability}.`,
|
|
42925
|
+
"",
|
|
42926
|
+
"Checks:"
|
|
42927
|
+
];
|
|
42928
|
+
for (const check of checks) {
|
|
42929
|
+
const outcome = outcomes.get(check.ordinal);
|
|
42930
|
+
const state3 = outcome?.state ?? "not_executed";
|
|
42931
|
+
const exit = outcome?.exitCode === null || outcome?.exitCode === void 0 ? "" : ` exit ${outcome.exitCode}`;
|
|
42932
|
+
const receipt = outcome?.commandId ? ` coding-receipt:${outcome.commandId}` : outcome && ["succeeded", "failed", "timed_out", "cancelled"].includes(outcome.state) ? " (receipt no longer available)" : "";
|
|
42933
|
+
lines.push(` [${check.ordinal}] ${state3}${exit} \u2014 ${check.command}${receipt}`);
|
|
42934
|
+
}
|
|
42935
|
+
if (attempt.error) lines.push("", `Limitation: ${attempt.error}`);
|
|
42936
|
+
lines.push(
|
|
42937
|
+
"",
|
|
42938
|
+
"Facts above are executor-owned. A non-zero exit is a result about the commands that ran, never",
|
|
42939
|
+
"proof about later code, and this is not an approval to publish, merge or deploy."
|
|
42940
|
+
);
|
|
42941
|
+
const payload = lines.join("\n");
|
|
42942
|
+
return payload.length > MAX_RESULT_CHARACTERS ? `${payload.slice(0, MAX_RESULT_CHARACTERS)}
|
|
42943
|
+
[result truncated]` : payload;
|
|
42944
|
+
}
|
|
42945
|
+
|
|
42946
|
+
// ../daemon/src/runtime/tools/verification.ts
|
|
42947
|
+
var VerificationCapabilityError = class extends Error {
|
|
42948
|
+
constructor(message) {
|
|
42949
|
+
super(message);
|
|
42950
|
+
this.name = "VerificationCapabilityError";
|
|
42951
|
+
}
|
|
42952
|
+
};
|
|
42953
|
+
|
|
42954
|
+
// ../daemon/src/lib/verification/runner.ts
|
|
42955
|
+
function createVerificationHost(input) {
|
|
42956
|
+
const { db, request: request2, attemptId, executor } = input;
|
|
42957
|
+
return {
|
|
42958
|
+
async read() {
|
|
42959
|
+
const declared = listVerificationChecks(db, request2.id);
|
|
42960
|
+
const outcomes = new Map(
|
|
42961
|
+
listVerificationCheckOutcomes(db, attemptId).map((outcome) => [outcome.ordinal, outcome])
|
|
42962
|
+
);
|
|
42963
|
+
const checks = declared.map((check) => {
|
|
42964
|
+
const outcome = outcomes.get(check.ordinal);
|
|
42965
|
+
return {
|
|
42966
|
+
ordinal: check.ordinal,
|
|
42967
|
+
command: check.command,
|
|
42968
|
+
cwd: check.cwd,
|
|
42969
|
+
purpose: check.purpose,
|
|
42970
|
+
timeoutMs: check.timeoutMs,
|
|
42971
|
+
state: outcome?.state ?? "not_executed",
|
|
42972
|
+
commandId: outcome?.commandId ?? null,
|
|
42973
|
+
exitCode: outcome?.exitCode ?? null
|
|
42974
|
+
};
|
|
42975
|
+
});
|
|
42976
|
+
return {
|
|
42977
|
+
requestId: request2.id,
|
|
42978
|
+
summary: request2.summary,
|
|
42979
|
+
snapshot: {
|
|
42980
|
+
id: request2.snapshotId,
|
|
42981
|
+
complete: request2.snapshotComplete,
|
|
42982
|
+
head: request2.head,
|
|
42983
|
+
baseOid: request2.baseOid
|
|
42984
|
+
},
|
|
42985
|
+
environment: {
|
|
42986
|
+
image: request2.environment.image,
|
|
42987
|
+
sandbox: request2.environment.sandbox,
|
|
42988
|
+
...request2.environment.cwd ? { cwd: request2.environment.cwd } : {}
|
|
42989
|
+
},
|
|
42990
|
+
writablePaths: request2.environment.writablePaths ?? [],
|
|
42991
|
+
checks,
|
|
42992
|
+
applicability: input.applicability
|
|
42993
|
+
};
|
|
42994
|
+
},
|
|
42995
|
+
async invoke(ordinal) {
|
|
42996
|
+
const declared = listVerificationChecks(db, request2.id).find(
|
|
42997
|
+
(check) => check.ordinal === ordinal
|
|
42998
|
+
);
|
|
42999
|
+
if (!declared) {
|
|
43000
|
+
throw new VerificationCapabilityError(`check ${ordinal} was not captured with this request`);
|
|
43001
|
+
}
|
|
43002
|
+
const settled = listVerificationCheckOutcomes(db, attemptId).find(
|
|
43003
|
+
(outcome) => outcome.ordinal === ordinal
|
|
43004
|
+
);
|
|
43005
|
+
if (settled && settled.state !== "not_executed") {
|
|
43006
|
+
throw new VerificationCapabilityError(
|
|
43007
|
+
`check ${ordinal} already reported '${settled.state}' and cannot be run again`
|
|
43008
|
+
);
|
|
43009
|
+
}
|
|
43010
|
+
const startedAt = Date.now();
|
|
43011
|
+
let result;
|
|
43012
|
+
try {
|
|
43013
|
+
result = await executor.run({
|
|
43014
|
+
command: declared.command,
|
|
43015
|
+
cwd: declared.cwd,
|
|
43016
|
+
timeoutMs: declared.timeoutMs,
|
|
43017
|
+
purpose: "verification",
|
|
43018
|
+
writablePaths: request2.environment.writablePaths ?? []
|
|
43019
|
+
});
|
|
43020
|
+
} catch (error2) {
|
|
43021
|
+
throw error2 instanceof Error ? error2 : new Error("verification check failed to start");
|
|
43022
|
+
}
|
|
43023
|
+
const state3 = normalizeState(result.state);
|
|
43024
|
+
if (state3 !== "blocked" && !result.commandId) {
|
|
43025
|
+
throw new VerificationCapabilityError(
|
|
43026
|
+
`a ${state3} check must report the receipt that produced it`
|
|
43027
|
+
);
|
|
43028
|
+
}
|
|
43029
|
+
const recorded = recordVerificationCheckOutcome(db, {
|
|
43030
|
+
attemptId,
|
|
43031
|
+
ordinal,
|
|
43032
|
+
state: state3,
|
|
43033
|
+
commandId: state3 === "blocked" ? null : result.commandId,
|
|
43034
|
+
exitCode: state3 === "succeeded" || state3 === "failed" ? result.exitCode : null,
|
|
43035
|
+
startedAt,
|
|
43036
|
+
finishedAt: Date.now()
|
|
43037
|
+
});
|
|
43038
|
+
if (!recorded) {
|
|
43039
|
+
throw new VerificationCapabilityError(`check ${ordinal} was already settled`);
|
|
43040
|
+
}
|
|
43041
|
+
return {
|
|
43042
|
+
ordinal,
|
|
43043
|
+
state: state3,
|
|
43044
|
+
commandId: state3 === "blocked" ? null : result.commandId,
|
|
43045
|
+
exitCode: state3 === "succeeded" || state3 === "failed" ? result.exitCode : null,
|
|
43046
|
+
output: result.output,
|
|
43047
|
+
truncated: result.truncated
|
|
43048
|
+
};
|
|
43049
|
+
}
|
|
43050
|
+
};
|
|
43051
|
+
}
|
|
43052
|
+
function normalizeState(state3) {
|
|
43053
|
+
return state3;
|
|
43054
|
+
}
|
|
43055
|
+
function settleVerificationAttempt(db, input) {
|
|
43056
|
+
const now = input.now ?? Date.now();
|
|
43057
|
+
const owned = db.raw.query(
|
|
43058
|
+
`SELECT id FROM verification_attempts
|
|
43059
|
+
WHERE id = ? AND lease_owner = ? AND finished_at IS NULL`
|
|
43060
|
+
).get(input.attemptId, input.leaseOwner);
|
|
43061
|
+
if (!owned) return "uncertain";
|
|
43062
|
+
const declared = listVerificationChecks(db, input.requestId);
|
|
43063
|
+
const outcomes = new Map(
|
|
43064
|
+
listVerificationCheckOutcomes(db, input.attemptId).map((outcome) => [outcome.ordinal, outcome])
|
|
43065
|
+
);
|
|
43066
|
+
for (const check of declared) {
|
|
43067
|
+
const outcome = outcomes.get(check.ordinal);
|
|
43068
|
+
if (!outcome || outcome.state === "not_executed") {
|
|
43069
|
+
db.raw.run(
|
|
43070
|
+
`UPDATE verification_check_outcomes SET state = 'skipped', finished_at = ?
|
|
43071
|
+
WHERE attempt_id = ? AND ordinal = ? AND state = 'not_executed'`,
|
|
43072
|
+
[now, input.attemptId, check.ordinal]
|
|
43073
|
+
);
|
|
43074
|
+
}
|
|
43075
|
+
}
|
|
43076
|
+
const settled = listVerificationCheckOutcomes(db, input.attemptId);
|
|
43077
|
+
const executed = settled.filter(
|
|
43078
|
+
(outcome) => ["succeeded", "failed"].includes(outcome.state)
|
|
43079
|
+
).length;
|
|
43080
|
+
const state3 = executed > 0 ? "completed" : "failed";
|
|
43081
|
+
const error2 = state3 === "failed" ? "no captured check executed" : null;
|
|
43082
|
+
const finished = finishVerificationAttempt(db, {
|
|
43083
|
+
attemptId: input.attemptId,
|
|
43084
|
+
leaseOwner: input.leaseOwner,
|
|
43085
|
+
state: state3,
|
|
43086
|
+
error: error2,
|
|
43087
|
+
now
|
|
43088
|
+
});
|
|
43089
|
+
if (!finished) {
|
|
43090
|
+
return "uncertain";
|
|
43091
|
+
}
|
|
43092
|
+
setRequestState(db, input.requestId, state3);
|
|
43093
|
+
return state3;
|
|
43094
|
+
}
|
|
43095
|
+
function abandonVerificationAttempt(db, input) {
|
|
43096
|
+
const now = input.now ?? Date.now();
|
|
43097
|
+
const finished = finishVerificationAttempt(db, {
|
|
43098
|
+
attemptId: input.attemptId,
|
|
43099
|
+
leaseOwner: input.leaseOwner,
|
|
43100
|
+
state: input.state,
|
|
43101
|
+
error: input.error,
|
|
43102
|
+
now
|
|
43103
|
+
});
|
|
43104
|
+
if (!finished) return false;
|
|
43105
|
+
db.raw.run(
|
|
43106
|
+
`UPDATE verification_check_outcomes
|
|
43107
|
+
SET state = 'unknown', finished_at = ?
|
|
43108
|
+
WHERE attempt_id = ? AND state = 'not_executed'`,
|
|
43109
|
+
[now, input.attemptId]
|
|
43110
|
+
);
|
|
43111
|
+
setRequestState(db, input.requestId, input.state);
|
|
43112
|
+
return true;
|
|
43113
|
+
}
|
|
43114
|
+
|
|
43115
|
+
// ../daemon/src/lib/verification/dispatch.ts
|
|
43116
|
+
var DISPATCH_REGISTRY_KEY = /* @__PURE__ */ Symbol.for("bazilion.verification.dispatch");
|
|
43117
|
+
function dispatchRegistry() {
|
|
43118
|
+
const host2 = globalThis;
|
|
43119
|
+
host2[DISPATCH_REGISTRY_KEY] ??= { controllers: /* @__PURE__ */ new Map() };
|
|
43120
|
+
return host2[DISPATCH_REGISTRY_KEY];
|
|
43121
|
+
}
|
|
43122
|
+
function cancelVerificationDispatch(requestId2) {
|
|
43123
|
+
const controller = dispatchRegistry().controllers.get(requestId2);
|
|
43124
|
+
if (!controller) return false;
|
|
43125
|
+
controller.abort();
|
|
43126
|
+
return true;
|
|
43127
|
+
}
|
|
43128
|
+
async function dispatchVerificationRequest(requestId2, opts = {}) {
|
|
43129
|
+
const { db, paths } = getCtx();
|
|
43130
|
+
const request2 = getVerificationRequestById(db, requestId2);
|
|
43131
|
+
if (!request2) return "not_dispatchable";
|
|
43132
|
+
if (isActiveAgent(request2.recipientAgentId)) return "agent_busy";
|
|
43133
|
+
const releaseLease = await acquireAgentLifecycleLease(request2.recipientAgentId);
|
|
43134
|
+
const controller = new AbortController();
|
|
43135
|
+
let registered = false;
|
|
43136
|
+
try {
|
|
43137
|
+
if (isActiveAgent(request2.recipientAgentId)) return "agent_busy";
|
|
43138
|
+
registerAgent(request2.recipientAgentId, controller);
|
|
43139
|
+
registered = true;
|
|
43140
|
+
} finally {
|
|
43141
|
+
releaseLease();
|
|
43142
|
+
}
|
|
43143
|
+
if (opts.signal) opts.signal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
43144
|
+
dispatchRegistry().controllers.set(requestId2, controller);
|
|
43145
|
+
let admission;
|
|
43146
|
+
try {
|
|
43147
|
+
admission = await admitVerificationRequest(db, paths, requestId2);
|
|
43148
|
+
if (admission.kind !== "admitted") return "not_dispatchable";
|
|
43149
|
+
const admitted = admission;
|
|
43150
|
+
const live2 = getVerificationRequest(db, request2.teamId, requestId2);
|
|
43151
|
+
if (!live2) {
|
|
43152
|
+
await workspaceLifecycle(db).release(admitted.workspace);
|
|
43153
|
+
settleVerificationAttempt(db, {
|
|
43154
|
+
attemptId: admitted.claim.attempt.id,
|
|
43155
|
+
requestId: requestId2,
|
|
43156
|
+
leaseOwner: VERIFICATION_DISPATCH_OWNER
|
|
43157
|
+
});
|
|
43158
|
+
return "settled";
|
|
43159
|
+
}
|
|
43160
|
+
const prepared = await prepareVerificationTurn({
|
|
43161
|
+
request: live2,
|
|
43162
|
+
attemptId: admitted.claim.attempt.id
|
|
43163
|
+
});
|
|
43164
|
+
const capability = bindVerificationCapability(
|
|
43165
|
+
createVerificationHost({
|
|
43166
|
+
db,
|
|
43167
|
+
request: live2,
|
|
43168
|
+
attemptId: admitted.claim.attempt.id,
|
|
43169
|
+
applicability: "identical",
|
|
43170
|
+
executor: createProtectedCheckExecutor({
|
|
43171
|
+
db,
|
|
43172
|
+
paths,
|
|
43173
|
+
request: live2,
|
|
43174
|
+
attemptId: admitted.claim.attempt.id,
|
|
43175
|
+
teamPath: paths.teamDir(live2.teamId),
|
|
43176
|
+
secrets: () => currentSecrets(),
|
|
43177
|
+
signal: controller.signal
|
|
43178
|
+
})
|
|
43179
|
+
}),
|
|
43180
|
+
{ requestId: requestId2, attemptId: admitted.claim.attempt.id }
|
|
43181
|
+
);
|
|
43182
|
+
let failure = null;
|
|
43183
|
+
for await (const frame of executePreparedVerification(prepared, {
|
|
43184
|
+
verificationHost: capability,
|
|
43185
|
+
signal: controller.signal,
|
|
43186
|
+
...opts.workerEntryPath ? { workerEntryPath: opts.workerEntryPath } : {}
|
|
43187
|
+
})) {
|
|
43188
|
+
if (frame.kind === "fatal") failure ??= frame.error;
|
|
43189
|
+
else if (frame.kind === "event" && frame.event.type === "error") failure ??= frame.event.error;
|
|
43190
|
+
}
|
|
43191
|
+
if (controller.signal.aborted) {
|
|
43192
|
+
const abandoned = abandonVerificationAttempt(db, {
|
|
43193
|
+
attemptId: admitted.claim.attempt.id,
|
|
43194
|
+
requestId: requestId2,
|
|
43195
|
+
leaseOwner: VERIFICATION_DISPATCH_OWNER,
|
|
43196
|
+
state: "cancelled",
|
|
43197
|
+
error: "verification was cancelled before it reported"
|
|
43198
|
+
});
|
|
43199
|
+
if (abandoned) await handBackResult(db, paths, requestId2, "cancelled");
|
|
43200
|
+
return "settled";
|
|
43201
|
+
}
|
|
43202
|
+
if (failure) {
|
|
43203
|
+
const abandoned = abandonVerificationAttempt(db, {
|
|
43204
|
+
attemptId: admitted.claim.attempt.id,
|
|
43205
|
+
requestId: requestId2,
|
|
43206
|
+
leaseOwner: VERIFICATION_DISPATCH_OWNER,
|
|
43207
|
+
state: "failed",
|
|
43208
|
+
error: failure
|
|
43209
|
+
});
|
|
43210
|
+
if (abandoned) await handBackResult(db, paths, requestId2, "failed");
|
|
43211
|
+
return "settled";
|
|
43212
|
+
}
|
|
43213
|
+
const settled = settleVerificationAttempt(db, {
|
|
43214
|
+
attemptId: admitted.claim.attempt.id,
|
|
43215
|
+
requestId: requestId2,
|
|
43216
|
+
leaseOwner: VERIFICATION_DISPATCH_OWNER
|
|
43217
|
+
});
|
|
43218
|
+
if (settled !== "uncertain") await handBackResult(db, paths, requestId2, settled);
|
|
43219
|
+
return "dispatched";
|
|
43220
|
+
} catch (error2) {
|
|
43221
|
+
if (admission?.kind === "admitted") {
|
|
43222
|
+
abandonVerificationAttempt(db, {
|
|
43223
|
+
attemptId: admission.claim.attempt.id,
|
|
43224
|
+
requestId: requestId2,
|
|
43225
|
+
leaseOwner: VERIFICATION_DISPATCH_OWNER,
|
|
43226
|
+
state: controller.signal.aborted ? "cancelled" : "failed",
|
|
43227
|
+
error: protectedFailureMessage(error2, "Verification")
|
|
43228
|
+
});
|
|
43229
|
+
}
|
|
43230
|
+
return "settled";
|
|
43231
|
+
} finally {
|
|
43232
|
+
if (admission?.kind === "admitted") await workspaceLifecycle(db).release(admission.workspace);
|
|
43233
|
+
dispatchRegistry().controllers.delete(requestId2);
|
|
43234
|
+
if (registered) unregisterAgent(request2.recipientAgentId);
|
|
43235
|
+
}
|
|
43236
|
+
}
|
|
43237
|
+
async function handBackResult(db, paths, requestId2, outcome) {
|
|
43238
|
+
const request2 = getVerificationRequestById(db, requestId2);
|
|
43239
|
+
if (!request2) return;
|
|
43240
|
+
const attempt = listVerificationAttempts(db, requestId2).at(-1);
|
|
43241
|
+
if (!attempt) return;
|
|
43242
|
+
let applicability = null;
|
|
43243
|
+
try {
|
|
43244
|
+
const comparison = await readSnapshotApplicability(
|
|
43245
|
+
db,
|
|
43246
|
+
paths,
|
|
43247
|
+
request2.teamId,
|
|
43248
|
+
request2.snapshotId
|
|
43249
|
+
);
|
|
43250
|
+
applicability = comparison.comparison;
|
|
43251
|
+
} catch {
|
|
43252
|
+
applicability = null;
|
|
43253
|
+
}
|
|
43254
|
+
deliverVerificationResult({ db, paths, request: request2, attempt, outcome, applicability });
|
|
43255
|
+
}
|
|
43256
|
+
async function dispatchPendingVerifications(now = Date.now()) {
|
|
43257
|
+
const { db, paths } = getCtx();
|
|
43258
|
+
pruneVerificationRequests(db, now);
|
|
43259
|
+
const pending = db.raw.query(
|
|
43260
|
+
`SELECT id FROM verification_requests
|
|
43261
|
+
WHERE state = 'pending' AND expires_at > ?
|
|
43262
|
+
ORDER BY created_at LIMIT 20`
|
|
43263
|
+
).all(now);
|
|
43264
|
+
void paths;
|
|
43265
|
+
await Promise.allSettled(pending.map((row) => dispatchVerificationRequest(row.id)));
|
|
43266
|
+
}
|
|
43267
|
+
function currentSecrets() {
|
|
43268
|
+
const { db, authToken } = getCtx();
|
|
43269
|
+
return codingSecrets(mergeSecretsIntoEnv(db, authToken));
|
|
43270
|
+
}
|
|
43271
|
+
|
|
43272
|
+
// ../daemon/src/lib/scheduler.ts
|
|
43273
|
+
var SCHEDULER_KEY = /* @__PURE__ */ Symbol.for("bazilion.scheduler");
|
|
43274
|
+
var TICK_MS = Number(process.env.BAZILION_SCHEDULER_TICK_MS ?? 5e3);
|
|
43275
|
+
function state2() {
|
|
43276
|
+
const g2 = globalThis;
|
|
43277
|
+
let s = g2[SCHEDULER_KEY];
|
|
43278
|
+
if (!s) {
|
|
43279
|
+
s = { timer: null, firing: /* @__PURE__ */ new Set(), cronCache: /* @__PURE__ */ new Map(), stopped: false };
|
|
43280
|
+
g2[SCHEDULER_KEY] = s;
|
|
43281
|
+
}
|
|
43282
|
+
return s;
|
|
43283
|
+
}
|
|
43284
|
+
function floorToMinute(ms) {
|
|
43285
|
+
return Math.floor(ms / 6e4) * 6e4;
|
|
43286
|
+
}
|
|
43287
|
+
function isDue(t, now, cronCache) {
|
|
43288
|
+
if (!t.enabled) return false;
|
|
43289
|
+
if (t.kind === "interval") {
|
|
43290
|
+
const every = (t.intervalSec ?? 0) * 1e3;
|
|
43291
|
+
if (every <= 0) return false;
|
|
43292
|
+
const baseline = t.lastFiredAt ?? t.createdAt;
|
|
43293
|
+
return now - baseline >= every;
|
|
43294
|
+
}
|
|
43295
|
+
if (t.kind === "cron") {
|
|
43296
|
+
if (!t.cronExpr) return false;
|
|
43297
|
+
let parsed = cronCache.get(t.cronExpr);
|
|
43298
|
+
if (!parsed) {
|
|
43299
|
+
try {
|
|
43300
|
+
parsed = parseCron(t.cronExpr);
|
|
43301
|
+
} catch {
|
|
43302
|
+
return false;
|
|
43303
|
+
}
|
|
43304
|
+
cronCache.set(t.cronExpr, parsed);
|
|
43305
|
+
}
|
|
43306
|
+
const nowFloor = floorToMinute(now);
|
|
43307
|
+
if (t.lastFiredAt && floorToMinute(t.lastFiredAt) === nowFloor) return false;
|
|
43308
|
+
return matchesCron(parsed, new Date(nowFloor));
|
|
43309
|
+
}
|
|
43310
|
+
return false;
|
|
43311
|
+
}
|
|
42046
43312
|
function scheduledOccurrence(t, now) {
|
|
42047
43313
|
if (t.kind === "cron") return floorToMinute(now);
|
|
42048
43314
|
const baseline = t.lastFiredAt ?? t.createdAt;
|
|
@@ -42404,6 +43670,7 @@ async function tick() {
|
|
|
42404
43670
|
work.push(fireInboxWake(agentId));
|
|
42405
43671
|
}
|
|
42406
43672
|
work.push(dispatchClaimableReviews(now));
|
|
43673
|
+
work.push(dispatchPendingVerifications(now));
|
|
42407
43674
|
await Promise.allSettled(work);
|
|
42408
43675
|
}
|
|
42409
43676
|
function startScheduler() {
|
|
@@ -42463,6 +43730,7 @@ function bootstrap(paths) {
|
|
|
42463
43730
|
recoverInterrupted2(db);
|
|
42464
43731
|
recoverInterrupted(db);
|
|
42465
43732
|
interruptCodingCommands(db);
|
|
43733
|
+
recoverInterruptedVerificationAttempts(db, VERIFICATION_DISPATCH_OWNER);
|
|
42466
43734
|
reconcileApprovalHolds(db);
|
|
42467
43735
|
recoverInterruptedResultDeliveries(db);
|
|
42468
43736
|
reconcilePrivateResults(db);
|
|
@@ -42630,7 +43898,7 @@ async function authMiddleware(c, next) {
|
|
|
42630
43898
|
}
|
|
42631
43899
|
|
|
42632
43900
|
// ../daemon/src/routes/agents.ts
|
|
42633
|
-
import { randomUUID as
|
|
43901
|
+
import { randomUUID as randomUUID37 } from "crypto";
|
|
42634
43902
|
import { existsSync as existsSync18, readFileSync as readFileSync12 } from "fs";
|
|
42635
43903
|
import { join as join28 } from "path";
|
|
42636
43904
|
import { Hono } from "hono";
|
|
@@ -43955,7 +45223,7 @@ async function notifyTelegramQueueStatus(db, agentId, itemId) {
|
|
|
43955
45223
|
}
|
|
43956
45224
|
|
|
43957
45225
|
// ../daemon/src/lib/user-queue-admission.ts
|
|
43958
|
-
import { randomUUID as
|
|
45226
|
+
import { randomUUID as randomUUID36 } from "crypto";
|
|
43959
45227
|
async function enqueueTelegramInput(binding, message, attachments2, context = getCtx()) {
|
|
43960
45228
|
validateInput(message, attachments2);
|
|
43961
45229
|
const { db, paths, authToken } = context;
|
|
@@ -43974,7 +45242,7 @@ async function enqueueTelegramInput(binding, message, attachments2, context = ge
|
|
|
43974
45242
|
const existing = findAttempt(db, "telegram", binding.authorization.attemptId);
|
|
43975
45243
|
return db.raw.transaction(() => {
|
|
43976
45244
|
const item = accept(db, {
|
|
43977
|
-
id: existing?.id ??
|
|
45245
|
+
id: existing?.id ?? randomUUID36(),
|
|
43978
45246
|
agentId,
|
|
43979
45247
|
teamId: existing?.teamId ?? agent.team.id,
|
|
43980
45248
|
conversationId,
|
|
@@ -45794,7 +47062,7 @@ agentsRouter.post("/:id/chat", async (c) => {
|
|
|
45794
47062
|
if (!message && attachments2.length === 0) {
|
|
45795
47063
|
return c.json({ error: "message or an attachment is required" }, 400);
|
|
45796
47064
|
}
|
|
45797
|
-
const requestAttemptId = c.req.header("x-request-id") ??
|
|
47065
|
+
const requestAttemptId = c.req.header("x-request-id") ?? randomUUID37();
|
|
45798
47066
|
let preparedTurn;
|
|
45799
47067
|
try {
|
|
45800
47068
|
preparedTurn = await prepareAgentTurn({
|
|
@@ -46257,6 +47525,9 @@ import { Bot as Bot2, InputFile as InputFile2 } from "grammy";
|
|
|
46257
47525
|
import { Hono as Hono2 } from "hono";
|
|
46258
47526
|
|
|
46259
47527
|
// ../daemon/src/lib/approval-delivery-plan.ts
|
|
47528
|
+
function isTelegramDeliveryPlan(plan) {
|
|
47529
|
+
return plan.kind === "telegram_text" || plan.kind === "telegram_typing" || plan.kind === "telegram_image" || plan.kind === "telegram_file";
|
|
47530
|
+
}
|
|
46260
47531
|
var ApprovalDeliveryValidationError = class extends Error {
|
|
46261
47532
|
constructor(code) {
|
|
46262
47533
|
super(`approval_delivery_invalid: ${code}`);
|
|
@@ -46297,6 +47568,14 @@ function planApprovalDelivery(approval, context = {}) {
|
|
|
46297
47568
|
return invalid3("question_binding");
|
|
46298
47569
|
}
|
|
46299
47570
|
}
|
|
47571
|
+
if (approval.payloadKind === "verification_request") {
|
|
47572
|
+
const payload = approval.payload;
|
|
47573
|
+
if (approval.operation !== "request_verification" || approval.origin !== "verification_request" || !isRecord3(payload) || Object.keys(payload).sort().join(",") !== "requestId" || typeof payload.requestId !== "string" || !/^[0-9a-f-]{36}$/i.test(payload.requestId))
|
|
47574
|
+
return invalid3("verification_request_payload");
|
|
47575
|
+
requireAttemptKind(approval, "verification_request");
|
|
47576
|
+
if (approval.attemptId !== payload.requestId) return invalid3("verification_request_attempt");
|
|
47577
|
+
return { kind: "verification_request", approval, payload: { requestId: payload.requestId } };
|
|
47578
|
+
}
|
|
46300
47579
|
if (approval.payloadKind === "queued_user") {
|
|
46301
47580
|
const payload = validateQueuedUserApproval(approval, context.queuedInput ?? (() => null));
|
|
46302
47581
|
return { kind: "queued_user", approval, payload };
|
|
@@ -46678,6 +47957,40 @@ async function deliverQueuedApproval(approval) {
|
|
|
46678
47957
|
}
|
|
46679
47958
|
}
|
|
46680
47959
|
|
|
47960
|
+
// ../daemon/src/lib/verification/approval.ts
|
|
47961
|
+
function validateVerificationGrant(db, paths, requestId2) {
|
|
47962
|
+
const request2 = getVerificationRequestByIdSafe(db, requestId2);
|
|
47963
|
+
if (!request2) return "verification request is unknown or past its retention window";
|
|
47964
|
+
if (request2.state !== "awaiting_approval") {
|
|
47965
|
+
return `verification request is ${request2.state}, not awaiting approval`;
|
|
47966
|
+
}
|
|
47967
|
+
const team = safeTeam2(db, paths, request2.teamId);
|
|
47968
|
+
if (!team) return "verification request no longer names a known Team";
|
|
47969
|
+
const recipient = get(db, request2.recipientAgentId);
|
|
47970
|
+
if (!recipient || recipient.status === "archived") {
|
|
47971
|
+
return "the selected specialist is missing or archived";
|
|
47972
|
+
}
|
|
47973
|
+
if (recipient.teamId !== team.id) return "the selected specialist left this Team";
|
|
47974
|
+
if (!getSourceSnapshot(db, team.id, request2.snapshotId)) {
|
|
47975
|
+
return "the captured change is no longer inside its retention window";
|
|
47976
|
+
}
|
|
47977
|
+
return null;
|
|
47978
|
+
}
|
|
47979
|
+
function releaseVerificationGrant(db, requestId2) {
|
|
47980
|
+
const request2 = getVerificationRequestByIdSafe(db, requestId2);
|
|
47981
|
+
if (request2?.state === "awaiting_approval") setRequestState(db, requestId2, "pending");
|
|
47982
|
+
}
|
|
47983
|
+
function getVerificationRequestByIdSafe(db, requestId2) {
|
|
47984
|
+
return getVerificationRequestById(db, requestId2);
|
|
47985
|
+
}
|
|
47986
|
+
function safeTeam2(db, paths, teamId) {
|
|
47987
|
+
try {
|
|
47988
|
+
return requireTeam(db, paths, teamId);
|
|
47989
|
+
} catch {
|
|
47990
|
+
return null;
|
|
47991
|
+
}
|
|
47992
|
+
}
|
|
47993
|
+
|
|
46681
47994
|
// ../daemon/src/routes/approvals.ts
|
|
46682
47995
|
var approvalsRouter = new Hono2();
|
|
46683
47996
|
approvalsRouter.use("*", async (_c, next) => {
|
|
@@ -46799,6 +48112,33 @@ approvalsRouter.post("/:id/approve", async (c) => {
|
|
|
46799
48112
|
);
|
|
46800
48113
|
return c.json({ error: "approval delivery failed", detail: error2.message }, 500);
|
|
46801
48114
|
}
|
|
48115
|
+
if (pendingPlan.kind === "verification_request") {
|
|
48116
|
+
const { paths } = getCtx();
|
|
48117
|
+
const granted = communicationApprovals_exports.grantVerificationRequest(
|
|
48118
|
+
db,
|
|
48119
|
+
id,
|
|
48120
|
+
"authenticated_operator",
|
|
48121
|
+
(approval) => authorizeInSnapshot(db, {
|
|
48122
|
+
source: approval.source,
|
|
48123
|
+
target: approval.target,
|
|
48124
|
+
origin: approval.origin,
|
|
48125
|
+
attemptKind: approval.attemptKind,
|
|
48126
|
+
attemptId: approval.attemptId
|
|
48127
|
+
}),
|
|
48128
|
+
() => validateVerificationGrant(db, paths, pendingPlan.payload.requestId),
|
|
48129
|
+
() => releaseVerificationGrant(db, pendingPlan.payload.requestId)
|
|
48130
|
+
);
|
|
48131
|
+
if (!granted.granted) {
|
|
48132
|
+
return c.json(
|
|
48133
|
+
{
|
|
48134
|
+
error: granted.failureKind === "revalidation" ? "approval revalidation failed" : "approval delivery failed",
|
|
48135
|
+
detail: granted.error
|
|
48136
|
+
},
|
|
48137
|
+
409
|
|
48138
|
+
);
|
|
48139
|
+
}
|
|
48140
|
+
return c.json(granted.approval);
|
|
48141
|
+
}
|
|
46802
48142
|
if (pendingPlan.kind === "scheduler_trigger") {
|
|
46803
48143
|
const granted = communicationApprovals_exports.grantSchedulerTrigger(
|
|
46804
48144
|
db,
|
|
@@ -46921,6 +48261,9 @@ async function deliver(plan) {
|
|
|
46921
48261
|
if (plan.kind === "scheduler_trigger") {
|
|
46922
48262
|
return;
|
|
46923
48263
|
}
|
|
48264
|
+
if (plan.kind === "verification_request") {
|
|
48265
|
+
return;
|
|
48266
|
+
}
|
|
46924
48267
|
if (plan.kind === "agent_turn") {
|
|
46925
48268
|
const preparedTurn = await prepareAgentTurn({
|
|
46926
48269
|
invocation: createTrustedTurnInvocation({
|
|
@@ -47025,6 +48368,9 @@ async function deliver(plan) {
|
|
|
47025
48368
|
if (failure) throw new Error(failure);
|
|
47026
48369
|
return;
|
|
47027
48370
|
}
|
|
48371
|
+
if (!isTelegramDeliveryPlan(plan)) {
|
|
48372
|
+
throw new Error("approval_delivery_invalid: no delivery handler for this plan kind");
|
|
48373
|
+
}
|
|
47028
48374
|
const { db, authToken } = getCtx();
|
|
47029
48375
|
if (plan.kind === "telegram_file" && plan.payload.result) {
|
|
47030
48376
|
if (plan.approval.source.kind !== "agent") throw new Error("Missing result producer");
|
|
@@ -48078,7 +49424,7 @@ function createBackupArchive(paths, snapshot) {
|
|
|
48078
49424
|
}
|
|
48079
49425
|
|
|
48080
49426
|
// ../daemon/src/lib/daemon-liveness.ts
|
|
48081
|
-
import { createHash as createHash17, randomUUID as
|
|
49427
|
+
import { createHash as createHash17, randomUUID as randomUUID38 } from "crypto";
|
|
48082
49428
|
import {
|
|
48083
49429
|
chmodSync as chmodSync2,
|
|
48084
49430
|
closeSync as closeSync10,
|
|
@@ -48248,7 +49594,7 @@ function acquireDaemonLiveness(paths) {
|
|
|
48248
49594
|
mkdirSync11(dirname6(resolve7(paths.home)), { recursive: true });
|
|
48249
49595
|
const path = daemonLivenessPath(paths.home);
|
|
48250
49596
|
mkdirSync11(dirname6(path), { recursive: true });
|
|
48251
|
-
const instanceId =
|
|
49597
|
+
const instanceId = randomUUID38();
|
|
48252
49598
|
const startedAt = Date.now();
|
|
48253
49599
|
let fd = null;
|
|
48254
49600
|
let reclaimClaim = null;
|
|
@@ -48613,7 +49959,7 @@ miscRouter.get("/health/details", async (c) => {
|
|
|
48613
49959
|
}
|
|
48614
49960
|
}
|
|
48615
49961
|
});
|
|
48616
|
-
const
|
|
49962
|
+
const report2 = {
|
|
48617
49963
|
// Structural install health only. Protected work has an explicit, independent signal below.
|
|
48618
49964
|
ok: pathChecks.home && pathChecks.db && pathChecks.auth && pathChecks.profiles && pathChecks.agents && pathChecks.skills && (database === null || database.ok) && parseErrors === 0 && shellSecurity.ok,
|
|
48619
49965
|
protectedWorkBaselineReady: executionSecurity.protectedUnattendedTurns.baseRuntimeReady,
|
|
@@ -48647,7 +49993,7 @@ miscRouter.get("/health/details", async (c) => {
|
|
|
48647
49993
|
decisions: { ...communicationDecisionMetrics }
|
|
48648
49994
|
}
|
|
48649
49995
|
};
|
|
48650
|
-
return c.json(
|
|
49996
|
+
return c.json(report2);
|
|
48651
49997
|
});
|
|
48652
49998
|
function publicShellSecurityError(error2) {
|
|
48653
49999
|
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
@@ -48763,7 +50109,7 @@ import { bodyLimit } from "hono/body-limit";
|
|
|
48763
50109
|
import { HTTPException } from "hono/http-exception";
|
|
48764
50110
|
|
|
48765
50111
|
// ../daemon/src/lib/notification-control.ts
|
|
48766
|
-
import { randomUUID as
|
|
50112
|
+
import { randomUUID as randomUUID39 } from "crypto";
|
|
48767
50113
|
|
|
48768
50114
|
// ../daemon/src/lib/notification-authorization.ts
|
|
48769
50115
|
function authorizeAttentionNotification(db, item, captured) {
|
|
@@ -48928,7 +50274,7 @@ var NotificationControl = class {
|
|
|
48928
50274
|
);
|
|
48929
50275
|
for (const item of items) byKind[item.kind]++;
|
|
48930
50276
|
const value = {
|
|
48931
|
-
id:
|
|
50277
|
+
id: randomUUID39(),
|
|
48932
50278
|
settingsRevision: revision4,
|
|
48933
50279
|
destinationId: binding.id,
|
|
48934
50280
|
kinds,
|
|
@@ -49838,7 +51184,7 @@ async function parseImportInput(request2) {
|
|
|
49838
51184
|
}
|
|
49839
51185
|
|
|
49840
51186
|
// ../daemon/src/routes/team-templates.ts
|
|
49841
|
-
import { randomUUID as
|
|
51187
|
+
import { randomUUID as randomUUID40 } from "crypto";
|
|
49842
51188
|
import { Hono as Hono17 } from "hono";
|
|
49843
51189
|
var teamTemplatesRouter = new Hono17();
|
|
49844
51190
|
teamTemplatesRouter.get("/", (c) => {
|
|
@@ -49878,7 +51224,7 @@ teamTemplatesRouter.post("/import", async (c) => {
|
|
|
49878
51224
|
if (!profiles_exports.get(db, parsed.profileId)) {
|
|
49879
51225
|
throw new Error(`profile not found: ${parsed.profileId}`);
|
|
49880
51226
|
}
|
|
49881
|
-
const slotId =
|
|
51227
|
+
const slotId = randomUUID40();
|
|
49882
51228
|
keyToSlot.set(clientKey, slotId);
|
|
49883
51229
|
return { ...parsed, slotId };
|
|
49884
51230
|
});
|
|
@@ -50326,6 +51672,194 @@ function lineRange(request2, _captured) {
|
|
|
50326
51672
|
return { start, end };
|
|
50327
51673
|
}
|
|
50328
51674
|
|
|
51675
|
+
// ../daemon/src/lib/verification/capture.ts
|
|
51676
|
+
function captureVerificationRequest(db, paths, intent, env = process.env) {
|
|
51677
|
+
const team = safeTeam3(db, paths, intent.teamId);
|
|
51678
|
+
if (!team) return blocked2("unsupported", "the request does not name a known Team");
|
|
51679
|
+
const recipient = get(db, intent.recipientAgentId);
|
|
51680
|
+
if (!recipient) return blocked2("recipient_unavailable", "the selected specialist does not exist");
|
|
51681
|
+
if (recipient.teamId !== team.id) {
|
|
51682
|
+
return blocked2("recipient_not_same_team", "the selected specialist belongs to another Team");
|
|
51683
|
+
}
|
|
51684
|
+
if (recipient.status === "archived") {
|
|
51685
|
+
return blocked2("recipient_unavailable", "the selected specialist is archived");
|
|
51686
|
+
}
|
|
51687
|
+
if (intent.requesterKind === "agent") {
|
|
51688
|
+
const requester = get(db, intent.requesterAgentId);
|
|
51689
|
+
if (!requester) return blocked2("requester_unavailable", "the requesting Agent does not exist");
|
|
51690
|
+
if (requester.teamId !== team.id) {
|
|
51691
|
+
return blocked2("requester_unavailable", "the requesting Agent belongs to another Team");
|
|
51692
|
+
}
|
|
51693
|
+
if (requester.id === recipient.id) {
|
|
51694
|
+
return blocked2("unsupported", "a specialist cannot verify its own request");
|
|
51695
|
+
}
|
|
51696
|
+
}
|
|
51697
|
+
const snapshot = getSourceSnapshot(db, team.id, intent.snapshotId);
|
|
51698
|
+
if (!snapshot) {
|
|
51699
|
+
return blocked2(
|
|
51700
|
+
"snapshot_unavailable",
|
|
51701
|
+
"the captured change is unknown in this Team or past its retention window"
|
|
51702
|
+
);
|
|
51703
|
+
}
|
|
51704
|
+
if (!snapshot.complete) {
|
|
51705
|
+
return blocked2(
|
|
51706
|
+
"snapshot_incomplete",
|
|
51707
|
+
"the captured change has incomplete coverage, so a result could not be tied to it"
|
|
51708
|
+
);
|
|
51709
|
+
}
|
|
51710
|
+
const environment = admittedEnvironment(db, team.id, env);
|
|
51711
|
+
if (!environment) {
|
|
51712
|
+
return blocked2(
|
|
51713
|
+
"environment_unavailable",
|
|
51714
|
+
"the Team has no usable admitted environment to freeze with the request"
|
|
51715
|
+
);
|
|
51716
|
+
}
|
|
51717
|
+
if (intent.writablePaths && intent.writablePaths.length > 0) {
|
|
51718
|
+
const bounded3 = [];
|
|
51719
|
+
for (const path of intent.writablePaths) {
|
|
51720
|
+
if (typeof path !== "string" || path.length === 0 || path.length > 1e3) {
|
|
51721
|
+
return blocked2("unsupported", "declared writable paths are outside their bounded contract");
|
|
51722
|
+
}
|
|
51723
|
+
if (path.startsWith("/") || path.startsWith("~") || path.includes("\\")) {
|
|
51724
|
+
return blocked2("unsupported", `declared writable path must be Team-relative: ${path}`);
|
|
51725
|
+
}
|
|
51726
|
+
const parts = path.split("/").filter((part) => part && part !== ".");
|
|
51727
|
+
if (parts.length === 0 || parts.some((part) => part === "..")) {
|
|
51728
|
+
return blocked2(
|
|
51729
|
+
"unsupported",
|
|
51730
|
+
`declared writable path must be inside the workspace: ${path}`
|
|
51731
|
+
);
|
|
51732
|
+
}
|
|
51733
|
+
bounded3.push(parts.join("/"));
|
|
51734
|
+
}
|
|
51735
|
+
if (bounded3.length > 16) {
|
|
51736
|
+
return blocked2("unsupported", "too many declared writable paths");
|
|
51737
|
+
}
|
|
51738
|
+
environment.writablePaths = bounded3;
|
|
51739
|
+
}
|
|
51740
|
+
try {
|
|
51741
|
+
const request2 = createVerificationRequest(db, {
|
|
51742
|
+
teamId: team.id,
|
|
51743
|
+
requesterKind: intent.requesterKind,
|
|
51744
|
+
requesterAgentId: intent.requesterKind === "agent" ? intent.requesterAgentId : null,
|
|
51745
|
+
recipientAgentId: recipient.id,
|
|
51746
|
+
messageId: intent.messageId ?? null,
|
|
51747
|
+
sourceSessionId: intent.sourceSessionId ?? null,
|
|
51748
|
+
snapshotId: snapshot.snapshotId,
|
|
51749
|
+
snapshotComplete: snapshot.complete,
|
|
51750
|
+
head: snapshot.head,
|
|
51751
|
+
baseOid: snapshot.baseOid,
|
|
51752
|
+
environment,
|
|
51753
|
+
summary: intent.summary ?? null,
|
|
51754
|
+
checks: intent.checks
|
|
51755
|
+
});
|
|
51756
|
+
return { kind: "captured", request: request2 };
|
|
51757
|
+
} catch (error2) {
|
|
51758
|
+
return blocked2("unsupported", error2 instanceof Error ? error2.message : "invalid request");
|
|
51759
|
+
}
|
|
51760
|
+
}
|
|
51761
|
+
function admittedEnvironment(db, teamId, env) {
|
|
51762
|
+
try {
|
|
51763
|
+
const security = resolveShellSecurityConfig(env);
|
|
51764
|
+
const resolved = resolveTeamCodingEnvironment(db, teamId, env);
|
|
51765
|
+
if (!resolved.image) return null;
|
|
51766
|
+
return {
|
|
51767
|
+
image: resolved.image,
|
|
51768
|
+
sandbox: security.sandboxMode === "docker" ? "docker" : "off",
|
|
51769
|
+
...resolved.coding ? { cwd: resolved.coding.cwd } : {},
|
|
51770
|
+
...resolved.coding ? { env: { ...resolved.coding.env } } : {}
|
|
51771
|
+
};
|
|
51772
|
+
} catch {
|
|
51773
|
+
return null;
|
|
51774
|
+
}
|
|
51775
|
+
}
|
|
51776
|
+
function readVerificationSummary(db, paths, teamId, requestId2) {
|
|
51777
|
+
const team = safeTeam3(db, paths, teamId);
|
|
51778
|
+
if (!team) return null;
|
|
51779
|
+
const record3 = getVerificationRequest(db, team.id, requestId2);
|
|
51780
|
+
if (!record3) return null;
|
|
51781
|
+
const checks = listVerificationChecks(db, record3.id);
|
|
51782
|
+
const attempts = listVerificationAttempts(db, record3.id).map((attempt) => ({
|
|
51783
|
+
id: attempt.id,
|
|
51784
|
+
attemptNumber: attempt.attemptNumber,
|
|
51785
|
+
supersedesAttemptId: attempt.supersedesAttemptId,
|
|
51786
|
+
state: attempt.state,
|
|
51787
|
+
startedAt: attempt.startedAt,
|
|
51788
|
+
finishedAt: attempt.finishedAt,
|
|
51789
|
+
error: attempt.error,
|
|
51790
|
+
outcomes: listVerificationCheckOutcomes(db, attempt.id).map((outcome) => ({
|
|
51791
|
+
ordinal: outcome.ordinal,
|
|
51792
|
+
state: outcome.state,
|
|
51793
|
+
commandId: outcome.commandId,
|
|
51794
|
+
// Executed, but no receipt pointer: the receipt was pruned or expired, which is different from
|
|
51795
|
+
// never having recorded one.
|
|
51796
|
+
receiptUnavailable: outcome.commandId === null && ["succeeded", "failed", "timed_out", "cancelled"].includes(outcome.state),
|
|
51797
|
+
exitCode: outcome.exitCode,
|
|
51798
|
+
startedAt: outcome.startedAt,
|
|
51799
|
+
finishedAt: outcome.finishedAt
|
|
51800
|
+
}))
|
|
51801
|
+
}));
|
|
51802
|
+
return {
|
|
51803
|
+
request: toWireRequest(record3),
|
|
51804
|
+
checks: checks.map((check) => ({
|
|
51805
|
+
ordinal: check.ordinal,
|
|
51806
|
+
command: check.command,
|
|
51807
|
+
cwd: check.cwd,
|
|
51808
|
+
purpose: check.purpose,
|
|
51809
|
+
timeoutMs: check.timeoutMs
|
|
51810
|
+
})),
|
|
51811
|
+
attempts
|
|
51812
|
+
};
|
|
51813
|
+
}
|
|
51814
|
+
async function readVerificationReport(db, paths, teamId, requestId2) {
|
|
51815
|
+
const summary = readVerificationSummary(db, paths, teamId, requestId2);
|
|
51816
|
+
if (!summary) return null;
|
|
51817
|
+
const applicability = await readSnapshotApplicability(
|
|
51818
|
+
db,
|
|
51819
|
+
paths,
|
|
51820
|
+
summary.request.teamId,
|
|
51821
|
+
summary.request.snapshot.id
|
|
51822
|
+
);
|
|
51823
|
+
return {
|
|
51824
|
+
...summary,
|
|
51825
|
+
applicability: {
|
|
51826
|
+
comparison: applicability.comparison,
|
|
51827
|
+
testedSnapshotId: applicability.comparison === "unknown" ? null : summary.request.snapshot.id
|
|
51828
|
+
}
|
|
51829
|
+
};
|
|
51830
|
+
}
|
|
51831
|
+
function toWireRequest(record3) {
|
|
51832
|
+
return {
|
|
51833
|
+
id: record3.id,
|
|
51834
|
+
teamId: record3.teamId,
|
|
51835
|
+
requester: record3.requesterKind === "agent" && record3.requesterAgentId ? { kind: "agent", agentId: record3.requesterAgentId } : { kind: "operator" },
|
|
51836
|
+
recipientAgentId: record3.recipientAgentId,
|
|
51837
|
+
messageId: record3.messageId,
|
|
51838
|
+
sourceSessionId: record3.sourceSessionId,
|
|
51839
|
+
snapshot: {
|
|
51840
|
+
id: record3.snapshotId,
|
|
51841
|
+
complete: record3.snapshotComplete,
|
|
51842
|
+
head: record3.head,
|
|
51843
|
+
baseOid: record3.baseOid
|
|
51844
|
+
},
|
|
51845
|
+
environment: record3.environment,
|
|
51846
|
+
summary: record3.summary,
|
|
51847
|
+
state: record3.state,
|
|
51848
|
+
createdAt: record3.createdAt,
|
|
51849
|
+
expiresAt: record3.expiresAt
|
|
51850
|
+
};
|
|
51851
|
+
}
|
|
51852
|
+
function blocked2(reason, detail3) {
|
|
51853
|
+
return { kind: "blocked", blocker: { reason, detail: detail3 } };
|
|
51854
|
+
}
|
|
51855
|
+
function safeTeam3(db, paths, teamId) {
|
|
51856
|
+
try {
|
|
51857
|
+
return requireTeam(db, paths, teamId);
|
|
51858
|
+
} catch {
|
|
51859
|
+
return null;
|
|
51860
|
+
}
|
|
51861
|
+
}
|
|
51862
|
+
|
|
50329
51863
|
// ../daemon/src/routes/teams.ts
|
|
50330
51864
|
var USER_MD_MAX_BYTES2 = 12e3;
|
|
50331
51865
|
var teamsRouter = new Hono18();
|
|
@@ -50949,6 +52483,91 @@ function teamPolicyError(c, error2) {
|
|
|
50949
52483
|
}
|
|
50950
52484
|
return c.json({ error: message, code: "team_policy_invalid" }, 400);
|
|
50951
52485
|
}
|
|
52486
|
+
teamsRouter.get("/:id/verifications", async (c) => {
|
|
52487
|
+
const { db, paths } = getCtx();
|
|
52488
|
+
c.header("Cache-Control", "no-store");
|
|
52489
|
+
try {
|
|
52490
|
+
const team = requireTeam(db, paths, c.req.param("id"));
|
|
52491
|
+
const requests = listVerificationRequests(db, team.id);
|
|
52492
|
+
const reports = requests.map((record3) => readVerificationSummary(db, paths, team.id, record3.id)).filter((summary) => summary !== null);
|
|
52493
|
+
return c.json({ requests: reports });
|
|
52494
|
+
} catch (error2) {
|
|
52495
|
+
return reviewFailure(c, error2);
|
|
52496
|
+
}
|
|
52497
|
+
});
|
|
52498
|
+
teamsRouter.post("/:id/verifications", async (c) => {
|
|
52499
|
+
const { db, paths } = getCtx();
|
|
52500
|
+
c.header("Cache-Control", "no-store");
|
|
52501
|
+
const body = await c.req.json().catch(() => null);
|
|
52502
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) {
|
|
52503
|
+
return c.json({ error: "Invalid verification request" }, 400);
|
|
52504
|
+
}
|
|
52505
|
+
const input = body;
|
|
52506
|
+
if (typeof input.recipientAgentId !== "string" || typeof input.snapshotId !== "string" || !Array.isArray(input.checks) || input.checks.some(
|
|
52507
|
+
(check) => !check || typeof check.command !== "string" || typeof check.cwd !== "string" || typeof check.purpose !== "string" || !Number.isInteger(check.timeoutMs)
|
|
52508
|
+
)) {
|
|
52509
|
+
return c.json({ error: "Invalid verification request" }, 400);
|
|
52510
|
+
}
|
|
52511
|
+
try {
|
|
52512
|
+
const result = captureVerificationRequest(db, paths, {
|
|
52513
|
+
teamId: c.req.param("id"),
|
|
52514
|
+
requesterKind: "operator",
|
|
52515
|
+
requesterAgentId: null,
|
|
52516
|
+
recipientAgentId: input.recipientAgentId,
|
|
52517
|
+
snapshotId: input.snapshotId,
|
|
52518
|
+
checks: input.checks,
|
|
52519
|
+
summary: typeof input.summary === "string" ? input.summary : null,
|
|
52520
|
+
sourceSessionId: typeof input.sourceSessionId === "string" ? input.sourceSessionId : null,
|
|
52521
|
+
...Array.isArray(input.writablePaths) ? { writablePaths: input.writablePaths } : {}
|
|
52522
|
+
});
|
|
52523
|
+
if (result.kind === "blocked") return c.json({ blocked: result.blocker }, 409);
|
|
52524
|
+
return c.json({ request: await report(db, paths, result.request) }, 201);
|
|
52525
|
+
} catch (error2) {
|
|
52526
|
+
return reviewFailure(c, error2);
|
|
52527
|
+
}
|
|
52528
|
+
});
|
|
52529
|
+
teamsRouter.get("/:id/verifications/:requestId", async (c) => {
|
|
52530
|
+
const { db, paths } = getCtx();
|
|
52531
|
+
c.header("Cache-Control", "no-store");
|
|
52532
|
+
try {
|
|
52533
|
+
const report2 = await readVerificationReport(
|
|
52534
|
+
db,
|
|
52535
|
+
paths,
|
|
52536
|
+
c.req.param("id"),
|
|
52537
|
+
c.req.param("requestId")
|
|
52538
|
+
);
|
|
52539
|
+
if (!report2) return c.json({ error: "Verification request not found" }, 404);
|
|
52540
|
+
return c.json({ request: report2 });
|
|
52541
|
+
} catch (error2) {
|
|
52542
|
+
return reviewFailure(c, error2);
|
|
52543
|
+
}
|
|
52544
|
+
});
|
|
52545
|
+
teamsRouter.post("/:id/verifications/:requestId/cancel", async (c) => {
|
|
52546
|
+
const { db, paths } = getCtx();
|
|
52547
|
+
c.header("Cache-Control", "no-store");
|
|
52548
|
+
try {
|
|
52549
|
+
const team = requireTeam(db, paths, c.req.param("id"));
|
|
52550
|
+
const record3 = getVerificationRequest(db, team.id, c.req.param("requestId"));
|
|
52551
|
+
if (!record3) return c.json({ error: "Verification request not found" }, 404);
|
|
52552
|
+
if (record3.state !== "pending" && record3.state !== "awaiting_approval" && record3.state !== "running") {
|
|
52553
|
+
return c.json({ error: `Verification request is already ${record3.state}` }, 409);
|
|
52554
|
+
}
|
|
52555
|
+
if (record3.state === "pending" || record3.state === "awaiting_approval") {
|
|
52556
|
+
setRequestState(db, record3.id, "cancelled");
|
|
52557
|
+
} else {
|
|
52558
|
+
const aborted2 = cancelVerificationDispatch(record3.id);
|
|
52559
|
+
if (!aborted2) {
|
|
52560
|
+
return c.json({ error: "Verification request is not cancelled yet; retry" }, 409);
|
|
52561
|
+
}
|
|
52562
|
+
}
|
|
52563
|
+
return c.json({ request: await readVerificationReport(db, paths, team.id, record3.id) });
|
|
52564
|
+
} catch (error2) {
|
|
52565
|
+
return reviewFailure(c, error2);
|
|
52566
|
+
}
|
|
52567
|
+
});
|
|
52568
|
+
async function report(db, paths, record3) {
|
|
52569
|
+
return readVerificationReport(db, paths, record3.teamId, record3.id);
|
|
52570
|
+
}
|
|
50952
52571
|
|
|
50953
52572
|
// ../daemon/src/routes/telegram.ts
|
|
50954
52573
|
import { Hono as Hono19 } from "hono";
|