bazilion 0.19.1 → 0.20.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 +272 -129
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +1667 -707
- package/dist/daemon.js.map +1 -1
- package/dist/migrations/0001_init.sql +46 -0
- package/dist/web/client/assets/{ChatPane-DCyGcqdh.js → ChatPane-CGCtAuD3.js} +1 -1
- package/dist/web/client/assets/{ConfirmDialog-C908TxS5.js → ConfirmDialog-Br19uXWH.js} +1 -1
- package/dist/web/client/assets/{FieldRow-CELqI-1V.js → FieldRow-Csy3_cH5.js} +1 -1
- package/dist/web/client/assets/{ProductionTeamPolicyEditor-DnTcWhG8.js → ProductionTeamPolicyEditor-DG1x4Cqz.js} +1 -1
- package/dist/web/client/assets/{ProfileCommunicationEditor-BVIEaW3s.js → ProfileCommunicationEditor-C3odNVkK.js} +1 -1
- package/dist/web/client/assets/{ResultSourceConversation-4gbZCh_s.js → ResultSourceConversation-5PFWqXTY.js} +1 -1
- package/dist/web/client/assets/{TeamTabs-V17b45X5.js → TeamTabs-BHB_COm0.js} +1 -1
- package/dist/web/client/assets/{TemplatesTabs-BMK3Qok_.js → TemplatesTabs-YyytjW7k.js} +1 -1
- package/dist/web/client/assets/{UnsavedChangesGuard-BaE-UzyS.js → UnsavedChangesGuard-CredyC3E.js} +1 -1
- package/dist/web/client/assets/{_id-CArZR-IO.js → _id-BLm9LVlZ.js} +1 -1
- package/dist/web/client/assets/{_id-BU1l9gP7.js → _id-BZ_-4M4s.js} +1 -1
- package/dist/web/client/assets/{_id-Bvh5LyUv.js → _id-CIkPtQY0.js} +1 -1
- package/dist/web/client/assets/{_id-BVANQm00.js → _id-KXX6nuKc.js} +1 -1
- package/dist/web/client/assets/{_id-tUkSe5li.js → _id-nDbQY7f_.js} +1 -1
- package/dist/web/client/assets/{activity-CWCnqjqj.js → activity-BE7jG1Mz.js} +1 -1
- package/dist/web/client/assets/{agents-CdCnhH06.js → agents-S9lzXrrs.js} +1 -1
- package/dist/web/client/assets/{agents-CX4STmGK.js → agents-vOPd-upn.js} +1 -1
- package/dist/web/client/assets/{approvals-CnNpwG78.js → approvals-BUfhlUAX.js} +1 -1
- package/dist/web/client/assets/{attention-CEE-wWrx.js → attention-C3r-2GSp.js} +1 -1
- package/dist/web/client/assets/chevron-right-C7P3Z105.js +1 -0
- package/dist/web/client/assets/{config-CSEtI-dq.js → config-AL_EM57n.js} +1 -1
- package/dist/web/client/assets/{inbox-MYnBtPdF.js → inbox-LlCpJrMH.js} +1 -1
- package/dist/web/client/assets/{index-Ct31TjS-.js → index-CwMw0pnV.js} +2 -2
- package/dist/web/client/assets/{learning-BIR5FTgQ.js → learning-zvTJ_9vM.js} +1 -1
- package/dist/web/client/assets/{login-DIeceuOs.js → login-BpQ54z8Y.js} +1 -1
- package/dist/web/client/assets/{mcp-CX3kJpGu.js → mcp-BD6VzXg_.js} +1 -1
- package/dist/web/client/assets/{members-DlhSjye1.js → members-SEDi8SFo.js} +1 -1
- package/dist/web/client/assets/{memory-CsDd6b2l.js → memory-zi_dPlMA.js} +1 -1
- package/dist/web/client/assets/{policy-DkWDhG0x.js → policy-URjQAAdN.js} +1 -1
- package/dist/web/client/assets/{results-BHdhNHJJ.js → results-Bcuy4Flp.js} +1 -1
- package/dist/web/client/assets/review-CVH7X9-d.js +1 -0
- package/dist/web/client/assets/{routes-DtYD4WJL.js → routes-BJEX6yAE.js} +1 -1
- package/dist/web/client/assets/{services-WUlW7oEo.js → services-BTG4F5FL.js} +1 -1
- package/dist/web/client/assets/{skills-jNoUfUSZ.js → skills-DwiHS7eD.js} +1 -1
- package/dist/web/client/assets/{teams-C1kYRrtP.js → teams-DcROmSGB.js} +1 -1
- package/dist/web/client/assets/{teams-D3FaSKE7.js → teams-DfpwQu1i.js} +1 -1
- package/dist/web/client/assets/{telegram-D86AO6V9.js → telegram-BLyaaUXE.js} +1 -1
- package/dist/web/client/assets/{tokens-B42KDisP.js → tokens-Dp9Vwvfx.js} +1 -1
- package/dist/web/client/assets/{triggers-yEfWnQ_K.js → triggers-CtVhrAGA.js} +1 -1
- package/dist/web/client/assets/verifications-TC0ccGLY.js +2 -0
- package/dist/web/client/assets/{welcome-D8IbF_P0.js → welcome-DML3X1ha.js} +1 -1
- package/dist/web/client/assets/{x-CXKABZ7C.js → x-D8yuCam7.js} +1 -1
- package/dist/web/server/assets/{_id-bVispdh-.js → _id-Bazctexc.js} +1 -1
- package/dist/web/server/assets/{_id-Dab2CVtO2.js → _id-BjvOb4CK2.js} +1 -1
- package/dist/web/server/assets/{_id-DL-SnSnK.js → _id-Bn0w00AG.js} +1 -1
- package/dist/web/server/assets/{_id-D2bDA1iV.js → _id-DFf_uQiI.js} +1 -1
- package/dist/web/server/assets/{_tanstack-start-manifest_v-BcTOb0oj.js → _tanstack-start-manifest_v-BGSoO6CK.js} +79 -79
- package/dist/web/server/assets/{activity-CLDAy6rk.js → activity-j_Enmf3L.js} +1 -1
- package/dist/web/server/assets/{agents-CdB2kuNN.js → agents-BAi0dE66.js} +1 -1
- package/dist/web/server/assets/{agents-DfHcb2H2.js → agents-BHUbTrm7.js} +1 -1
- package/dist/web/server/assets/{approvals-Bq846WaP.js → approvals-BcUm6IOo.js} +1 -1
- package/dist/web/server/assets/{attention-Sm-U7s_0.js → attention-BQBa0Bu5.js} +1 -1
- package/dist/web/server/assets/{auth-PB5dVyvX.js → auth-PDNSxrT-.js} +1 -1
- package/dist/web/server/assets/{config-BNGTBu80.js → config-Cf7hhsUR.js} +1 -1
- package/dist/web/server/assets/{daemon-client-CWQvck6B.js → daemon-client-DY4jE6KU.js} +15 -0
- package/dist/web/server/assets/{git-review-C_h_tezf.js → git-review-RvzReZyD.js} +1 -1
- package/dist/web/server/assets/{inbox-DJoU-bla.js → inbox-Du1guYth.js} +1 -1
- package/dist/web/server/assets/{learning-DVb0I_3Z.js → learning-CjcixPRH.js} +1 -1
- package/dist/web/server/assets/{mcp-CeZqOiDG.js → mcp-BCalFLvt.js} +1 -1
- package/dist/web/server/assets/{members-CcYjuqxB.js → members-C4TpK50B.js} +1 -1
- package/dist/web/server/assets/{memory-CH2yNT89.js → memory-CLZs-XRY.js} +1 -1
- package/dist/web/server/assets/{policy-DrRKinMr.js → policy-BrIXpwxZ.js} +1 -1
- package/dist/web/server/assets/publications-BrX3-WJf.js +57 -0
- package/dist/web/server/assets/{results-fT2zyiJx.js → results-CJR6dNzB.js} +1 -1
- package/dist/web/server/assets/{review-CvUPk4HA.js → review-CRHiZfC8.js} +1 -1
- package/dist/web/server/assets/{review-DYcYdUTv.js → review-Dqdts12v.js} +205 -3
- package/dist/web/server/assets/{review-packets-e36PsTSX.js → review-packets-D3bZ7QYU.js} +1 -1
- package/dist/web/server/assets/{router-NYhuYQCd.js → router-BVhdWkwP.js} +3 -3
- package/dist/web/server/assets/{routes-RdppWPiW.js → routes-DizvfkfZ.js} +1 -1
- package/dist/web/server/assets/{services-Dgu7dcTC.js → services-DDRj180j.js} +1 -1
- package/dist/web/server/assets/{skills-DL7UIWa8.js → skills-Bck9L5oo.js} +1 -1
- package/dist/web/server/assets/{teams-DiC-MBg4.js → teams-CSqR5mWl.js} +1 -1
- package/dist/web/server/assets/{teams-Cmn7mdx9.js → teams-C_PicOsj.js} +1 -1
- package/dist/web/server/assets/{telegram-CLOFnLjF.js → telegram-D0odXx1E.js} +1 -1
- package/dist/web/server/assets/{tokens-BVva7GHu.js → tokens-B2O0Di4p.js} +1 -1
- package/dist/web/server/assets/{triggers-D4orksJq.js → triggers-DtKMYL2r.js} +1 -1
- package/dist/web/server/assets/{verification-C1SHMTX8.js → verification-no5BrOeR.js} +1 -1
- package/dist/web/server/assets/{verifications-Ci49n2Km.js → verifications-CM-Bbgjt.js} +114 -91
- package/dist/web/server/assets/{verifications-C_ycXrPK.js → verifications-DhGe86E1.js} +1 -1
- package/dist/web/server/server.js +56 -48
- package/dist/worker.js +36 -0
- package/dist/worker.js.map +1 -1
- package/package.json +3 -3
- package/dist/web/client/assets/chevron-right-CvCEwfSl.js +0 -1
- package/dist/web/client/assets/review-Dyw47eM1.js +0 -1
- package/dist/web/client/assets/verifications-DrHQEQFx.js +0 -2
package/dist/daemon.js
CHANGED
|
@@ -271,12 +271,12 @@ var require_path_key = __commonJS({
|
|
|
271
271
|
"../../node_modules/.pnpm/path-key@3.1.1/node_modules/path-key/index.js"(exports, module) {
|
|
272
272
|
"use strict";
|
|
273
273
|
var pathKey = (options = {}) => {
|
|
274
|
-
const
|
|
274
|
+
const environment2 = options.env || process.env;
|
|
275
275
|
const platform = options.platform || process.platform;
|
|
276
276
|
if (platform !== "win32") {
|
|
277
277
|
return "PATH";
|
|
278
278
|
}
|
|
279
|
-
return Object.keys(
|
|
279
|
+
return Object.keys(environment2).reverse().find((key3) => key3.toUpperCase() === "PATH") || "Path";
|
|
280
280
|
};
|
|
281
281
|
module.exports = pathKey;
|
|
282
282
|
module.exports.default = pathKey;
|
|
@@ -19276,14 +19276,14 @@ function remove(db, id) {
|
|
|
19276
19276
|
db.raw.run("DELETE FROM agents WHERE id = ?", [id]);
|
|
19277
19277
|
}
|
|
19278
19278
|
function getTelegramTopicId(db, agentId) {
|
|
19279
|
-
const
|
|
19279
|
+
const row2 = db.raw.query(
|
|
19280
19280
|
"SELECT telegram_topic_id FROM agents WHERE id = ?"
|
|
19281
19281
|
).get(agentId);
|
|
19282
|
-
return
|
|
19282
|
+
return row2?.telegram_topic_id ?? null;
|
|
19283
19283
|
}
|
|
19284
19284
|
function findByTelegramTopicId(db, topicId) {
|
|
19285
|
-
const
|
|
19286
|
-
return
|
|
19285
|
+
const row2 = db.raw.query("SELECT * FROM agents WHERE telegram_topic_id = ?").get(topicId);
|
|
19286
|
+
return row2 ? toAgent(row2) : null;
|
|
19287
19287
|
}
|
|
19288
19288
|
function setTelegramTopicId(db, agentId, topicId) {
|
|
19289
19289
|
db.raw.run(
|
|
@@ -19303,10 +19303,10 @@ function findByName(db, name) {
|
|
|
19303
19303
|
).all(name).map(toAgent);
|
|
19304
19304
|
}
|
|
19305
19305
|
function findByNameInGroup(db, teamId, name) {
|
|
19306
|
-
const
|
|
19306
|
+
const row2 = db.raw.query(
|
|
19307
19307
|
"SELECT * FROM agents WHERE team_id = ? AND name = ? AND status != 'archived' LIMIT 1"
|
|
19308
19308
|
).get(teamId, name);
|
|
19309
|
-
return
|
|
19309
|
+
return row2 ? toAgent(row2) : null;
|
|
19310
19310
|
}
|
|
19311
19311
|
function listBoundUnlockedTopicsInGroup(db, teamId) {
|
|
19312
19312
|
return db.raw.query(
|
|
@@ -19376,25 +19376,25 @@ __export(teamPolicies_exports, {
|
|
|
19376
19376
|
replacePolicy: () => replacePolicy
|
|
19377
19377
|
});
|
|
19378
19378
|
function get2(db, teamId) {
|
|
19379
|
-
const
|
|
19380
|
-
return
|
|
19381
|
-
teamId:
|
|
19382
|
-
revision:
|
|
19383
|
-
baselineInstantiationId:
|
|
19384
|
-
updatedAt:
|
|
19379
|
+
const row2 = db.raw.query("SELECT * FROM team_policies WHERE team_id = ?").get(teamId);
|
|
19380
|
+
return row2 ? {
|
|
19381
|
+
teamId: row2.team_id,
|
|
19382
|
+
revision: row2.revision,
|
|
19383
|
+
baselineInstantiationId: row2.baseline_instantiation_id,
|
|
19384
|
+
updatedAt: row2.updated_at
|
|
19385
19385
|
} : null;
|
|
19386
19386
|
}
|
|
19387
19387
|
function edges(db, teamId) {
|
|
19388
19388
|
return db.raw.query(
|
|
19389
19389
|
`SELECT * FROM team_policy_edges WHERE team_id = ?
|
|
19390
19390
|
ORDER BY source_kind, source_id, target_kind, target_id`
|
|
19391
|
-
).all(teamId).map((
|
|
19392
|
-
teamId:
|
|
19393
|
-
sourceKind:
|
|
19394
|
-
sourceId:
|
|
19395
|
-
targetKind:
|
|
19396
|
-
targetId:
|
|
19397
|
-
posture:
|
|
19391
|
+
).all(teamId).map((row2) => ({
|
|
19392
|
+
teamId: row2.team_id,
|
|
19393
|
+
sourceKind: row2.source_kind,
|
|
19394
|
+
sourceId: row2.source_id || null,
|
|
19395
|
+
targetKind: row2.target_kind,
|
|
19396
|
+
targetId: row2.target_id || null,
|
|
19397
|
+
posture: row2.posture
|
|
19398
19398
|
}));
|
|
19399
19399
|
}
|
|
19400
19400
|
function detail(db, teamId) {
|
|
@@ -19464,7 +19464,7 @@ function placementEdgesPreview(db, teamId, agentId, placement, profileId) {
|
|
|
19464
19464
|
};
|
|
19465
19465
|
const peers = db.raw.query(
|
|
19466
19466
|
"SELECT id FROM agents WHERE team_id = ? AND id <> ? ORDER BY id"
|
|
19467
|
-
).all(teamId, agentId).map((
|
|
19467
|
+
).all(teamId, agentId).map((row2) => row2.id);
|
|
19468
19468
|
const defaults = db.raw.query("SELECT * FROM profile_communication_defaults WHERE profile_id = ?").get(profileId);
|
|
19469
19469
|
if (!defaults) return [];
|
|
19470
19470
|
if (defaults.user_input) add2("user", null, "agent", agentId);
|
|
@@ -19492,12 +19492,12 @@ function instantiations(db, teamId) {
|
|
|
19492
19492
|
return db.raw.query(
|
|
19493
19493
|
`SELECT * FROM template_instantiations WHERE team_id = ?
|
|
19494
19494
|
ORDER BY created_at ASC, id ASC`
|
|
19495
|
-
).all(teamId).map((
|
|
19496
|
-
id:
|
|
19497
|
-
teamId:
|
|
19498
|
-
templateId:
|
|
19499
|
-
templateRevision:
|
|
19500
|
-
createdAt:
|
|
19495
|
+
).all(teamId).map((row2) => ({
|
|
19496
|
+
id: row2.id,
|
|
19497
|
+
teamId: row2.team_id,
|
|
19498
|
+
templateId: row2.template_id,
|
|
19499
|
+
templateRevision: row2.template_revision,
|
|
19500
|
+
createdAt: row2.created_at
|
|
19501
19501
|
}));
|
|
19502
19502
|
}
|
|
19503
19503
|
function bindings(db, teamId) {
|
|
@@ -19505,18 +19505,18 @@ function bindings(db, teamId) {
|
|
|
19505
19505
|
`SELECT b.* FROM source_slot_bindings b
|
|
19506
19506
|
JOIN template_instantiations i ON i.id = b.instantiation_id
|
|
19507
19507
|
WHERE i.team_id = ? ORDER BY b.agent_id ASC`
|
|
19508
|
-
).all(teamId).map((
|
|
19509
|
-
agentId:
|
|
19510
|
-
instantiationId:
|
|
19511
|
-
sourceSlotId:
|
|
19508
|
+
).all(teamId).map((row2) => ({
|
|
19509
|
+
agentId: row2.agent_id,
|
|
19510
|
+
instantiationId: row2.instantiation_id,
|
|
19511
|
+
sourceSlotId: row2.source_slot_id
|
|
19512
19512
|
}));
|
|
19513
19513
|
}
|
|
19514
19514
|
function agentState(db, teamId) {
|
|
19515
|
-
return db.raw.query("SELECT * FROM team_agent_state WHERE team_id = ? ORDER BY agent_id ASC").all(teamId).map((
|
|
19516
|
-
agentId:
|
|
19517
|
-
teamId:
|
|
19518
|
-
position:
|
|
19519
|
-
display:
|
|
19515
|
+
return db.raw.query("SELECT * FROM team_agent_state WHERE team_id = ? ORDER BY agent_id ASC").all(teamId).map((row2) => ({
|
|
19516
|
+
agentId: row2.agent_id,
|
|
19517
|
+
teamId: row2.team_id,
|
|
19518
|
+
position: row2.position_x === null || row2.position_y === null ? null : { x: row2.position_x, y: row2.position_y },
|
|
19519
|
+
display: row2.display_json ? JSON.parse(row2.display_json) : null
|
|
19520
19520
|
}));
|
|
19521
19521
|
}
|
|
19522
19522
|
function requireTeamPolicy(db, teamId) {
|
|
@@ -19536,7 +19536,7 @@ function requireRevision(teamPolicy, expected) {
|
|
|
19536
19536
|
}
|
|
19537
19537
|
function validateEdges(db, teamId, policyEdges) {
|
|
19538
19538
|
const members2 = new Set(
|
|
19539
|
-
db.raw.query("SELECT id FROM agents WHERE team_id = ?").all(teamId).map((
|
|
19539
|
+
db.raw.query("SELECT id FROM agents WHERE team_id = ?").all(teamId).map((row2) => row2.id)
|
|
19540
19540
|
);
|
|
19541
19541
|
const keys2 = /* @__PURE__ */ new Set();
|
|
19542
19542
|
for (const edge of policyEdges) {
|
|
@@ -19835,8 +19835,8 @@ function insert2(db, g2, paths2) {
|
|
|
19835
19835
|
};
|
|
19836
19836
|
}
|
|
19837
19837
|
function get3(db, id, paths2) {
|
|
19838
|
-
const
|
|
19839
|
-
return
|
|
19838
|
+
const row2 = db.raw.query("SELECT * FROM teams WHERE id = ?").get(id);
|
|
19839
|
+
return row2 ? toTeam(row2, paths2) : null;
|
|
19840
19840
|
}
|
|
19841
19841
|
function list2(db, paths2) {
|
|
19842
19842
|
return db.raw.query("SELECT * FROM teams ORDER BY created_at ASC").all().map((r) => toTeam(r, paths2));
|
|
@@ -19851,10 +19851,10 @@ function setTelegramTopicNameFormat(db, id, format) {
|
|
|
19851
19851
|
db.raw.run("UPDATE teams SET telegram_topic_name_format = ? WHERE id = ?", [format, id]);
|
|
19852
19852
|
}
|
|
19853
19853
|
function getTelegramIconColor(db, id) {
|
|
19854
|
-
const
|
|
19854
|
+
const row2 = db.raw.query(
|
|
19855
19855
|
"SELECT telegram_icon_color FROM teams WHERE id = ?"
|
|
19856
19856
|
).get(id);
|
|
19857
|
-
return
|
|
19857
|
+
return row2?.telegram_icon_color ?? null;
|
|
19858
19858
|
}
|
|
19859
19859
|
function setTelegramIconColor(db, id, color) {
|
|
19860
19860
|
db.raw.run("UPDATE teams SET telegram_icon_color = ? WHERE id = ?", [color, id]);
|
|
@@ -20060,21 +20060,21 @@ __export(agentLessonProposals_exports, {
|
|
|
20060
20060
|
updatePending: () => updatePending
|
|
20061
20061
|
});
|
|
20062
20062
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
20063
|
-
function toProposal(
|
|
20063
|
+
function toProposal(row2) {
|
|
20064
20064
|
return {
|
|
20065
|
-
id:
|
|
20066
|
-
reviewId:
|
|
20067
|
-
agentId:
|
|
20068
|
-
scope:
|
|
20069
|
-
text:
|
|
20070
|
-
evidence: JSON.parse(
|
|
20071
|
-
status:
|
|
20072
|
-
version:
|
|
20073
|
-
decidedAt:
|
|
20074
|
-
revokedAt:
|
|
20075
|
-
appliedKey:
|
|
20076
|
-
createdAt:
|
|
20077
|
-
updatedAt:
|
|
20065
|
+
id: row2.id,
|
|
20066
|
+
reviewId: row2.review_id,
|
|
20067
|
+
agentId: row2.agent_id,
|
|
20068
|
+
scope: row2.scope,
|
|
20069
|
+
text: row2.text,
|
|
20070
|
+
evidence: JSON.parse(row2.evidence_json),
|
|
20071
|
+
status: row2.status,
|
|
20072
|
+
version: row2.version,
|
|
20073
|
+
decidedAt: row2.decided_at,
|
|
20074
|
+
revokedAt: row2.revoked_at,
|
|
20075
|
+
appliedKey: row2.applied_key,
|
|
20076
|
+
createdAt: row2.created_at,
|
|
20077
|
+
updatedAt: row2.updated_at
|
|
20078
20078
|
};
|
|
20079
20079
|
}
|
|
20080
20080
|
function insert3(db, input) {
|
|
@@ -20100,8 +20100,8 @@ function insert3(db, input) {
|
|
|
20100
20100
|
return proposal;
|
|
20101
20101
|
}
|
|
20102
20102
|
function get4(db, id) {
|
|
20103
|
-
const
|
|
20104
|
-
return
|
|
20103
|
+
const row2 = db.raw.query("SELECT * FROM agent_lesson_proposals WHERE id = ?").get(id);
|
|
20104
|
+
return row2 ? toProposal(row2) : null;
|
|
20105
20105
|
}
|
|
20106
20106
|
function listForReview(db, reviewId) {
|
|
20107
20107
|
return db.raw.query(
|
|
@@ -20190,8 +20190,8 @@ function insert4(db, p) {
|
|
|
20190
20190
|
return { ...p, createdAt: now, updatedAt: now };
|
|
20191
20191
|
}
|
|
20192
20192
|
function get5(db, id) {
|
|
20193
|
-
const
|
|
20194
|
-
return
|
|
20193
|
+
const row2 = db.raw.query("SELECT * FROM profiles WHERE id = ?").get(id);
|
|
20194
|
+
return row2 ? toProfile(row2) : null;
|
|
20195
20195
|
}
|
|
20196
20196
|
function list3(db) {
|
|
20197
20197
|
return db.raw.query("SELECT * FROM profiles ORDER BY created_at ASC").all().map(toProfile);
|
|
@@ -20263,16 +20263,16 @@ __export(profileCommunicationDefaults_exports, {
|
|
|
20263
20263
|
set: () => set
|
|
20264
20264
|
});
|
|
20265
20265
|
function get6(db, profileId) {
|
|
20266
|
-
const
|
|
20266
|
+
const row2 = db.raw.query(
|
|
20267
20267
|
`SELECT user_input, user_output, outside_team_input, outside_team_output, peer_default
|
|
20268
20268
|
FROM profile_communication_defaults WHERE profile_id = ?`
|
|
20269
20269
|
).get(profileId);
|
|
20270
|
-
return
|
|
20271
|
-
userInput:
|
|
20272
|
-
userOutput:
|
|
20273
|
-
outsideTeamInput:
|
|
20274
|
-
outsideTeamOutput:
|
|
20275
|
-
peerDefault:
|
|
20270
|
+
return row2 ? {
|
|
20271
|
+
userInput: row2.user_input === 1,
|
|
20272
|
+
userOutput: row2.user_output === 1,
|
|
20273
|
+
outsideTeamInput: row2.outside_team_input === 1,
|
|
20274
|
+
outsideTeamOutput: row2.outside_team_output === 1,
|
|
20275
|
+
peerDefault: row2.peer_default
|
|
20276
20276
|
} : null;
|
|
20277
20277
|
}
|
|
20278
20278
|
function set(db, profileId, value) {
|
|
@@ -20351,10 +20351,10 @@ function list4(db, provider) {
|
|
|
20351
20351
|
}
|
|
20352
20352
|
function listAll(db) {
|
|
20353
20353
|
const out = {};
|
|
20354
|
-
for (const
|
|
20355
|
-
const bucket = out[
|
|
20356
|
-
bucket.push(
|
|
20357
|
-
out[
|
|
20354
|
+
for (const row2 of db.raw.query("SELECT * FROM provider_models ORDER BY provider ASC, added_at ASC").all()) {
|
|
20355
|
+
const bucket = out[row2.provider] ?? [];
|
|
20356
|
+
bucket.push(row2.model);
|
|
20357
|
+
out[row2.provider] = bucket;
|
|
20358
20358
|
}
|
|
20359
20359
|
return out;
|
|
20360
20360
|
}
|
|
@@ -20385,8 +20385,8 @@ __export(providerState_exports, {
|
|
|
20385
20385
|
setEnabled: () => setEnabled
|
|
20386
20386
|
});
|
|
20387
20387
|
function isEnabled(db, providerId) {
|
|
20388
|
-
const
|
|
20389
|
-
return
|
|
20388
|
+
const row2 = db.raw.query("SELECT * FROM provider_state WHERE provider_id = ?").get(providerId);
|
|
20389
|
+
return row2?.enabled === 1;
|
|
20390
20390
|
}
|
|
20391
20391
|
function setEnabled(db, providerId, enabled) {
|
|
20392
20392
|
db.raw.run(
|
|
@@ -20797,8 +20797,8 @@ var sources = [
|
|
|
20797
20797
|
)
|
|
20798
20798
|
}
|
|
20799
20799
|
];
|
|
20800
|
-
function normalize(
|
|
20801
|
-
const { acknowledged_at, ...item } =
|
|
20800
|
+
function normalize(row2) {
|
|
20801
|
+
const { acknowledged_at, ...item } = row2;
|
|
20802
20802
|
return { ...item, key: `${item.kind}:${item.sourceId}`, acknowledgedAt: acknowledged_at };
|
|
20803
20803
|
}
|
|
20804
20804
|
function parseAttentionKey(key3) {
|
|
@@ -21022,7 +21022,7 @@ function schemaObjects(db) {
|
|
|
21022
21022
|
).all();
|
|
21023
21023
|
}
|
|
21024
21024
|
function schemaPayload(rows) {
|
|
21025
|
-
return rows.map((
|
|
21025
|
+
return rows.map((row2) => [row2.type, row2.name, row2.tbl_name, normalizeSql(row2.sql)].join("\0")).join("\n");
|
|
21026
21026
|
}
|
|
21027
21027
|
function expectedSchema(files) {
|
|
21028
21028
|
if (canonicalSchemaObjects !== null) return canonicalSchemaObjects;
|
|
@@ -21041,7 +21041,7 @@ function assertMigrationCompatibility(db) {
|
|
|
21041
21041
|
const expectedVersions = files.map((file) => file.version);
|
|
21042
21042
|
let appliedVersions;
|
|
21043
21043
|
try {
|
|
21044
|
-
appliedVersions = db.raw.query("SELECT version FROM schema_migrations ORDER BY version").all().map((
|
|
21044
|
+
appliedVersions = db.raw.query("SELECT version FROM schema_migrations ORDER BY version").all().map((row2) => row2.version);
|
|
21045
21045
|
} catch {
|
|
21046
21046
|
throw new IncompatibleDatabaseError();
|
|
21047
21047
|
}
|
|
@@ -21049,10 +21049,10 @@ function assertMigrationCompatibility(db) {
|
|
|
21049
21049
|
const expectedObjects = expectedSchema(files);
|
|
21050
21050
|
if (appliedVersions.length === 0) {
|
|
21051
21051
|
const migrationTable = actualObjects.filter(
|
|
21052
|
-
(
|
|
21052
|
+
(row2) => row2.type === "table" && row2.name === "schema_migrations"
|
|
21053
21053
|
);
|
|
21054
21054
|
const expectedMigrationTable = expectedObjects.filter(
|
|
21055
|
-
(
|
|
21055
|
+
(row2) => row2.type === "table" && row2.name === "schema_migrations"
|
|
21056
21056
|
);
|
|
21057
21057
|
if (actualObjects.length !== 1 || migrationTable.length !== 1 || schemaPayload(migrationTable) !== schemaPayload(expectedMigrationTable)) {
|
|
21058
21058
|
throw new IncompatibleDatabaseError();
|
|
@@ -21065,7 +21065,7 @@ function assertMigrationCompatibility(db) {
|
|
|
21065
21065
|
}
|
|
21066
21066
|
function runMigrations(db) {
|
|
21067
21067
|
const existingObjects = schemaObjects(db);
|
|
21068
|
-
if (existingObjects.length > 0 && !existingObjects.some((
|
|
21068
|
+
if (existingObjects.length > 0 && !existingObjects.some((row2) => row2.type === "table" && row2.name === "schema_migrations")) {
|
|
21069
21069
|
throw new IncompatibleDatabaseError();
|
|
21070
21070
|
}
|
|
21071
21071
|
db.raw.exec(schemaMigrationsSql);
|
|
@@ -21138,44 +21138,44 @@ __export(teamTemplates_exports, {
|
|
|
21138
21138
|
updateCanonicalMetadata: () => updateCanonicalMetadata
|
|
21139
21139
|
});
|
|
21140
21140
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
21141
|
-
function toTemplate(
|
|
21141
|
+
function toTemplate(row2) {
|
|
21142
21142
|
return {
|
|
21143
|
-
id:
|
|
21144
|
-
name:
|
|
21145
|
-
userMd:
|
|
21146
|
-
currentRevision:
|
|
21147
|
-
deletedAt:
|
|
21148
|
-
createdAt:
|
|
21149
|
-
updatedAt:
|
|
21143
|
+
id: row2.id,
|
|
21144
|
+
name: row2.name,
|
|
21145
|
+
userMd: row2.user_md,
|
|
21146
|
+
currentRevision: row2.current_revision,
|
|
21147
|
+
deletedAt: row2.deleted_at,
|
|
21148
|
+
createdAt: row2.created_at,
|
|
21149
|
+
updatedAt: row2.updated_at
|
|
21150
21150
|
};
|
|
21151
21151
|
}
|
|
21152
|
-
function toSlot(
|
|
21152
|
+
function toSlot(row2) {
|
|
21153
21153
|
return {
|
|
21154
|
-
templateId:
|
|
21155
|
-
slotId:
|
|
21156
|
-
position:
|
|
21157
|
-
profileId:
|
|
21158
|
-
agentName:
|
|
21159
|
-
modelOverride:
|
|
21160
|
-
reasoningLevel:
|
|
21161
|
-
layoutPosition:
|
|
21162
|
-
display:
|
|
21163
|
-
tombstonedAt:
|
|
21164
|
-
};
|
|
21165
|
-
}
|
|
21166
|
-
function toEdge(
|
|
21154
|
+
templateId: row2.template_id,
|
|
21155
|
+
slotId: row2.slot_id,
|
|
21156
|
+
position: row2.position,
|
|
21157
|
+
profileId: row2.profile_id,
|
|
21158
|
+
agentName: row2.agent_name,
|
|
21159
|
+
modelOverride: row2.model_override,
|
|
21160
|
+
reasoningLevel: row2.reasoning_level,
|
|
21161
|
+
layoutPosition: row2.position_x === null || row2.position_y === null ? null : { x: row2.position_x, y: row2.position_y },
|
|
21162
|
+
display: row2.display_json ? JSON.parse(row2.display_json) : null,
|
|
21163
|
+
tombstonedAt: row2.tombstoned_at
|
|
21164
|
+
};
|
|
21165
|
+
}
|
|
21166
|
+
function toEdge(row2) {
|
|
21167
21167
|
return {
|
|
21168
|
-
templateId:
|
|
21169
|
-
sourceKind:
|
|
21170
|
-
sourceId:
|
|
21171
|
-
targetKind:
|
|
21172
|
-
targetId:
|
|
21173
|
-
posture:
|
|
21168
|
+
templateId: row2.template_id,
|
|
21169
|
+
sourceKind: row2.source_kind,
|
|
21170
|
+
sourceId: row2.source_id || null,
|
|
21171
|
+
targetKind: row2.target_kind,
|
|
21172
|
+
targetId: row2.target_id || null,
|
|
21173
|
+
posture: row2.posture
|
|
21174
21174
|
};
|
|
21175
21175
|
}
|
|
21176
21176
|
function get7(db, id) {
|
|
21177
|
-
const
|
|
21178
|
-
return
|
|
21177
|
+
const row2 = db.raw.query("SELECT * FROM team_templates WHERE id = ?").get(id);
|
|
21178
|
+
return row2 ? toTemplate(row2) : null;
|
|
21179
21179
|
}
|
|
21180
21180
|
function list5(db) {
|
|
21181
21181
|
return db.raw.query("SELECT * FROM team_templates ORDER BY created_at ASC").all().map(toTemplate);
|
|
@@ -21658,26 +21658,26 @@ __export(agentReviews_exports, {
|
|
|
21658
21658
|
setSource: () => setSource
|
|
21659
21659
|
});
|
|
21660
21660
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
21661
|
-
function toReview(
|
|
21661
|
+
function toReview(row2) {
|
|
21662
21662
|
return {
|
|
21663
|
-
id:
|
|
21664
|
-
agentId:
|
|
21665
|
-
status:
|
|
21666
|
-
trigger:
|
|
21667
|
-
sourceSessionId:
|
|
21668
|
-
sourceStartOrdinal:
|
|
21669
|
-
sourceEndOrdinal:
|
|
21670
|
-
inputCharacters:
|
|
21671
|
-
turnsReviewed:
|
|
21672
|
-
proposalCount:
|
|
21673
|
-
attemptCount:
|
|
21674
|
-
nextAttemptAt:
|
|
21675
|
-
leaseExpiresAt:
|
|
21676
|
-
startedAt:
|
|
21677
|
-
finishedAt:
|
|
21678
|
-
lastError:
|
|
21679
|
-
createdAt:
|
|
21680
|
-
updatedAt:
|
|
21663
|
+
id: row2.id,
|
|
21664
|
+
agentId: row2.agent_id,
|
|
21665
|
+
status: row2.status,
|
|
21666
|
+
trigger: row2.trigger_kind,
|
|
21667
|
+
sourceSessionId: row2.source_session_id,
|
|
21668
|
+
sourceStartOrdinal: row2.source_start_ordinal,
|
|
21669
|
+
sourceEndOrdinal: row2.source_end_ordinal,
|
|
21670
|
+
inputCharacters: row2.input_characters,
|
|
21671
|
+
turnsReviewed: row2.turns_reviewed,
|
|
21672
|
+
proposalCount: row2.proposal_count,
|
|
21673
|
+
attemptCount: row2.attempt_count,
|
|
21674
|
+
nextAttemptAt: row2.next_attempt_at,
|
|
21675
|
+
leaseExpiresAt: row2.lease_expires_at,
|
|
21676
|
+
startedAt: row2.started_at,
|
|
21677
|
+
finishedAt: row2.finished_at,
|
|
21678
|
+
lastError: row2.last_error,
|
|
21679
|
+
createdAt: row2.created_at,
|
|
21680
|
+
updatedAt: row2.updated_at
|
|
21681
21681
|
};
|
|
21682
21682
|
}
|
|
21683
21683
|
function insert5(db, agentId, trigger, now) {
|
|
@@ -21694,15 +21694,15 @@ function insert5(db, agentId, trigger, now) {
|
|
|
21694
21694
|
return review;
|
|
21695
21695
|
}
|
|
21696
21696
|
function get8(db, id) {
|
|
21697
|
-
const
|
|
21698
|
-
return
|
|
21697
|
+
const row2 = db.raw.query("SELECT * FROM agent_reviews WHERE id = ?").get(id);
|
|
21698
|
+
return row2 ? toReview(row2) : null;
|
|
21699
21699
|
}
|
|
21700
21700
|
function getOpenForAgent(db, agentId) {
|
|
21701
|
-
const
|
|
21701
|
+
const row2 = db.raw.query(
|
|
21702
21702
|
`SELECT * FROM agent_reviews WHERE agent_id = ?
|
|
21703
21703
|
AND status IN ('pending','running','retrying') LIMIT 1`
|
|
21704
21704
|
).get(agentId);
|
|
21705
|
-
return
|
|
21705
|
+
return row2 ? toReview(row2) : null;
|
|
21706
21706
|
}
|
|
21707
21707
|
function enqueueManual(db, agentId, now = Date.now()) {
|
|
21708
21708
|
return db.raw.transaction(
|
|
@@ -21762,11 +21762,11 @@ function defer(db, id, nextAttemptAt = Date.now() + 1e3) {
|
|
|
21762
21762
|
);
|
|
21763
21763
|
}
|
|
21764
21764
|
function getLatestCompleted(db, agentId) {
|
|
21765
|
-
const
|
|
21765
|
+
const row2 = db.raw.query(
|
|
21766
21766
|
`SELECT * FROM agent_reviews WHERE agent_id = ? AND status = 'completed'
|
|
21767
21767
|
ORDER BY finished_at DESC LIMIT 1`
|
|
21768
21768
|
).get(agentId);
|
|
21769
|
-
return
|
|
21769
|
+
return row2 ? toReview(row2) : null;
|
|
21770
21770
|
}
|
|
21771
21771
|
function setSource(db, id, source) {
|
|
21772
21772
|
db.raw.run(
|
|
@@ -21844,40 +21844,40 @@ function endpoint(kind, id, teamId) {
|
|
|
21844
21844
|
if (kind === "agent") return { kind, id };
|
|
21845
21845
|
return { kind, teamId: teamId ?? "__missing__" };
|
|
21846
21846
|
}
|
|
21847
|
-
function toApproval(
|
|
21847
|
+
function toApproval(row2) {
|
|
21848
21848
|
return {
|
|
21849
|
-
id:
|
|
21850
|
-
attemptKind:
|
|
21851
|
-
attemptId:
|
|
21852
|
-
operation:
|
|
21853
|
-
source: endpoint(
|
|
21854
|
-
target: endpoint(
|
|
21855
|
-
sourceTeamId:
|
|
21856
|
-
targetTeamId:
|
|
21857
|
-
channel:
|
|
21858
|
-
origin:
|
|
21859
|
-
requester:
|
|
21860
|
-
policyRefs: JSON.parse(
|
|
21861
|
-
requiredEdgeIds: JSON.parse(
|
|
21862
|
-
payloadKind:
|
|
21863
|
-
status:
|
|
21864
|
-
expiresAt:
|
|
21865
|
-
decidedAt:
|
|
21866
|
-
decidedBy:
|
|
21867
|
-
decisionReason:
|
|
21868
|
-
deliveryError:
|
|
21869
|
-
createdAt:
|
|
21870
|
-
updatedAt:
|
|
21871
|
-
};
|
|
21872
|
-
}
|
|
21873
|
-
function event(
|
|
21849
|
+
id: row2.id,
|
|
21850
|
+
attemptKind: row2.attempt_kind,
|
|
21851
|
+
attemptId: row2.attempt_id,
|
|
21852
|
+
operation: row2.operation,
|
|
21853
|
+
source: endpoint(row2.source_kind, row2.source_id, row2.source_team_id),
|
|
21854
|
+
target: endpoint(row2.target_kind, row2.target_id, row2.target_team_id),
|
|
21855
|
+
sourceTeamId: row2.source_team_id,
|
|
21856
|
+
targetTeamId: row2.target_team_id,
|
|
21857
|
+
channel: row2.channel,
|
|
21858
|
+
origin: row2.origin,
|
|
21859
|
+
requester: row2.requester,
|
|
21860
|
+
policyRefs: JSON.parse(row2.policy_refs_json),
|
|
21861
|
+
requiredEdgeIds: JSON.parse(row2.required_edge_ids_json),
|
|
21862
|
+
payloadKind: row2.payload_kind,
|
|
21863
|
+
status: row2.status,
|
|
21864
|
+
expiresAt: row2.expires_at,
|
|
21865
|
+
decidedAt: row2.decided_at,
|
|
21866
|
+
decidedBy: row2.decided_by,
|
|
21867
|
+
decisionReason: row2.decision_reason,
|
|
21868
|
+
deliveryError: row2.delivery_error,
|
|
21869
|
+
createdAt: row2.created_at,
|
|
21870
|
+
updatedAt: row2.updated_at
|
|
21871
|
+
};
|
|
21872
|
+
}
|
|
21873
|
+
function event(row2) {
|
|
21874
21874
|
return {
|
|
21875
|
-
id:
|
|
21876
|
-
approvalId:
|
|
21877
|
-
event:
|
|
21878
|
-
actor:
|
|
21879
|
-
detail:
|
|
21880
|
-
createdAt:
|
|
21875
|
+
id: row2.id,
|
|
21876
|
+
approvalId: row2.approval_id,
|
|
21877
|
+
event: row2.event,
|
|
21878
|
+
actor: row2.actor,
|
|
21879
|
+
detail: row2.detail,
|
|
21880
|
+
createdAt: row2.created_at
|
|
21881
21881
|
};
|
|
21882
21882
|
}
|
|
21883
21883
|
function raw(db, id) {
|
|
@@ -21971,16 +21971,16 @@ function request(db, input, operation, authorization, payloadKind, payload, opti
|
|
|
21971
21971
|
return toApproval(raced);
|
|
21972
21972
|
}
|
|
21973
21973
|
}
|
|
21974
|
-
function expireOne(db,
|
|
21975
|
-
if (
|
|
21974
|
+
function expireOne(db, row2, now) {
|
|
21975
|
+
if (row2.status !== "pending" || row2.expires_at > now) return false;
|
|
21976
21976
|
const changed = db.raw.run(
|
|
21977
21977
|
`UPDATE communication_approvals
|
|
21978
21978
|
SET status = 'expired', decided_at = ?, decided_by = 'system',
|
|
21979
21979
|
decision_reason = 'approval expired', updated_at = ?
|
|
21980
21980
|
WHERE id = ? AND status = 'pending' AND expires_at <= ?`,
|
|
21981
|
-
[now, now,
|
|
21981
|
+
[now, now, row2.id, now]
|
|
21982
21982
|
).changes;
|
|
21983
|
-
if (changed) appendEvent(db,
|
|
21983
|
+
if (changed) appendEvent(db, row2.id, "expired", "system", "approval expired", now);
|
|
21984
21984
|
return changed > 0;
|
|
21985
21985
|
}
|
|
21986
21986
|
function expirePending(db, now = Date.now()) {
|
|
@@ -21988,29 +21988,29 @@ function expirePending(db, now = Date.now()) {
|
|
|
21988
21988
|
const rows = db.raw.query(
|
|
21989
21989
|
"SELECT * FROM communication_approvals WHERE status = 'pending' AND expires_at <= ?"
|
|
21990
21990
|
).all(now);
|
|
21991
|
-
for (const
|
|
21991
|
+
for (const row2 of rows) expireOne(db, row2, now);
|
|
21992
21992
|
return rows.length;
|
|
21993
21993
|
})();
|
|
21994
21994
|
}
|
|
21995
21995
|
function get9(db, id, includePayload = false) {
|
|
21996
21996
|
expirePending(db);
|
|
21997
|
-
const
|
|
21998
|
-
if (!
|
|
21999
|
-
const approval = toApproval(
|
|
21997
|
+
const row2 = raw(db, id);
|
|
21998
|
+
if (!row2) return null;
|
|
21999
|
+
const approval = toApproval(row2);
|
|
22000
22000
|
if (!includePayload) return approval;
|
|
22001
|
-
return detailFromRow(db,
|
|
22001
|
+
return detailFromRow(db, row2);
|
|
22002
22002
|
}
|
|
22003
22003
|
function getByAttempt(db, attemptKind, attemptId, includePayload = false) {
|
|
22004
22004
|
expirePending(db);
|
|
22005
|
-
const
|
|
22006
|
-
if (!
|
|
22007
|
-
return includePayload ? detailFromRow(db,
|
|
22005
|
+
const row2 = rawByAttempt(db, attemptKind, attemptId);
|
|
22006
|
+
if (!row2) return null;
|
|
22007
|
+
return includePayload ? detailFromRow(db, row2) : toApproval(row2);
|
|
22008
22008
|
}
|
|
22009
|
-
function detailFromRow(db,
|
|
22009
|
+
function detailFromRow(db, row2) {
|
|
22010
22010
|
const events = db.raw.query(
|
|
22011
22011
|
"SELECT * FROM communication_approval_events WHERE approval_id = ? ORDER BY created_at, rowid"
|
|
22012
|
-
).all(
|
|
22013
|
-
return { ...toApproval(
|
|
22012
|
+
).all(row2.id).map(event);
|
|
22013
|
+
return { ...toApproval(row2), payload: JSON.parse(row2.payload_json), events };
|
|
22014
22014
|
}
|
|
22015
22015
|
function list6(db, filters = {}) {
|
|
22016
22016
|
expirePending(db);
|
|
@@ -22032,8 +22032,8 @@ function list6(db, filters = {}) {
|
|
|
22032
22032
|
function decide(db, id, decision, actor, reason, now = Date.now()) {
|
|
22033
22033
|
expirePending(db, now);
|
|
22034
22034
|
return db.raw.transaction(() => {
|
|
22035
|
-
const
|
|
22036
|
-
if (!
|
|
22035
|
+
const row2 = raw(db, id);
|
|
22036
|
+
if (!row2) throw new Error(`approval_not_found: ${id}`);
|
|
22037
22037
|
const current = raw(db, id);
|
|
22038
22038
|
if (current.status !== "pending")
|
|
22039
22039
|
throw new Error(`approval_state_conflict: current ${current.status}`);
|
|
@@ -22773,6 +22773,42 @@ var SERVICES = [
|
|
|
22773
22773
|
description: "Numeric id of the forum-enabled supergroup the bot is admin in."
|
|
22774
22774
|
}
|
|
22775
22775
|
]
|
|
22776
|
+
},
|
|
22777
|
+
{
|
|
22778
|
+
id: "publication",
|
|
22779
|
+
displayName: "Code host publication",
|
|
22780
|
+
category: "integration",
|
|
22781
|
+
hint: "Where an accepted change is committed and opened as a pull request",
|
|
22782
|
+
fields: [
|
|
22783
|
+
{
|
|
22784
|
+
envVar: "PUBLICATION_HOST",
|
|
22785
|
+
kind: "config",
|
|
22786
|
+
label: "Host",
|
|
22787
|
+
placeholder: "github",
|
|
22788
|
+
description: 'The only supported host today. "local" points at a bare repository path and opens no pull request.'
|
|
22789
|
+
},
|
|
22790
|
+
{
|
|
22791
|
+
envVar: "PUBLICATION_REPOSITORY",
|
|
22792
|
+
kind: "config",
|
|
22793
|
+
label: "Repository",
|
|
22794
|
+
placeholder: "owner/name",
|
|
22795
|
+
description: "For github: owner/name. For local: an absolute path to a bare repository. The Team repository's own origin is never used."
|
|
22796
|
+
},
|
|
22797
|
+
{
|
|
22798
|
+
envVar: "PUBLICATION_BASE_BRANCH",
|
|
22799
|
+
kind: "config",
|
|
22800
|
+
label: "Base branch",
|
|
22801
|
+
placeholder: "main",
|
|
22802
|
+
description: "The branch a publication is based on and its pull request targets."
|
|
22803
|
+
},
|
|
22804
|
+
{
|
|
22805
|
+
envVar: "GITHUB_TOKEN",
|
|
22806
|
+
kind: "secret",
|
|
22807
|
+
label: "GitHub token",
|
|
22808
|
+
placeholder: "ghp_...",
|
|
22809
|
+
description: "Needs contents:write and pull_requests:write on that repository. Used only for one push and one pull request."
|
|
22810
|
+
}
|
|
22811
|
+
]
|
|
22776
22812
|
}
|
|
22777
22813
|
];
|
|
22778
22814
|
var FIELD_INDEX = (() => {
|
|
@@ -22812,8 +22848,8 @@ function isConfigKey(key3) {
|
|
|
22812
22848
|
function openConfig(db) {
|
|
22813
22849
|
return {
|
|
22814
22850
|
get(key3) {
|
|
22815
|
-
const
|
|
22816
|
-
return
|
|
22851
|
+
const row2 = db.raw.query("SELECT * FROM config WHERE key = ?").get(key3);
|
|
22852
|
+
return row2?.value;
|
|
22817
22853
|
},
|
|
22818
22854
|
set(key3, value) {
|
|
22819
22855
|
if (!isConfigKey(key3)) {
|
|
@@ -22895,17 +22931,17 @@ function insert6(db, input) {
|
|
|
22895
22931
|
now
|
|
22896
22932
|
]
|
|
22897
22933
|
);
|
|
22898
|
-
const
|
|
22899
|
-
if (!
|
|
22900
|
-
return
|
|
22934
|
+
const row2 = get10(db, id);
|
|
22935
|
+
if (!row2) throw new Error("mcp server insert failed");
|
|
22936
|
+
return row2;
|
|
22901
22937
|
}
|
|
22902
22938
|
function get10(db, id) {
|
|
22903
|
-
const
|
|
22904
|
-
return
|
|
22939
|
+
const row2 = db.raw.query("SELECT * FROM mcp_servers WHERE id = ?").get(id);
|
|
22940
|
+
return row2 ? toServer(row2) : null;
|
|
22905
22941
|
}
|
|
22906
22942
|
function getByName(db, name) {
|
|
22907
|
-
const
|
|
22908
|
-
return
|
|
22943
|
+
const row2 = db.raw.query("SELECT * FROM mcp_servers WHERE name = ?").get(name);
|
|
22944
|
+
return row2 ? toServer(row2) : null;
|
|
22909
22945
|
}
|
|
22910
22946
|
function list7(db) {
|
|
22911
22947
|
return db.raw.query("SELECT * FROM mcp_servers ORDER BY created_at ASC").all().map(toServer);
|
|
@@ -23008,8 +23044,8 @@ function send(db, input) {
|
|
|
23008
23044
|
};
|
|
23009
23045
|
}
|
|
23010
23046
|
function get11(db, id) {
|
|
23011
|
-
const
|
|
23012
|
-
return
|
|
23047
|
+
const row2 = db.raw.query("SELECT * FROM messages WHERE id = ?").get(id);
|
|
23048
|
+
return row2 ? toMessage(row2) : null;
|
|
23013
23049
|
}
|
|
23014
23050
|
function listInbox(db, agentId, opts) {
|
|
23015
23051
|
const sql = opts?.unreadOnly ? "SELECT * FROM messages WHERE to_agent_id = ? AND read_at IS NULL AND policy_claimed_at IS NULL AND policy_disposition = 'deliverable' ORDER BY created_at ASC" : "SELECT * FROM messages WHERE to_agent_id = ? AND policy_disposition = 'deliverable' ORDER BY created_at ASC";
|
|
@@ -23124,9 +23160,9 @@ function openSecrets(db, password) {
|
|
|
23124
23160
|
function listAll3() {
|
|
23125
23161
|
return db.raw.query("SELECT * FROM secrets ORDER BY key ASC").all();
|
|
23126
23162
|
}
|
|
23127
|
-
function tryDecrypt(
|
|
23163
|
+
function tryDecrypt(row2) {
|
|
23128
23164
|
try {
|
|
23129
|
-
const envelope = JSON.parse(
|
|
23165
|
+
const envelope = JSON.parse(row2.envelope);
|
|
23130
23166
|
return decrypt(envelope, password);
|
|
23131
23167
|
} catch {
|
|
23132
23168
|
return void 0;
|
|
@@ -23134,9 +23170,9 @@ function openSecrets(db, password) {
|
|
|
23134
23170
|
}
|
|
23135
23171
|
return {
|
|
23136
23172
|
get(key3) {
|
|
23137
|
-
const
|
|
23138
|
-
if (!
|
|
23139
|
-
return tryDecrypt(
|
|
23173
|
+
const row2 = getRow(key3);
|
|
23174
|
+
if (!row2) return void 0;
|
|
23175
|
+
return tryDecrypt(row2);
|
|
23140
23176
|
},
|
|
23141
23177
|
set(key3, value) {
|
|
23142
23178
|
const envelope = JSON.stringify(encrypt(value, password));
|
|
@@ -23188,8 +23224,8 @@ function toMeta(r) {
|
|
|
23188
23224
|
};
|
|
23189
23225
|
}
|
|
23190
23226
|
function get12(db, name) {
|
|
23191
|
-
const
|
|
23192
|
-
return
|
|
23227
|
+
const row2 = db.raw.query("SELECT * FROM skill_meta WHERE name = ?").get(name);
|
|
23228
|
+
return row2 ? toMeta(row2) : null;
|
|
23193
23229
|
}
|
|
23194
23230
|
function listAll2(db) {
|
|
23195
23231
|
return db.raw.query("SELECT * FROM skill_meta ORDER BY name ASC").all().map(toMeta);
|
|
@@ -23234,8 +23270,8 @@ function list8(db) {
|
|
|
23234
23270
|
return db.raw.query("SELECT * FROM telegram_allowed_users ORDER BY added_at ASC").all().map(toUser);
|
|
23235
23271
|
}
|
|
23236
23272
|
function get13(db, userId) {
|
|
23237
|
-
const
|
|
23238
|
-
return
|
|
23273
|
+
const row2 = db.raw.query("SELECT * FROM telegram_allowed_users WHERE user_id = ?").get(userId);
|
|
23274
|
+
return row2 ? toUser(row2) : null;
|
|
23239
23275
|
}
|
|
23240
23276
|
function isAllowed(db, userId) {
|
|
23241
23277
|
return get13(db, userId) !== null;
|
|
@@ -23308,30 +23344,30 @@ function status(db) {
|
|
|
23308
23344
|
const owner = db.raw.query(
|
|
23309
23345
|
"SELECT user_id FROM telegram_allowed_users WHERE role = 'owner' ORDER BY added_at LIMIT 1"
|
|
23310
23346
|
).get();
|
|
23311
|
-
const
|
|
23347
|
+
const row2 = db.raw.query(
|
|
23312
23348
|
"SELECT digest, expires_at, created_at FROM telegram_pairing_challenge WHERE singleton = 1"
|
|
23313
23349
|
).get();
|
|
23314
|
-
const active =
|
|
23315
|
-
if (
|
|
23350
|
+
const active = row2 !== null && row2.expires_at > Date.now();
|
|
23351
|
+
if (row2 && !active) cancel2(db);
|
|
23316
23352
|
return {
|
|
23317
23353
|
paired: owner !== null,
|
|
23318
23354
|
challengeActive: active,
|
|
23319
|
-
challengeExpiresAt: active ?
|
|
23355
|
+
challengeExpiresAt: active ? row2?.expires_at ?? null : null,
|
|
23320
23356
|
ownerUserId: owner?.user_id ?? null
|
|
23321
23357
|
};
|
|
23322
23358
|
}
|
|
23323
23359
|
function consume(db, input) {
|
|
23324
23360
|
return db.raw.transaction(() => {
|
|
23325
23361
|
if (status(db).paired) return false;
|
|
23326
|
-
const
|
|
23362
|
+
const row2 = db.raw.query(
|
|
23327
23363
|
"SELECT digest, expires_at, created_at FROM telegram_pairing_challenge WHERE singleton = 1"
|
|
23328
23364
|
).get();
|
|
23329
|
-
if (!
|
|
23365
|
+
if (!row2 || row2.expires_at <= Date.now()) {
|
|
23330
23366
|
cancel2(db);
|
|
23331
23367
|
return false;
|
|
23332
23368
|
}
|
|
23333
23369
|
const supplied = digest(input.code);
|
|
23334
|
-
const expected = Buffer.from(
|
|
23370
|
+
const expected = Buffer.from(row2.digest, "hex");
|
|
23335
23371
|
if (supplied.length !== expected.length || !timingSafeEqual(supplied, expected)) return false;
|
|
23336
23372
|
add(db, { ...input, role: "owner" });
|
|
23337
23373
|
cancel2(db);
|
|
@@ -23355,22 +23391,22 @@ __export(triggerDispatches_exports, {
|
|
|
23355
23391
|
succeed: () => succeed
|
|
23356
23392
|
});
|
|
23357
23393
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
23358
|
-
function toDispatch(
|
|
23394
|
+
function toDispatch(row2) {
|
|
23359
23395
|
return {
|
|
23360
|
-
id:
|
|
23361
|
-
triggerId:
|
|
23362
|
-
agentId:
|
|
23363
|
-
conversationId:
|
|
23364
|
-
scheduledAt:
|
|
23365
|
-
status:
|
|
23366
|
-
attemptCount:
|
|
23367
|
-
nextAttemptAt:
|
|
23368
|
-
leaseExpiresAt:
|
|
23369
|
-
startedAt:
|
|
23370
|
-
finishedAt:
|
|
23371
|
-
lastError:
|
|
23372
|
-
createdAt:
|
|
23373
|
-
updatedAt:
|
|
23396
|
+
id: row2.id,
|
|
23397
|
+
triggerId: row2.trigger_id,
|
|
23398
|
+
agentId: row2.agent_id,
|
|
23399
|
+
conversationId: row2.conversation_id,
|
|
23400
|
+
scheduledAt: row2.scheduled_at,
|
|
23401
|
+
status: row2.status,
|
|
23402
|
+
attemptCount: row2.attempt_count,
|
|
23403
|
+
nextAttemptAt: row2.next_attempt_at,
|
|
23404
|
+
leaseExpiresAt: row2.lease_expires_at,
|
|
23405
|
+
startedAt: row2.started_at,
|
|
23406
|
+
finishedAt: row2.finished_at,
|
|
23407
|
+
lastError: row2.last_error,
|
|
23408
|
+
createdAt: row2.created_at,
|
|
23409
|
+
updatedAt: row2.updated_at
|
|
23374
23410
|
};
|
|
23375
23411
|
}
|
|
23376
23412
|
function materialize(db, input) {
|
|
@@ -23392,15 +23428,15 @@ function materialize(db, input) {
|
|
|
23392
23428
|
now
|
|
23393
23429
|
]
|
|
23394
23430
|
);
|
|
23395
|
-
const
|
|
23431
|
+
const row2 = db.raw.query(
|
|
23396
23432
|
"SELECT * FROM trigger_dispatches WHERE trigger_id = ? AND scheduled_at = ?"
|
|
23397
23433
|
).get(input.triggerId, input.scheduledAt);
|
|
23398
|
-
if (!
|
|
23399
|
-
return toDispatch(
|
|
23434
|
+
if (!row2) throw new Error("trigger dispatch materialization failed");
|
|
23435
|
+
return toDispatch(row2);
|
|
23400
23436
|
}
|
|
23401
23437
|
function get14(db, id) {
|
|
23402
|
-
const
|
|
23403
|
-
return
|
|
23438
|
+
const row2 = db.raw.query("SELECT * FROM trigger_dispatches WHERE id = ?").get(id);
|
|
23439
|
+
return row2 ? toDispatch(row2) : null;
|
|
23404
23440
|
}
|
|
23405
23441
|
function listClaimable2(db, now = Date.now()) {
|
|
23406
23442
|
return db.raw.query(
|
|
@@ -23431,8 +23467,8 @@ function claim2(db, id, options = {}) {
|
|
|
23431
23467
|
[leaseExpiresAt, now, now, id, now, now]
|
|
23432
23468
|
);
|
|
23433
23469
|
if (Number(result.changes) !== 1) return null;
|
|
23434
|
-
const
|
|
23435
|
-
return
|
|
23470
|
+
const row2 = db.raw.query("SELECT * FROM trigger_dispatches WHERE id = ?").get(id);
|
|
23471
|
+
return row2 ? toDispatch(row2) : null;
|
|
23436
23472
|
})();
|
|
23437
23473
|
}
|
|
23438
23474
|
function succeed(db, id, now = Date.now()) {
|
|
@@ -23541,8 +23577,8 @@ function insert7(db, input) {
|
|
|
23541
23577
|
};
|
|
23542
23578
|
}
|
|
23543
23579
|
function get15(db, id) {
|
|
23544
|
-
const
|
|
23545
|
-
return
|
|
23580
|
+
const row2 = db.raw.query("SELECT * FROM agent_triggers WHERE id = ?").get(id);
|
|
23581
|
+
return row2 ? toTrigger(row2) : null;
|
|
23546
23582
|
}
|
|
23547
23583
|
function listForAgent3(db, agentId) {
|
|
23548
23584
|
return db.raw.query(
|
|
@@ -23643,25 +23679,25 @@ function list9(db, opts) {
|
|
|
23643
23679
|
return db.raw.query(sql).all().map(toToken);
|
|
23644
23680
|
}
|
|
23645
23681
|
function get16(db, id) {
|
|
23646
|
-
const
|
|
23647
|
-
return
|
|
23682
|
+
const row2 = db.raw.query("SELECT * FROM web_tokens WHERE id = ?").get(id);
|
|
23683
|
+
return row2 ? toToken(row2) : null;
|
|
23648
23684
|
}
|
|
23649
23685
|
function findActiveByToken(db, token) {
|
|
23650
23686
|
const tokenHash = hashToken(token);
|
|
23651
|
-
const
|
|
23687
|
+
const row2 = db.raw.query(
|
|
23652
23688
|
`SELECT * FROM web_tokens
|
|
23653
23689
|
WHERE token_hash = ? AND revoked_at IS NULL
|
|
23654
23690
|
AND (expires_at IS NULL OR expires_at > ?)`
|
|
23655
23691
|
).get(tokenHash, Date.now());
|
|
23656
|
-
return
|
|
23692
|
+
return row2 ? toToken(row2) : null;
|
|
23657
23693
|
}
|
|
23658
23694
|
function rejectionReason(db, token, now = Date.now()) {
|
|
23659
|
-
const
|
|
23695
|
+
const row2 = db.raw.query(
|
|
23660
23696
|
"SELECT expires_at, revoked_at FROM web_tokens WHERE token_hash = ?"
|
|
23661
23697
|
).get(hashToken(token));
|
|
23662
|
-
if (!
|
|
23663
|
-
if (
|
|
23664
|
-
if (
|
|
23698
|
+
if (!row2) return "invalid";
|
|
23699
|
+
if (row2.revoked_at !== null) return "revoked";
|
|
23700
|
+
if (row2.expires_at !== null && row2.expires_at <= now) return "expired";
|
|
23665
23701
|
return "invalid";
|
|
23666
23702
|
}
|
|
23667
23703
|
function markUsed(db, id, when = Date.now()) {
|
|
@@ -23681,17 +23717,17 @@ var SESSION_ABSOLUTE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
23681
23717
|
function hash(value) {
|
|
23682
23718
|
return createHash4("sha256").update(value).digest("hex");
|
|
23683
23719
|
}
|
|
23684
|
-
function toSession(
|
|
23720
|
+
function toSession(row2, currentId) {
|
|
23685
23721
|
return {
|
|
23686
|
-
id:
|
|
23687
|
-
deviceTokenId:
|
|
23688
|
-
deviceLabel:
|
|
23689
|
-
createdAt:
|
|
23690
|
-
lastSeenAt:
|
|
23691
|
-
idleExpiresAt:
|
|
23692
|
-
absoluteExpiresAt:
|
|
23693
|
-
revokedAt:
|
|
23694
|
-
current:
|
|
23722
|
+
id: row2.id,
|
|
23723
|
+
deviceTokenId: row2.device_token_id,
|
|
23724
|
+
deviceLabel: row2.device_label,
|
|
23725
|
+
createdAt: row2.created_at,
|
|
23726
|
+
lastSeenAt: row2.last_seen_at,
|
|
23727
|
+
idleExpiresAt: row2.idle_expires_at,
|
|
23728
|
+
absoluteExpiresAt: row2.absolute_expires_at,
|
|
23729
|
+
revokedAt: row2.revoked_at,
|
|
23730
|
+
current: row2.id === currentId
|
|
23695
23731
|
};
|
|
23696
23732
|
}
|
|
23697
23733
|
function create3(db, deviceTokenId, now = Date.now()) {
|
|
@@ -23734,15 +23770,15 @@ function authenticate(db, cookieValue, now = Date.now()) {
|
|
|
23734
23770
|
const id = cookieValue.slice(0, separator);
|
|
23735
23771
|
const secret = cookieValue.slice(separator + 1);
|
|
23736
23772
|
if (!secret) return null;
|
|
23737
|
-
const
|
|
23773
|
+
const row2 = db.raw.query(
|
|
23738
23774
|
`SELECT s.*, t.label AS device_label
|
|
23739
23775
|
FROM web_sessions s JOIN web_tokens t ON t.id = s.device_token_id
|
|
23740
23776
|
WHERE s.id = ? AND s.secret_hash = ? AND s.revoked_at IS NULL
|
|
23741
23777
|
AND s.idle_expires_at > ? AND s.absolute_expires_at > ?
|
|
23742
23778
|
AND t.kind = 'device' AND t.revoked_at IS NULL AND t.expires_at > ?`
|
|
23743
23779
|
).get(id, hash(secret), now, now, now);
|
|
23744
|
-
if (!
|
|
23745
|
-
const idleExpiresAt = Math.min(now + SESSION_IDLE_MS,
|
|
23780
|
+
if (!row2) return null;
|
|
23781
|
+
const idleExpiresAt = Math.min(now + SESSION_IDLE_MS, row2.absolute_expires_at);
|
|
23746
23782
|
db.raw.run("UPDATE web_sessions SET last_seen_at = ?, idle_expires_at = ? WHERE id = ?", [
|
|
23747
23783
|
now,
|
|
23748
23784
|
idleExpiresAt,
|
|
@@ -23750,9 +23786,9 @@ function authenticate(db, cookieValue, now = Date.now()) {
|
|
|
23750
23786
|
]);
|
|
23751
23787
|
return {
|
|
23752
23788
|
id,
|
|
23753
|
-
deviceTokenId:
|
|
23754
|
-
deviceLabel:
|
|
23755
|
-
csrfHash:
|
|
23789
|
+
deviceTokenId: row2.device_token_id,
|
|
23790
|
+
deviceLabel: row2.device_label,
|
|
23791
|
+
csrfHash: row2.csrf_hash
|
|
23756
23792
|
};
|
|
23757
23793
|
}
|
|
23758
23794
|
function csrfMatches(session, csrf) {
|
|
@@ -23764,7 +23800,7 @@ function list10(db, opts = {}) {
|
|
|
23764
23800
|
`SELECT s.*, t.label AS device_label FROM web_sessions s
|
|
23765
23801
|
JOIN web_tokens t ON t.id = s.device_token_id
|
|
23766
23802
|
${where} ORDER BY s.created_at DESC`
|
|
23767
|
-
).all().map((
|
|
23803
|
+
).all().map((row2) => toSession(row2, opts.currentId));
|
|
23768
23804
|
}
|
|
23769
23805
|
function revoke3(db, id, now = Date.now()) {
|
|
23770
23806
|
return db.raw.run("UPDATE web_sessions SET revoked_at = ? WHERE id = ? AND revoked_at IS NULL", [
|
|
@@ -24985,15 +25021,15 @@ function saveCodingCommand(db, receipt) {
|
|
|
24985
25021
|
pruneCodingCommands(db, receipt.teamId);
|
|
24986
25022
|
}
|
|
24987
25023
|
function getCodingCommand(db, id) {
|
|
24988
|
-
const
|
|
25024
|
+
const row2 = db.raw.query(
|
|
24989
25025
|
"SELECT receipt_json FROM coding_commands WHERE id = ?"
|
|
24990
25026
|
).get(id);
|
|
24991
|
-
return
|
|
25027
|
+
return row2 ? JSON.parse(row2.receipt_json) : null;
|
|
24992
25028
|
}
|
|
24993
25029
|
function interruptCodingCommands(db, turnId) {
|
|
24994
25030
|
const rows = db.raw.query("SELECT receipt_json FROM coding_commands").all();
|
|
24995
|
-
for (const
|
|
24996
|
-
const receipt = JSON.parse(
|
|
25031
|
+
for (const row2 of rows) {
|
|
25032
|
+
const receipt = JSON.parse(row2.receipt_json);
|
|
24997
25033
|
if (turnId && receipt.turnId !== turnId) continue;
|
|
24998
25034
|
if (!turnId) receipt.environment.inputFingerprint = null;
|
|
24999
25035
|
if (receipt.state === "running") {
|
|
@@ -25024,15 +25060,15 @@ var receiptFields = `id, source_kind sourceKind, source_id sourceId, agent_id ag
|
|
|
25024
25060
|
function publicDestination(binding) {
|
|
25025
25061
|
return { id: binding.id, chatId: binding.chatId, topicId: binding.topicId };
|
|
25026
25062
|
}
|
|
25027
|
-
function decode(
|
|
25028
|
-
const { destinationJson, ...receipt } =
|
|
25063
|
+
function decode(row2) {
|
|
25064
|
+
const { destinationJson, ...receipt } = row2;
|
|
25029
25065
|
return { ...receipt, destination: publicDestination(JSON.parse(destinationJson)) };
|
|
25030
25066
|
}
|
|
25031
25067
|
function settings(db) {
|
|
25032
|
-
const
|
|
25068
|
+
const row2 = db.raw.query(
|
|
25033
25069
|
`SELECT ${settingsFields} FROM notification_settings WHERE singleton = 1`
|
|
25034
25070
|
).get();
|
|
25035
|
-
if (!
|
|
25071
|
+
if (!row2)
|
|
25036
25072
|
return {
|
|
25037
25073
|
revision: 0,
|
|
25038
25074
|
enabled: false,
|
|
@@ -25045,28 +25081,28 @@ function settings(db) {
|
|
|
25045
25081
|
updatedAt: 0
|
|
25046
25082
|
};
|
|
25047
25083
|
return {
|
|
25048
|
-
revision:
|
|
25049
|
-
enabled:
|
|
25050
|
-
restorePaused:
|
|
25051
|
-
kinds: JSON.parse(
|
|
25052
|
-
timezone:
|
|
25053
|
-
quietHours:
|
|
25054
|
-
destination:
|
|
25055
|
-
eligibleAfter:
|
|
25056
|
-
updatedAt:
|
|
25084
|
+
revision: row2.revision,
|
|
25085
|
+
enabled: row2.enabled === 1,
|
|
25086
|
+
restorePaused: row2.restorePaused === 1,
|
|
25087
|
+
kinds: JSON.parse(row2.kindsJson),
|
|
25088
|
+
timezone: row2.timezone,
|
|
25089
|
+
quietHours: row2.quietJson === null ? null : JSON.parse(row2.quietJson),
|
|
25090
|
+
destination: row2.destinationJson === null ? null : publicDestination(JSON.parse(row2.destinationJson)),
|
|
25091
|
+
eligibleAfter: row2.eligibleAfter,
|
|
25092
|
+
updatedAt: row2.updatedAt
|
|
25057
25093
|
};
|
|
25058
25094
|
}
|
|
25059
25095
|
function destinationBinding(db) {
|
|
25060
|
-
const
|
|
25096
|
+
const row2 = db.raw.query(
|
|
25061
25097
|
"SELECT destination_json value FROM notification_settings WHERE singleton = 1"
|
|
25062
25098
|
).get();
|
|
25063
|
-
return
|
|
25099
|
+
return row2?.value ? JSON.parse(row2.value) : null;
|
|
25064
25100
|
}
|
|
25065
25101
|
function eligibilityCutoffs(db) {
|
|
25066
|
-
const
|
|
25102
|
+
const row2 = db.raw.query(
|
|
25067
25103
|
"SELECT kind_cutoffs_json value FROM notification_settings WHERE singleton=1"
|
|
25068
25104
|
).get();
|
|
25069
|
-
return
|
|
25105
|
+
return row2 ? JSON.parse(row2.value) : {};
|
|
25070
25106
|
}
|
|
25071
25107
|
function hasRestoredHistory(db) {
|
|
25072
25108
|
return db.raw.query(
|
|
@@ -25125,14 +25161,14 @@ function saveSettings(db, expectedRevision, next, binding, now = Date.now()) {
|
|
|
25125
25161
|
})();
|
|
25126
25162
|
}
|
|
25127
25163
|
function get17(db, id) {
|
|
25128
|
-
const
|
|
25129
|
-
return
|
|
25164
|
+
const row2 = db.raw.query(`SELECT ${receiptFields} FROM notification_receipts WHERE id=?`).get(id);
|
|
25165
|
+
return row2 ? decode(row2) : null;
|
|
25130
25166
|
}
|
|
25131
25167
|
function receiptBinding(db, id) {
|
|
25132
|
-
const
|
|
25168
|
+
const row2 = db.raw.query(
|
|
25133
25169
|
"SELECT destination_json value FROM notification_receipts WHERE id=?"
|
|
25134
25170
|
).get(id);
|
|
25135
|
-
return
|
|
25171
|
+
return row2 ? JSON.parse(row2.value) : null;
|
|
25136
25172
|
}
|
|
25137
25173
|
function admit(db, item, binding, now = Date.now()) {
|
|
25138
25174
|
return db.raw.transaction(() => {
|
|
@@ -25170,10 +25206,10 @@ function list11(db, options = {}) {
|
|
|
25170
25206
|
let after = "";
|
|
25171
25207
|
const params = [];
|
|
25172
25208
|
if (options.cursor) {
|
|
25173
|
-
const
|
|
25174
|
-
if (!
|
|
25209
|
+
const row2 = get17(db, options.cursor);
|
|
25210
|
+
if (!row2) throw new Error("notification_cursor_invalid");
|
|
25175
25211
|
after = ` AND (created_at ${comparison} ? OR (created_at = ? AND id ${comparison} ?))`;
|
|
25176
|
-
params.push(
|
|
25212
|
+
params.push(row2.createdAt, row2.createdAt, row2.id);
|
|
25177
25213
|
}
|
|
25178
25214
|
params.push(limit + 1);
|
|
25179
25215
|
const rows = db.raw.query(`SELECT ${receiptFields} FROM notification_receipts
|
|
@@ -25234,8 +25270,202 @@ function recoverInterrupted(db, now = Date.now()) {
|
|
|
25234
25270
|
);
|
|
25235
25271
|
}
|
|
25236
25272
|
|
|
25273
|
+
// ../daemon/src/core/repos/publications.ts
|
|
25274
|
+
import { randomUUID as randomUUID19 } from "crypto";
|
|
25275
|
+
var PUBLICATION_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
25276
|
+
var PublicationError = class extends Error {
|
|
25277
|
+
constructor(code, message) {
|
|
25278
|
+
super(message);
|
|
25279
|
+
this.code = code;
|
|
25280
|
+
}
|
|
25281
|
+
code;
|
|
25282
|
+
};
|
|
25283
|
+
var COLUMNS = `id, team_id, packet_id, snapshot_id, host, repository, base_branch, head_branch,
|
|
25284
|
+
base_oid, commit_message, notify_agent_id, state, refusal_reason, refusal_detail, commit_oid,
|
|
25285
|
+
signed, pull_request_number, pull_request_url, error, created_at, finished_at`;
|
|
25286
|
+
function toRecord(row2) {
|
|
25287
|
+
return {
|
|
25288
|
+
id: row2.id,
|
|
25289
|
+
teamId: row2.team_id,
|
|
25290
|
+
packetId: row2.packet_id,
|
|
25291
|
+
snapshotId: row2.snapshot_id,
|
|
25292
|
+
host: row2.host,
|
|
25293
|
+
repository: row2.repository,
|
|
25294
|
+
baseBranch: row2.base_branch,
|
|
25295
|
+
headBranch: row2.head_branch,
|
|
25296
|
+
baseOid: row2.base_oid,
|
|
25297
|
+
commitMessage: row2.commit_message,
|
|
25298
|
+
notifyAgentId: row2.notify_agent_id,
|
|
25299
|
+
state: row2.state,
|
|
25300
|
+
refusalReason: row2.refusal_reason,
|
|
25301
|
+
refusalDetail: row2.refusal_detail,
|
|
25302
|
+
commitOid: row2.commit_oid,
|
|
25303
|
+
// Always false. Read from the row rather than assumed, so a future migration that stores 1 would
|
|
25304
|
+
// surface here instead of being silently reported as unsigned.
|
|
25305
|
+
signed: row2.signed === 1,
|
|
25306
|
+
pullRequestNumber: row2.pull_request_number,
|
|
25307
|
+
pullRequestUrl: row2.pull_request_url,
|
|
25308
|
+
error: row2.error,
|
|
25309
|
+
createdAt: row2.created_at,
|
|
25310
|
+
finishedAt: row2.finished_at
|
|
25311
|
+
};
|
|
25312
|
+
}
|
|
25313
|
+
function createPublication(db, input) {
|
|
25314
|
+
const now = input.now ?? Date.now();
|
|
25315
|
+
const id = randomUUID19();
|
|
25316
|
+
return inTx(db, () => {
|
|
25317
|
+
const published = db.raw.query(
|
|
25318
|
+
"SELECT id FROM publications WHERE packet_id = ? AND state = 'published'"
|
|
25319
|
+
).get(input.packetId);
|
|
25320
|
+
if (published) {
|
|
25321
|
+
throw new PublicationError(
|
|
25322
|
+
"already_published",
|
|
25323
|
+
"this packet already has a published revision; publishing it again would duplicate the work"
|
|
25324
|
+
);
|
|
25325
|
+
}
|
|
25326
|
+
db.raw.run(
|
|
25327
|
+
`INSERT INTO publications (
|
|
25328
|
+
id, team_id, packet_id, snapshot_id, host, repository, base_branch, head_branch, base_oid,
|
|
25329
|
+
commit_message, notify_agent_id, state, signed, created_at, updated_at
|
|
25330
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'pending', 0, ?, ?)`,
|
|
25331
|
+
[
|
|
25332
|
+
id,
|
|
25333
|
+
input.teamId,
|
|
25334
|
+
input.packetId,
|
|
25335
|
+
input.snapshotId,
|
|
25336
|
+
input.host,
|
|
25337
|
+
input.repository,
|
|
25338
|
+
input.baseBranch,
|
|
25339
|
+
input.headBranch,
|
|
25340
|
+
input.baseOid,
|
|
25341
|
+
input.commitMessage,
|
|
25342
|
+
input.notifyAgentId ?? null,
|
|
25343
|
+
now,
|
|
25344
|
+
now
|
|
25345
|
+
]
|
|
25346
|
+
);
|
|
25347
|
+
const created = getPublication(db, id);
|
|
25348
|
+
if (!created)
|
|
25349
|
+
throw new PublicationError("publication_not_found", "the publication could not be read back");
|
|
25350
|
+
return created;
|
|
25351
|
+
});
|
|
25352
|
+
}
|
|
25353
|
+
function getPublication(db, id) {
|
|
25354
|
+
const row2 = db.raw.query(`SELECT ${COLUMNS} FROM publications WHERE id = ?`).get(id);
|
|
25355
|
+
return row2 ? toRecord(row2) : null;
|
|
25356
|
+
}
|
|
25357
|
+
function listPublications(db, teamId, limit = 50) {
|
|
25358
|
+
return db.raw.query(
|
|
25359
|
+
`SELECT ${COLUMNS} FROM publications WHERE team_id = ? ORDER BY created_at DESC, id DESC LIMIT ?`
|
|
25360
|
+
).all(teamId, limit).map(toRecord);
|
|
25361
|
+
}
|
|
25362
|
+
function claimPublication(db, input) {
|
|
25363
|
+
const now = input.now ?? Date.now();
|
|
25364
|
+
return inTx(db, () => {
|
|
25365
|
+
const result = db.raw.run(
|
|
25366
|
+
`UPDATE publications
|
|
25367
|
+
SET state = 'publishing', claimed_by = ?, lease_expires_at = ?, updated_at = ?
|
|
25368
|
+
WHERE id = ? AND state = 'pending'
|
|
25369
|
+
AND NOT EXISTS (
|
|
25370
|
+
SELECT 1 FROM publications p2
|
|
25371
|
+
WHERE p2.packet_id = publications.packet_id AND p2.state = 'published'
|
|
25372
|
+
)`,
|
|
25373
|
+
[input.leaseOwner, now + input.leaseMs, now, input.id]
|
|
25374
|
+
);
|
|
25375
|
+
if (Number(result.changes) === 0) return null;
|
|
25376
|
+
return getPublication(db, input.id);
|
|
25377
|
+
});
|
|
25378
|
+
}
|
|
25379
|
+
function refusePublication(db, input) {
|
|
25380
|
+
const now = input.now ?? Date.now();
|
|
25381
|
+
const record3 = inTx(db, () => {
|
|
25382
|
+
const result = db.raw.run(
|
|
25383
|
+
`UPDATE publications
|
|
25384
|
+
SET state = 'refused', refusal_reason = ?, refusal_detail = ?, lease_expires_at = NULL,
|
|
25385
|
+
claimed_by = NULL, finished_at = ?, updated_at = ?
|
|
25386
|
+
WHERE id = ? AND state IN ('pending', 'publishing')`,
|
|
25387
|
+
[input.reason, input.detail, now, now, input.id]
|
|
25388
|
+
);
|
|
25389
|
+
if (Number(result.changes) === 0) {
|
|
25390
|
+
throw new PublicationError(
|
|
25391
|
+
"publication_conflict",
|
|
25392
|
+
"a publication that already left the machine cannot be refused"
|
|
25393
|
+
);
|
|
25394
|
+
}
|
|
25395
|
+
return row(db, input.id);
|
|
25396
|
+
});
|
|
25397
|
+
return record3;
|
|
25398
|
+
}
|
|
25399
|
+
function settlePublicationPublished(db, input) {
|
|
25400
|
+
const now = input.now ?? Date.now();
|
|
25401
|
+
inTx(db, () => {
|
|
25402
|
+
const result = db.raw.run(
|
|
25403
|
+
`UPDATE publications
|
|
25404
|
+
SET state = 'published', commit_oid = ?, pull_request_number = ?, pull_request_url = ?,
|
|
25405
|
+
lease_expires_at = NULL, claimed_by = NULL, finished_at = ?, updated_at = ?
|
|
25406
|
+
WHERE id = ? AND state = 'publishing'`,
|
|
25407
|
+
[input.commitOid, input.pullRequestNumber, input.pullRequestUrl, now, now, input.id]
|
|
25408
|
+
);
|
|
25409
|
+
if (Number(result.changes) === 0) {
|
|
25410
|
+
throw new PublicationError("publication_conflict", "the publication was not being published");
|
|
25411
|
+
}
|
|
25412
|
+
});
|
|
25413
|
+
return row(db, input.id);
|
|
25414
|
+
}
|
|
25415
|
+
function settlePublicationUncertain(db, input) {
|
|
25416
|
+
return settleUnsent(
|
|
25417
|
+
db,
|
|
25418
|
+
input.id,
|
|
25419
|
+
"uncertain",
|
|
25420
|
+
input.error || "the attempt was interrupted before its outcome was recorded",
|
|
25421
|
+
input.now
|
|
25422
|
+
);
|
|
25423
|
+
}
|
|
25424
|
+
function settleUnsent(db, id, state3, error2, now = Date.now()) {
|
|
25425
|
+
inTx(db, () => {
|
|
25426
|
+
const result = db.raw.run(
|
|
25427
|
+
`UPDATE publications
|
|
25428
|
+
SET state = ?, error = ?, lease_expires_at = NULL, claimed_by = NULL,
|
|
25429
|
+
finished_at = ?, updated_at = ?
|
|
25430
|
+
WHERE id = ? AND state = 'publishing'`,
|
|
25431
|
+
[state3, error2, now, now, id]
|
|
25432
|
+
);
|
|
25433
|
+
if (Number(result.changes) === 0) {
|
|
25434
|
+
throw new PublicationError("publication_conflict", `the publication was not being published`);
|
|
25435
|
+
}
|
|
25436
|
+
});
|
|
25437
|
+
return row(db, id);
|
|
25438
|
+
}
|
|
25439
|
+
function recoverExpiredPublications(db, now = Date.now()) {
|
|
25440
|
+
const expired = db.raw.query(
|
|
25441
|
+
"SELECT id FROM publications WHERE state = 'publishing' AND lease_expires_at <= ?"
|
|
25442
|
+
).all(now);
|
|
25443
|
+
const recovered = [];
|
|
25444
|
+
for (const { id } of expired) {
|
|
25445
|
+
settlePublicationUncertain(db, {
|
|
25446
|
+
id,
|
|
25447
|
+
error: "the publishing process did not finish; whether the branch reached the host is unknown",
|
|
25448
|
+
now
|
|
25449
|
+
});
|
|
25450
|
+
recovered.push(id);
|
|
25451
|
+
}
|
|
25452
|
+
return recovered;
|
|
25453
|
+
}
|
|
25454
|
+
function row(db, id) {
|
|
25455
|
+
const record3 = getPublication(db, id);
|
|
25456
|
+
if (!record3) throw new PublicationError("publication_not_found", "the publication is gone");
|
|
25457
|
+
return record3;
|
|
25458
|
+
}
|
|
25459
|
+
function notePublicationError(db, id, error2, now = Date.now()) {
|
|
25460
|
+
db.raw.run("UPDATE publications SET error = ?, updated_at = ? WHERE id = ?", [
|
|
25461
|
+
error2.slice(0, 400),
|
|
25462
|
+
now,
|
|
25463
|
+
id
|
|
25464
|
+
]);
|
|
25465
|
+
}
|
|
25466
|
+
|
|
25237
25467
|
// ../daemon/src/core/repos/questions.ts
|
|
25238
|
-
import { createHash as createHash6, randomUUID as
|
|
25468
|
+
import { createHash as createHash6, randomUUID as randomUUID20 } from "crypto";
|
|
25239
25469
|
|
|
25240
25470
|
// ../daemon/src/lib/question-input.ts
|
|
25241
25471
|
var QUESTION_LIMITS = Object.freeze({
|
|
@@ -25336,8 +25566,8 @@ var fields = `id, agent_id AS agentId, team_id AS teamId, conversation_id AS con
|
|
|
25336
25566
|
created_at AS createdAt, expires_at AS expiresAt, settled_at AS settledAt, delivered_at AS deliveredAt, answer_json AS answerJson,
|
|
25337
25567
|
response_request_id AS responseRequestId, no_answer_reason AS noAnswerReason, continuation,
|
|
25338
25568
|
consumed_at AS consumedAt, delivery_approval_id AS deliveryApprovalId, answer_approval_id AS answerApprovalId`;
|
|
25339
|
-
function decode2(
|
|
25340
|
-
const { questionJson, answerJson, ...item } =
|
|
25569
|
+
function decode2(row2) {
|
|
25570
|
+
const { questionJson, answerJson, ...item } = row2;
|
|
25341
25571
|
return {
|
|
25342
25572
|
...item,
|
|
25343
25573
|
question: parseQuestionInput(JSON.parse(questionJson)),
|
|
@@ -25345,10 +25575,10 @@ function decode2(row) {
|
|
|
25345
25575
|
};
|
|
25346
25576
|
}
|
|
25347
25577
|
function get18(db, agentId, id) {
|
|
25348
|
-
const
|
|
25578
|
+
const row2 = db.raw.query(
|
|
25349
25579
|
`SELECT ${fields} FROM agent_questions WHERE agent_id = ? AND id = ?`
|
|
25350
25580
|
).get(agentId, id);
|
|
25351
|
-
return
|
|
25581
|
+
return row2 ? decode2(row2) : null;
|
|
25352
25582
|
}
|
|
25353
25583
|
function list12(db, agentId, limit = 20, conversationId) {
|
|
25354
25584
|
if (!Number.isInteger(limit) || limit < 1 || limit > 100)
|
|
@@ -25381,7 +25611,7 @@ function create4(db, input, now = Date.now()) {
|
|
|
25381
25611
|
COALESCE(SUM(status = 'pending'), 0) AS pending, COALESCE(SUM(turn_id = ?), 0) AS turn FROM agent_questions`).get(input.turnId);
|
|
25382
25612
|
if (!count3 || count3.total >= QUESTION_LIMITS.recordsPerHome || count3.pending >= QUESTION_LIMITS.pendingPerHome || count3.turn >= QUESTION_LIMITS.perTurn)
|
|
25383
25613
|
throw new Error("Question capacity reached");
|
|
25384
|
-
const id =
|
|
25614
|
+
const id = randomUUID20();
|
|
25385
25615
|
db.raw.run(
|
|
25386
25616
|
`INSERT INTO agent_questions (id, agent_id, team_id, conversation_id, turn_id, tool_call_id,
|
|
25387
25617
|
question_json, binding_json, status, created_at, expires_at, continuation) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'pending', ?, ?, 'waiting')`,
|
|
@@ -25493,10 +25723,10 @@ function retireClosedApprovals(db, now) {
|
|
|
25493
25723
|
WHERE q.status != 'pending' AND a.status = 'pending'
|
|
25494
25724
|
AND a.payload_kind IN ('question_delivery', 'question_answer')
|
|
25495
25725
|
`).all();
|
|
25496
|
-
for (const
|
|
25726
|
+
for (const row2 of rows)
|
|
25497
25727
|
decide(
|
|
25498
25728
|
db,
|
|
25499
|
-
|
|
25729
|
+
row2.id,
|
|
25500
25730
|
"cancel",
|
|
25501
25731
|
"system",
|
|
25502
25732
|
"Originating question is closed",
|
|
@@ -25507,13 +25737,13 @@ var digest2 = (value) => createHash6("sha256").update(JSON.stringify(value)).dig
|
|
|
25507
25737
|
function approvalSnapshot(db, agentId, id) {
|
|
25508
25738
|
const question = get18(db, agentId, id);
|
|
25509
25739
|
if (!question) return null;
|
|
25510
|
-
const
|
|
25740
|
+
const row2 = db.raw.query(
|
|
25511
25741
|
"SELECT binding_json, proposal_json FROM agent_questions WHERE id = ?"
|
|
25512
25742
|
).get(id);
|
|
25513
|
-
if (!
|
|
25743
|
+
if (!row2 || Buffer.byteLength(row2.binding_json) > 16384 || row2.proposal_json && Buffer.byteLength(row2.proposal_json) > 32768)
|
|
25514
25744
|
throw new Error("Question binding unavailable");
|
|
25515
|
-
const proposal =
|
|
25516
|
-
JSON.parse(
|
|
25745
|
+
const proposal = row2.proposal_json ? parseQuestionResponse(
|
|
25746
|
+
JSON.parse(row2.proposal_json),
|
|
25517
25747
|
question.question,
|
|
25518
25748
|
question.conversationId
|
|
25519
25749
|
) : null;
|
|
@@ -25525,7 +25755,7 @@ function approvalSnapshot(db, agentId, id) {
|
|
|
25525
25755
|
turnId: question.turnId,
|
|
25526
25756
|
toolCallId: question.toolCallId,
|
|
25527
25757
|
question: question.question,
|
|
25528
|
-
binding: JSON.parse(
|
|
25758
|
+
binding: JSON.parse(row2.binding_json)
|
|
25529
25759
|
});
|
|
25530
25760
|
return {
|
|
25531
25761
|
question,
|
|
@@ -25582,7 +25812,7 @@ function ownsApproval(db, capturedId, providedId) {
|
|
|
25582
25812
|
}
|
|
25583
25813
|
|
|
25584
25814
|
// ../daemon/src/core/repos/review-packets.ts
|
|
25585
|
-
import { randomUUID as
|
|
25815
|
+
import { randomUUID as randomUUID21 } from "crypto";
|
|
25586
25816
|
var REVIEW_PACKET_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
25587
25817
|
var REVIEW_LIMITS = {
|
|
25588
25818
|
summary: 2e3,
|
|
@@ -25612,7 +25842,7 @@ function assertLength(value, max, field) {
|
|
|
25612
25842
|
}
|
|
25613
25843
|
function createReviewPacket(db, input) {
|
|
25614
25844
|
const now = input.now ?? Date.now();
|
|
25615
|
-
const id =
|
|
25845
|
+
const id = randomUUID21();
|
|
25616
25846
|
if (input.summary) assertLength(input.summary, REVIEW_LIMITS.summary, "summary");
|
|
25617
25847
|
db.raw.run(
|
|
25618
25848
|
`INSERT INTO review_packets (
|
|
@@ -25639,16 +25869,16 @@ function createReviewPacket(db, input) {
|
|
|
25639
25869
|
return created;
|
|
25640
25870
|
}
|
|
25641
25871
|
function getReviewPacket(db, id, now = Date.now()) {
|
|
25642
|
-
const
|
|
25872
|
+
const row2 = db.raw.query(
|
|
25643
25873
|
`SELECT ${PACKET_COLUMNS} FROM review_packets WHERE id = ? AND expires_at > ?`
|
|
25644
25874
|
).get(id, now);
|
|
25645
|
-
return
|
|
25875
|
+
return row2 ? toPacket(row2) : null;
|
|
25646
25876
|
}
|
|
25647
25877
|
function getTeamReviewPacket(db, teamId, id, now = Date.now()) {
|
|
25648
|
-
const
|
|
25878
|
+
const row2 = db.raw.query(
|
|
25649
25879
|
`SELECT ${PACKET_COLUMNS} FROM review_packets WHERE id = ? AND team_id = ? AND expires_at > ?`
|
|
25650
25880
|
).get(id, teamId, now);
|
|
25651
|
-
return
|
|
25881
|
+
return row2 ? toPacket(row2) : null;
|
|
25652
25882
|
}
|
|
25653
25883
|
function listReviewPackets(db, teamId, limit = 50, now = Date.now()) {
|
|
25654
25884
|
return db.raw.query(
|
|
@@ -25691,7 +25921,7 @@ function addReviewFinding(db, input) {
|
|
|
25691
25921
|
`a packet holds at most ${REVIEW_LIMITS.findings} findings`
|
|
25692
25922
|
);
|
|
25693
25923
|
}
|
|
25694
|
-
const id =
|
|
25924
|
+
const id = randomUUID21();
|
|
25695
25925
|
db.raw.run(
|
|
25696
25926
|
`INSERT INTO review_findings (
|
|
25697
25927
|
id, packet_id, author_kind, author_agent_id, path, line_start, line_end, severity, note,
|
|
@@ -25712,14 +25942,14 @@ function addReviewFinding(db, input) {
|
|
|
25712
25942
|
input.now ?? Date.now()
|
|
25713
25943
|
]
|
|
25714
25944
|
);
|
|
25715
|
-
const
|
|
25716
|
-
if (!
|
|
25717
|
-
return
|
|
25945
|
+
const row2 = getReviewFinding(db, id);
|
|
25946
|
+
if (!row2) throw new ReviewPacketError("finding_not_found", "the finding could not be read back");
|
|
25947
|
+
return row2;
|
|
25718
25948
|
});
|
|
25719
25949
|
}
|
|
25720
25950
|
function getReviewFinding(db, id) {
|
|
25721
|
-
const
|
|
25722
|
-
return
|
|
25951
|
+
const row2 = db.raw.query(`SELECT ${FINDING_COLUMNS} FROM review_findings WHERE id = ?`).get(id);
|
|
25952
|
+
return row2 ? toFinding(row2) : null;
|
|
25723
25953
|
}
|
|
25724
25954
|
function listReviewFindings(db, packetId) {
|
|
25725
25955
|
return db.raw.query(
|
|
@@ -25760,7 +25990,7 @@ function resolveReviewFinding(db, input) {
|
|
|
25760
25990
|
}
|
|
25761
25991
|
function recordReviewConclusion(db, input) {
|
|
25762
25992
|
if (input.note) assertLength(input.note, REVIEW_LIMITS.note, "conclusion note");
|
|
25763
|
-
const id =
|
|
25993
|
+
const id = randomUUID21();
|
|
25764
25994
|
db.raw.run(
|
|
25765
25995
|
`INSERT INTO review_conclusions (
|
|
25766
25996
|
id, packet_id, reviewer_kind, reviewer_agent_id, conclusion, note, snapshot_id, created_at
|
|
@@ -25781,12 +26011,14 @@ function recordReviewConclusion(db, input) {
|
|
|
25781
26011
|
input.now ?? Date.now()
|
|
25782
26012
|
]
|
|
25783
26013
|
);
|
|
25784
|
-
const
|
|
26014
|
+
const row2 = db.raw.query(
|
|
25785
26015
|
`SELECT ${CONCLUSION_COLUMNS} FROM review_conclusions
|
|
25786
26016
|
WHERE packet_id = ? AND reviewer_kind = ? AND reviewer_agent_id IS ?`
|
|
25787
26017
|
).get(input.packetId, input.reviewerKind, input.reviewerAgentId ?? null);
|
|
25788
|
-
if (!
|
|
25789
|
-
|
|
26018
|
+
if (!row2) throw new ReviewPacketError("packet_not_found", "the conclusion could not be read back");
|
|
26019
|
+
const packet = getReviewPacket(db, input.packetId);
|
|
26020
|
+
if (packet?.state === "open") setReviewPacketState(db, input.packetId, "reviewed");
|
|
26021
|
+
return toConclusion(row2);
|
|
25790
26022
|
}
|
|
25791
26023
|
function listReviewConclusions(db, packetId) {
|
|
25792
26024
|
return db.raw.query(
|
|
@@ -25801,7 +26033,7 @@ function claimReviewAttempt(db, input) {
|
|
|
25801
26033
|
const next = (db.raw.query(
|
|
25802
26034
|
"SELECT COALESCE(MAX(attempt_number), 0) AS n FROM review_attempts WHERE packet_id = ?"
|
|
25803
26035
|
).get(input.packetId)?.n ?? 0) + 1;
|
|
25804
|
-
const id =
|
|
26036
|
+
const id = randomUUID21();
|
|
25805
26037
|
db.raw.run(
|
|
25806
26038
|
`INSERT INTO review_attempts (
|
|
25807
26039
|
id, packet_id, attempt_number, supersedes_attempt_id, state, lease_owner, lease_expires_at, created_at
|
|
@@ -25824,8 +26056,8 @@ function claimReviewAttempt(db, input) {
|
|
|
25824
26056
|
});
|
|
25825
26057
|
}
|
|
25826
26058
|
function getReviewAttempt(db, id) {
|
|
25827
|
-
const
|
|
25828
|
-
return
|
|
26059
|
+
const row2 = db.raw.query(`SELECT ${ATTEMPT_COLUMNS} FROM review_attempts WHERE id = ?`).get(id);
|
|
26060
|
+
return row2 ? toAttempt(row2) : null;
|
|
25829
26061
|
}
|
|
25830
26062
|
function listReviewAttempts(db, packetId) {
|
|
25831
26063
|
return db.raw.query(
|
|
@@ -25836,11 +26068,11 @@ function finishReviewAttempt(db, input) {
|
|
|
25836
26068
|
if (input.error != null) assertLength(input.error, REVIEW_LIMITS.summary, "error");
|
|
25837
26069
|
const now = input.now ?? Date.now();
|
|
25838
26070
|
return inTx(db, () => {
|
|
25839
|
-
const
|
|
26071
|
+
const row2 = db.raw.query(
|
|
25840
26072
|
`SELECT ${ATTEMPT_COLUMNS} FROM review_attempts WHERE id = ? AND lease_owner = ?`
|
|
25841
26073
|
).get(input.attemptId, input.leaseOwner);
|
|
25842
|
-
if (!
|
|
25843
|
-
const attempt = toAttempt(
|
|
26074
|
+
if (!row2) return false;
|
|
26075
|
+
const attempt = toAttempt(row2);
|
|
25844
26076
|
if (attempt.finishedAt !== null) return false;
|
|
25845
26077
|
db.raw.run(
|
|
25846
26078
|
`UPDATE review_attempts
|
|
@@ -25877,24 +26109,24 @@ var PACKET_COLUMNS = "id, team_id, requester_kind, requester_agent_id, reviewer_
|
|
|
25877
26109
|
var FINDING_COLUMNS = "id, packet_id, author_kind, author_agent_id, path, line_start, line_end, severity, note, snapshot_id, state, resolution_kind, resolution_note, resolved_at, resolved_by_kind, resolved_by_agent_id, created_at";
|
|
25878
26110
|
var CONCLUSION_COLUMNS = "id, packet_id, reviewer_kind, reviewer_agent_id, conclusion, note, snapshot_id, created_at";
|
|
25879
26111
|
var ATTEMPT_COLUMNS = "id, packet_id, attempt_number, supersedes_attempt_id, state, lease_owner, lease_expires_at, started_at, finished_at, error, created_at";
|
|
25880
|
-
function toPacket(
|
|
26112
|
+
function toPacket(row2) {
|
|
25881
26113
|
return {
|
|
25882
|
-
id:
|
|
25883
|
-
teamId:
|
|
25884
|
-
requesterKind:
|
|
25885
|
-
requesterAgentId:
|
|
25886
|
-
reviewerAgentId:
|
|
25887
|
-
snapshotId:
|
|
25888
|
-
snapshotComplete:
|
|
25889
|
-
head:
|
|
25890
|
-
baseOid:
|
|
25891
|
-
summary:
|
|
25892
|
-
state:
|
|
25893
|
-
exportedAt:
|
|
25894
|
-
exportRevision:
|
|
25895
|
-
reported: parseReported(
|
|
25896
|
-
createdAt:
|
|
25897
|
-
expiresAt:
|
|
26114
|
+
id: row2.id,
|
|
26115
|
+
teamId: row2.team_id,
|
|
26116
|
+
requesterKind: row2.requester_kind,
|
|
26117
|
+
requesterAgentId: row2.requester_agent_id,
|
|
26118
|
+
reviewerAgentId: row2.reviewer_agent_id,
|
|
26119
|
+
snapshotId: row2.snapshot_id,
|
|
26120
|
+
snapshotComplete: row2.snapshot_complete === 1,
|
|
26121
|
+
head: row2.head,
|
|
26122
|
+
baseOid: row2.base_oid,
|
|
26123
|
+
summary: row2.summary,
|
|
26124
|
+
state: row2.state,
|
|
26125
|
+
exportedAt: row2.exported_at,
|
|
26126
|
+
exportRevision: row2.export_revision,
|
|
26127
|
+
reported: parseReported(row2.reported_json),
|
|
26128
|
+
createdAt: row2.created_at,
|
|
26129
|
+
expiresAt: row2.expires_at
|
|
25898
26130
|
};
|
|
25899
26131
|
}
|
|
25900
26132
|
function parseReported(json) {
|
|
@@ -25934,57 +26166,57 @@ function recordReportedState(db, input) {
|
|
|
25934
26166
|
]);
|
|
25935
26167
|
return next;
|
|
25936
26168
|
}
|
|
25937
|
-
function toFinding(
|
|
26169
|
+
function toFinding(row2) {
|
|
25938
26170
|
return {
|
|
25939
|
-
id:
|
|
25940
|
-
packetId:
|
|
25941
|
-
authorKind:
|
|
25942
|
-
authorAgentId:
|
|
25943
|
-
path:
|
|
25944
|
-
lineStart:
|
|
25945
|
-
lineEnd:
|
|
25946
|
-
severity:
|
|
25947
|
-
note:
|
|
25948
|
-
snapshotId:
|
|
25949
|
-
state:
|
|
25950
|
-
resolutionKind:
|
|
25951
|
-
resolutionNote:
|
|
25952
|
-
resolvedAt:
|
|
25953
|
-
resolvedByKind:
|
|
25954
|
-
resolvedByAgentId:
|
|
25955
|
-
createdAt:
|
|
25956
|
-
};
|
|
25957
|
-
}
|
|
25958
|
-
function toConclusion(
|
|
26171
|
+
id: row2.id,
|
|
26172
|
+
packetId: row2.packet_id,
|
|
26173
|
+
authorKind: row2.author_kind,
|
|
26174
|
+
authorAgentId: row2.author_agent_id,
|
|
26175
|
+
path: row2.path,
|
|
26176
|
+
lineStart: row2.line_start,
|
|
26177
|
+
lineEnd: row2.line_end,
|
|
26178
|
+
severity: row2.severity,
|
|
26179
|
+
note: row2.note,
|
|
26180
|
+
snapshotId: row2.snapshot_id,
|
|
26181
|
+
state: row2.state,
|
|
26182
|
+
resolutionKind: row2.resolution_kind,
|
|
26183
|
+
resolutionNote: row2.resolution_note,
|
|
26184
|
+
resolvedAt: row2.resolved_at,
|
|
26185
|
+
resolvedByKind: row2.resolved_by_kind,
|
|
26186
|
+
resolvedByAgentId: row2.resolved_by_agent_id,
|
|
26187
|
+
createdAt: row2.created_at
|
|
26188
|
+
};
|
|
26189
|
+
}
|
|
26190
|
+
function toConclusion(row2) {
|
|
25959
26191
|
return {
|
|
25960
|
-
id:
|
|
25961
|
-
packetId:
|
|
25962
|
-
reviewerKind:
|
|
25963
|
-
reviewerAgentId:
|
|
25964
|
-
conclusion:
|
|
25965
|
-
note:
|
|
25966
|
-
snapshotId:
|
|
25967
|
-
createdAt:
|
|
26192
|
+
id: row2.id,
|
|
26193
|
+
packetId: row2.packet_id,
|
|
26194
|
+
reviewerKind: row2.reviewer_kind,
|
|
26195
|
+
reviewerAgentId: row2.reviewer_agent_id,
|
|
26196
|
+
conclusion: row2.conclusion,
|
|
26197
|
+
note: row2.note,
|
|
26198
|
+
snapshotId: row2.snapshot_id,
|
|
26199
|
+
createdAt: row2.created_at
|
|
25968
26200
|
};
|
|
25969
26201
|
}
|
|
25970
|
-
function toAttempt(
|
|
26202
|
+
function toAttempt(row2) {
|
|
25971
26203
|
return {
|
|
25972
|
-
id:
|
|
25973
|
-
packetId:
|
|
25974
|
-
attemptNumber:
|
|
25975
|
-
supersedesAttemptId:
|
|
25976
|
-
state:
|
|
25977
|
-
leaseOwner:
|
|
25978
|
-
leaseExpiresAt:
|
|
25979
|
-
startedAt:
|
|
25980
|
-
finishedAt:
|
|
25981
|
-
error:
|
|
25982
|
-
createdAt:
|
|
26204
|
+
id: row2.id,
|
|
26205
|
+
packetId: row2.packet_id,
|
|
26206
|
+
attemptNumber: row2.attempt_number,
|
|
26207
|
+
supersedesAttemptId: row2.supersedes_attempt_id,
|
|
26208
|
+
state: row2.state,
|
|
26209
|
+
leaseOwner: row2.lease_owner,
|
|
26210
|
+
leaseExpiresAt: row2.lease_expires_at,
|
|
26211
|
+
startedAt: row2.started_at,
|
|
26212
|
+
finishedAt: row2.finished_at,
|
|
26213
|
+
error: row2.error,
|
|
26214
|
+
createdAt: row2.created_at
|
|
25983
26215
|
};
|
|
25984
26216
|
}
|
|
25985
26217
|
|
|
25986
26218
|
// ../daemon/src/core/repos/user-queue.ts
|
|
25987
|
-
import { createHash as createHash7, randomUUID as
|
|
26219
|
+
import { createHash as createHash7, randomUUID as randomUUID22 } from "crypto";
|
|
25988
26220
|
var QUEUE_LIMITS = Object.freeze({
|
|
25989
26221
|
perAgent: 20,
|
|
25990
26222
|
perHome: 100,
|
|
@@ -26039,10 +26271,10 @@ function normalize2(message, attachments2) {
|
|
|
26039
26271
|
return { message, files, total };
|
|
26040
26272
|
}
|
|
26041
26273
|
function control(db, agentId) {
|
|
26042
|
-
const
|
|
26274
|
+
const row2 = db.raw.query(
|
|
26043
26275
|
"SELECT paused, revision, reason FROM user_queue_controls WHERE agent_id = ?"
|
|
26044
26276
|
).get(agentId);
|
|
26045
|
-
return
|
|
26277
|
+
return row2 ? { ...row2, paused: row2.paused === 1 } : { paused: false, revision: 0, reason: null };
|
|
26046
26278
|
}
|
|
26047
26279
|
function ensureControl(db, agentId) {
|
|
26048
26280
|
db.raw.run("INSERT INTO user_queue_controls (agent_id) VALUES (?) ON CONFLICT DO NOTHING", [
|
|
@@ -26054,18 +26286,18 @@ function attachments(db, id) {
|
|
|
26054
26286
|
`SELECT id, name, mime_type AS mimeType, byte_length AS byteLength, sha256 FROM user_queue_attachments WHERE item_id = ? ORDER BY ordinal`
|
|
26055
26287
|
).all(id);
|
|
26056
26288
|
}
|
|
26057
|
-
function hydrate(db,
|
|
26289
|
+
function hydrate(db, row2) {
|
|
26058
26290
|
return {
|
|
26059
|
-
...
|
|
26060
|
-
payloadRetained:
|
|
26061
|
-
attachments: attachments(db,
|
|
26291
|
+
...row2,
|
|
26292
|
+
payloadRetained: row2.payloadRetained === 1,
|
|
26293
|
+
attachments: attachments(db, row2.id)
|
|
26062
26294
|
};
|
|
26063
26295
|
}
|
|
26064
26296
|
function get19(db, agentId, id) {
|
|
26065
|
-
const
|
|
26297
|
+
const row2 = db.raw.query(
|
|
26066
26298
|
`SELECT ${fields2} FROM user_queue_items WHERE agent_id = ? AND id = ?`
|
|
26067
26299
|
).get(agentId, id);
|
|
26068
|
-
return
|
|
26300
|
+
return row2 ? hydrate(db, row2) : null;
|
|
26069
26301
|
}
|
|
26070
26302
|
function list13(db, agentId, options = {}) {
|
|
26071
26303
|
const { all = false, limit = 20, offset = 0 } = options;
|
|
@@ -26077,7 +26309,7 @@ function list13(db, agentId, options = {}) {
|
|
|
26077
26309
|
).all(agentId, limit, offset);
|
|
26078
26310
|
const total = db.raw.query(`SELECT count(*) n FROM user_queue_items WHERE ${where}`).get(agentId)?.n ?? 0;
|
|
26079
26311
|
return {
|
|
26080
|
-
items: rows.map((
|
|
26312
|
+
items: rows.map((row2) => hydrate(db, row2)),
|
|
26081
26313
|
control: control(db, agentId),
|
|
26082
26314
|
total,
|
|
26083
26315
|
limit,
|
|
@@ -26172,7 +26404,7 @@ function accept(db, input, replacement) {
|
|
|
26172
26404
|
db.raw.run(
|
|
26173
26405
|
`INSERT INTO user_queue_attachments (id,item_id,ordinal,name,mime_type,byte_length,sha256,bytes) VALUES (?,?,?,?,?,?,?,?)`,
|
|
26174
26406
|
[
|
|
26175
|
-
|
|
26407
|
+
randomUUID22(),
|
|
26176
26408
|
input.id,
|
|
26177
26409
|
ordinal,
|
|
26178
26410
|
file.name,
|
|
@@ -26192,10 +26424,10 @@ function readInput(db, agentId, id) {
|
|
|
26192
26424
|
const item = get19(db, agentId, id);
|
|
26193
26425
|
if (!item?.payloadRetained || item.text === null)
|
|
26194
26426
|
throw new Error("Queue input no longer retained");
|
|
26195
|
-
const
|
|
26427
|
+
const row2 = db.raw.query(
|
|
26196
26428
|
"SELECT provenance_json, input_digest FROM user_queue_items WHERE id = ?"
|
|
26197
26429
|
).get(id);
|
|
26198
|
-
if (!
|
|
26430
|
+
if (!row2) throw new Error("Queue input unavailable");
|
|
26199
26431
|
const retainedSize = db.raw.query(
|
|
26200
26432
|
"SELECT count(*) n, coalesce(sum(length(bytes)),0) bytes FROM user_queue_attachments WHERE item_id = ?"
|
|
26201
26433
|
).get(id);
|
|
@@ -26213,7 +26445,7 @@ function readInput(db, agentId, id) {
|
|
|
26213
26445
|
};
|
|
26214
26446
|
});
|
|
26215
26447
|
const normalized = normalize2(item.text, restored);
|
|
26216
|
-
const provenance = JSON.parse(
|
|
26448
|
+
const provenance = JSON.parse(row2.provenance_json);
|
|
26217
26449
|
const actualDigest = hash2(
|
|
26218
26450
|
JSON.stringify({
|
|
26219
26451
|
agentId: item.agentId,
|
|
@@ -26226,9 +26458,9 @@ function readInput(db, agentId, id) {
|
|
|
26226
26458
|
replaces: item.supersedesId
|
|
26227
26459
|
})
|
|
26228
26460
|
);
|
|
26229
|
-
if (actualDigest !==
|
|
26461
|
+
if (actualDigest !== row2.input_digest)
|
|
26230
26462
|
throw new Error("Queue input binding is missing or corrupt");
|
|
26231
|
-
return { item, attachments: restored, provenance, digest:
|
|
26463
|
+
return { item, attachments: restored, provenance, digest: row2.input_digest };
|
|
26232
26464
|
}
|
|
26233
26465
|
function setPaused(db, agentId, paused, expectedRevision, reason = null) {
|
|
26234
26466
|
if (typeof paused !== "boolean" || !Number.isSafeInteger(expectedRevision) || expectedRevision < 0 || reason !== null && (typeof reason !== "string" || reason.length > 500))
|
|
@@ -26324,11 +26556,11 @@ function recoverInterrupted3(db) {
|
|
|
26324
26556
|
const agents = db.raw.query(
|
|
26325
26557
|
`SELECT DISTINCT agent_id FROM user_queue_items WHERE ${interrupted}`
|
|
26326
26558
|
).all();
|
|
26327
|
-
for (const
|
|
26328
|
-
ensureControl(db,
|
|
26559
|
+
for (const row2 of agents) {
|
|
26560
|
+
ensureControl(db, row2.agent_id);
|
|
26329
26561
|
db.raw.run(
|
|
26330
26562
|
"UPDATE user_queue_controls SET paused = 1, revision = revision + 1, reason = 'interrupted' WHERE agent_id = ?",
|
|
26331
|
-
[
|
|
26563
|
+
[row2.agent_id]
|
|
26332
26564
|
);
|
|
26333
26565
|
}
|
|
26334
26566
|
return Number(
|
|
@@ -26371,36 +26603,36 @@ function pruneTerminalInput(db, now = Date.now()) {
|
|
|
26371
26603
|
})();
|
|
26372
26604
|
}
|
|
26373
26605
|
function findAttempt(db, source, attemptId) {
|
|
26374
|
-
const
|
|
26606
|
+
const row2 = db.raw.query(
|
|
26375
26607
|
`SELECT ${fields2} FROM user_queue_items WHERE source = ? AND attempt_id = ?`
|
|
26376
26608
|
).get(source, attemptId);
|
|
26377
|
-
return
|
|
26609
|
+
return row2 ? hydrate(db, row2) : null;
|
|
26378
26610
|
}
|
|
26379
26611
|
function agentsWithOpenItems(db) {
|
|
26380
26612
|
return db.raw.query(
|
|
26381
26613
|
`SELECT DISTINCT agent_id FROM user_queue_items WHERE status IN (${openStates})`
|
|
26382
|
-
).all().map((
|
|
26614
|
+
).all().map((row2) => row2.agent_id);
|
|
26383
26615
|
}
|
|
26384
26616
|
function validateInput(message, attachments2) {
|
|
26385
26617
|
normalize2(message, attachments2);
|
|
26386
26618
|
}
|
|
26387
26619
|
function readProvenance(db, agentId, id) {
|
|
26388
|
-
const
|
|
26620
|
+
const row2 = db.raw.query(
|
|
26389
26621
|
"SELECT provenance_json FROM user_queue_items WHERE agent_id = ? AND id = ? AND length(provenance_json) <= 16384"
|
|
26390
26622
|
).get(agentId, id);
|
|
26391
|
-
if (!
|
|
26392
|
-
return JSON.parse(
|
|
26623
|
+
if (!row2?.provenance_json) throw new Error("Queue provenance unavailable");
|
|
26624
|
+
return JSON.parse(row2.provenance_json);
|
|
26393
26625
|
}
|
|
26394
26626
|
function approvalReference(db, agentId, id) {
|
|
26395
|
-
const
|
|
26627
|
+
const row2 = db.raw.query(
|
|
26396
26628
|
"SELECT input_digest FROM user_queue_items WHERE id = ? AND agent_id = ?"
|
|
26397
26629
|
).get(id, agentId);
|
|
26398
|
-
if (!
|
|
26399
|
-
return { agentId, itemId: id, inputDigest:
|
|
26630
|
+
if (!row2) throw new QueueConflictError("Queue approval input unavailable");
|
|
26631
|
+
return { agentId, itemId: id, inputDigest: row2.input_digest };
|
|
26400
26632
|
}
|
|
26401
26633
|
|
|
26402
26634
|
// ../daemon/src/core/repos/verification-requests.ts
|
|
26403
|
-
import { randomUUID as
|
|
26635
|
+
import { randomUUID as randomUUID23 } from "crypto";
|
|
26404
26636
|
var VERIFICATION_REQUEST_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
26405
26637
|
var VERIFICATION_MAX_CHECKS = 8;
|
|
26406
26638
|
var VERIFICATION_LIMITS = {
|
|
@@ -26422,61 +26654,61 @@ var REQUEST_COLUMNS = "id, team_id, requester_kind, requester_agent_id, recipien
|
|
|
26422
26654
|
var CHECK_COLUMNS = "request_id, ordinal, command, cwd, purpose, timeout_ms";
|
|
26423
26655
|
var OUTCOME_COLUMNS = "attempt_id, ordinal, state, command_id, exit_code, started_at, finished_at";
|
|
26424
26656
|
var ATTEMPT_COLUMNS2 = "id, request_id, attempt_number, supersedes_attempt_id, state, lease_owner, lease_expires_at, started_at, finished_at, error, observed_writes_json, created_at";
|
|
26425
|
-
function toRequest(
|
|
26657
|
+
function toRequest(row2) {
|
|
26426
26658
|
return {
|
|
26427
|
-
id:
|
|
26428
|
-
teamId:
|
|
26429
|
-
requesterKind:
|
|
26430
|
-
requesterAgentId:
|
|
26431
|
-
recipientAgentId:
|
|
26432
|
-
messageId:
|
|
26433
|
-
sourceSessionId:
|
|
26434
|
-
snapshotId:
|
|
26435
|
-
snapshotComplete:
|
|
26436
|
-
head:
|
|
26437
|
-
baseOid:
|
|
26438
|
-
environment: JSON.parse(
|
|
26439
|
-
summary:
|
|
26440
|
-
state:
|
|
26441
|
-
createdAt:
|
|
26442
|
-
expiresAt:
|
|
26443
|
-
};
|
|
26444
|
-
}
|
|
26445
|
-
function toCheck(
|
|
26659
|
+
id: row2.id,
|
|
26660
|
+
teamId: row2.team_id,
|
|
26661
|
+
requesterKind: row2.requester_kind === "agent" ? "agent" : "operator",
|
|
26662
|
+
requesterAgentId: row2.requester_agent_id,
|
|
26663
|
+
recipientAgentId: row2.recipient_agent_id,
|
|
26664
|
+
messageId: row2.message_id,
|
|
26665
|
+
sourceSessionId: row2.source_session_id,
|
|
26666
|
+
snapshotId: row2.snapshot_id,
|
|
26667
|
+
snapshotComplete: row2.snapshot_complete === 1,
|
|
26668
|
+
head: row2.head,
|
|
26669
|
+
baseOid: row2.base_oid,
|
|
26670
|
+
environment: JSON.parse(row2.environment_json),
|
|
26671
|
+
summary: row2.summary,
|
|
26672
|
+
state: row2.state,
|
|
26673
|
+
createdAt: row2.created_at,
|
|
26674
|
+
expiresAt: row2.expires_at
|
|
26675
|
+
};
|
|
26676
|
+
}
|
|
26677
|
+
function toCheck(row2) {
|
|
26446
26678
|
return {
|
|
26447
|
-
requestId:
|
|
26448
|
-
ordinal:
|
|
26449
|
-
command:
|
|
26450
|
-
cwd:
|
|
26451
|
-
purpose:
|
|
26452
|
-
timeoutMs:
|
|
26679
|
+
requestId: row2.request_id,
|
|
26680
|
+
ordinal: row2.ordinal,
|
|
26681
|
+
command: row2.command,
|
|
26682
|
+
cwd: row2.cwd,
|
|
26683
|
+
purpose: row2.purpose,
|
|
26684
|
+
timeoutMs: row2.timeout_ms
|
|
26453
26685
|
};
|
|
26454
26686
|
}
|
|
26455
|
-
function toOutcome(
|
|
26687
|
+
function toOutcome(row2) {
|
|
26456
26688
|
return {
|
|
26457
|
-
attemptId:
|
|
26458
|
-
ordinal:
|
|
26459
|
-
state:
|
|
26460
|
-
commandId:
|
|
26461
|
-
exitCode:
|
|
26462
|
-
startedAt:
|
|
26463
|
-
finishedAt:
|
|
26689
|
+
attemptId: row2.attempt_id,
|
|
26690
|
+
ordinal: row2.ordinal,
|
|
26691
|
+
state: row2.state,
|
|
26692
|
+
commandId: row2.command_id,
|
|
26693
|
+
exitCode: row2.exit_code,
|
|
26694
|
+
startedAt: row2.started_at,
|
|
26695
|
+
finishedAt: row2.finished_at
|
|
26464
26696
|
};
|
|
26465
26697
|
}
|
|
26466
|
-
function toAttempt2(
|
|
26698
|
+
function toAttempt2(row2) {
|
|
26467
26699
|
return {
|
|
26468
|
-
id:
|
|
26469
|
-
requestId:
|
|
26470
|
-
attemptNumber:
|
|
26471
|
-
supersedesAttemptId:
|
|
26472
|
-
state:
|
|
26473
|
-
leaseOwner:
|
|
26474
|
-
leaseExpiresAt:
|
|
26475
|
-
startedAt:
|
|
26476
|
-
finishedAt:
|
|
26477
|
-
error:
|
|
26478
|
-
observedWrites: parseObservedWrites(
|
|
26479
|
-
createdAt:
|
|
26700
|
+
id: row2.id,
|
|
26701
|
+
requestId: row2.request_id,
|
|
26702
|
+
attemptNumber: row2.attempt_number,
|
|
26703
|
+
supersedesAttemptId: row2.supersedes_attempt_id,
|
|
26704
|
+
state: row2.state,
|
|
26705
|
+
leaseOwner: row2.lease_owner,
|
|
26706
|
+
leaseExpiresAt: row2.lease_expires_at,
|
|
26707
|
+
startedAt: row2.started_at,
|
|
26708
|
+
finishedAt: row2.finished_at,
|
|
26709
|
+
error: row2.error,
|
|
26710
|
+
observedWrites: parseObservedWrites(row2.observed_writes_json),
|
|
26711
|
+
createdAt: row2.created_at
|
|
26480
26712
|
};
|
|
26481
26713
|
}
|
|
26482
26714
|
function parseObservedWrites(json) {
|
|
@@ -26492,7 +26724,7 @@ var VerificationRequestError = class extends Error {
|
|
|
26492
26724
|
};
|
|
26493
26725
|
function createVerificationRequest(db, input) {
|
|
26494
26726
|
const now = input.now ?? Date.now();
|
|
26495
|
-
const id = input.id ??
|
|
26727
|
+
const id = input.id ?? randomUUID23();
|
|
26496
26728
|
if (input.checks.length < 1)
|
|
26497
26729
|
throw new VerificationRequestError("a request needs at least one check");
|
|
26498
26730
|
if (input.checks.length > VERIFICATION_MAX_CHECKS) {
|
|
@@ -26553,17 +26785,17 @@ function createVerificationRequest(db, input) {
|
|
|
26553
26785
|
});
|
|
26554
26786
|
}
|
|
26555
26787
|
function getVerificationRequest(db, teamId, id, now = Date.now()) {
|
|
26556
|
-
const
|
|
26788
|
+
const row2 = db.raw.query(
|
|
26557
26789
|
`SELECT ${REQUEST_COLUMNS} FROM verification_requests
|
|
26558
26790
|
WHERE team_id = ? AND id = ? AND expires_at > ?`
|
|
26559
26791
|
).get(teamId, id, now);
|
|
26560
|
-
return
|
|
26792
|
+
return row2 ? toRequest(row2) : null;
|
|
26561
26793
|
}
|
|
26562
26794
|
function getVerificationRequestById(db, id, now = Date.now()) {
|
|
26563
|
-
const
|
|
26795
|
+
const row2 = db.raw.query(
|
|
26564
26796
|
`SELECT ${REQUEST_COLUMNS} FROM verification_requests WHERE id = ? AND expires_at > ?`
|
|
26565
26797
|
).get(id, now);
|
|
26566
|
-
return
|
|
26798
|
+
return row2 ? toRequest(row2) : null;
|
|
26567
26799
|
}
|
|
26568
26800
|
function listVerificationRequests(db, teamId, limit = 50, now = Date.now()) {
|
|
26569
26801
|
return db.raw.query(
|
|
@@ -26594,11 +26826,11 @@ function claimVerificationAttempt(db, input) {
|
|
|
26594
26826
|
if (!input.leaseOwner) throw new VerificationRequestError("a claim requires an owner");
|
|
26595
26827
|
if (input.leaseMs <= 0) throw new VerificationRequestError("a claim requires a positive lease");
|
|
26596
26828
|
return inTx(db, () => {
|
|
26597
|
-
const
|
|
26829
|
+
const row2 = db.raw.query(
|
|
26598
26830
|
`SELECT ${REQUEST_COLUMNS} FROM verification_requests WHERE id = ? AND expires_at > ?`
|
|
26599
26831
|
).get(input.requestId, now);
|
|
26600
|
-
if (!
|
|
26601
|
-
const request2 = toRequest(
|
|
26832
|
+
if (!row2) return null;
|
|
26833
|
+
const request2 = toRequest(row2);
|
|
26602
26834
|
const terminal = VERIFICATION_TERMINAL_REQUEST_STATES.includes(request2.state);
|
|
26603
26835
|
if (!terminal && request2.state !== "pending") return null;
|
|
26604
26836
|
if (terminal && !input.rerun) return null;
|
|
@@ -26610,7 +26842,7 @@ function claimVerificationAttempt(db, input) {
|
|
|
26610
26842
|
`SELECT id, attempt_number FROM verification_attempts WHERE request_id = ?
|
|
26611
26843
|
ORDER BY attempt_number DESC LIMIT 1`
|
|
26612
26844
|
).get(input.requestId);
|
|
26613
|
-
const attemptId =
|
|
26845
|
+
const attemptId = randomUUID23();
|
|
26614
26846
|
db.raw.run(
|
|
26615
26847
|
`INSERT INTO verification_attempts
|
|
26616
26848
|
(id, request_id, attempt_number, supersedes_attempt_id, state, lease_owner,
|
|
@@ -26643,11 +26875,11 @@ function finishVerificationAttempt(db, input) {
|
|
|
26643
26875
|
const now = input.now ?? Date.now();
|
|
26644
26876
|
if (input.error != null) assertLength2(input.error, VERIFICATION_LIMITS.error, "error");
|
|
26645
26877
|
return inTx(db, () => {
|
|
26646
|
-
const
|
|
26878
|
+
const row2 = db.raw.query(
|
|
26647
26879
|
`SELECT ${ATTEMPT_COLUMNS2} FROM verification_attempts WHERE id = ? AND lease_owner = ?`
|
|
26648
26880
|
).get(input.attemptId, input.leaseOwner);
|
|
26649
|
-
if (!
|
|
26650
|
-
const attempt = toAttempt2(
|
|
26881
|
+
if (!row2) return false;
|
|
26882
|
+
const attempt = toAttempt2(row2);
|
|
26651
26883
|
if (attempt.finishedAt !== null) return false;
|
|
26652
26884
|
db.raw.run(
|
|
26653
26885
|
`UPDATE verification_attempts
|
|
@@ -26713,22 +26945,22 @@ function recoverInterruptedVerificationAttempts(db, daemonIdentity, now = Date.n
|
|
|
26713
26945
|
`SELECT id, request_id, lease_owner FROM verification_attempts WHERE finished_at IS NULL`
|
|
26714
26946
|
).all();
|
|
26715
26947
|
const recovered = [];
|
|
26716
|
-
for (const
|
|
26717
|
-
if (
|
|
26948
|
+
for (const row2 of rows) {
|
|
26949
|
+
if (row2.lease_owner === daemonIdentity) continue;
|
|
26718
26950
|
db.raw.run(
|
|
26719
26951
|
`UPDATE verification_attempts
|
|
26720
26952
|
SET state = 'uncertain', finished_at = ?, lease_owner = NULL, lease_expires_at = NULL,
|
|
26721
26953
|
error = 'execution was interrupted before it reported an outcome'
|
|
26722
26954
|
WHERE id = ?`,
|
|
26723
|
-
[now,
|
|
26955
|
+
[now, row2.id]
|
|
26724
26956
|
);
|
|
26725
26957
|
db.raw.run(
|
|
26726
26958
|
`UPDATE verification_check_outcomes SET state = 'unknown', finished_at = ?
|
|
26727
26959
|
WHERE attempt_id = ? AND state = 'not_executed'`,
|
|
26728
|
-
[now,
|
|
26960
|
+
[now, row2.id]
|
|
26729
26961
|
);
|
|
26730
|
-
setRequestState(db,
|
|
26731
|
-
recovered.push(
|
|
26962
|
+
setRequestState(db, row2.request_id, "uncertain");
|
|
26963
|
+
recovered.push(row2.request_id);
|
|
26732
26964
|
}
|
|
26733
26965
|
return recovered;
|
|
26734
26966
|
});
|
|
@@ -26749,13 +26981,13 @@ function validateCheck(check) {
|
|
|
26749
26981
|
throw new VerificationRequestError("timeout is outside its bounded contract");
|
|
26750
26982
|
}
|
|
26751
26983
|
}
|
|
26752
|
-
function validateEnvironment(
|
|
26753
|
-
if (!
|
|
26984
|
+
function validateEnvironment(environment2) {
|
|
26985
|
+
if (!environment2.image)
|
|
26754
26986
|
throw new VerificationRequestError("the admitted environment has no image");
|
|
26755
|
-
if (
|
|
26987
|
+
if (environment2.sandbox !== "off" && environment2.sandbox !== "docker") {
|
|
26756
26988
|
throw new VerificationRequestError("the admitted environment has an unknown shell backend");
|
|
26757
26989
|
}
|
|
26758
|
-
if (
|
|
26990
|
+
if (environment2.env && Object.keys(environment2.env).length > 32) {
|
|
26759
26991
|
throw new VerificationRequestError("the admitted environment carries too many variables");
|
|
26760
26992
|
}
|
|
26761
26993
|
}
|
|
@@ -26862,14 +27094,14 @@ function reconcilePrivateResults(db, options = {}) {
|
|
|
26862
27094
|
}
|
|
26863
27095
|
|
|
26864
27096
|
// ../daemon/src/lib/coding-environment/lifecycle.ts
|
|
26865
|
-
import { randomUUID as
|
|
27097
|
+
import { randomUUID as randomUUID27 } from "crypto";
|
|
26866
27098
|
|
|
26867
27099
|
// ../daemon/src/lib/coding-environment/resources.ts
|
|
26868
|
-
import { randomUUID as
|
|
27100
|
+
import { randomUUID as randomUUID25 } from "crypto";
|
|
26869
27101
|
|
|
26870
27102
|
// ../daemon/src/runtime/shell/docker.ts
|
|
26871
27103
|
import { spawn } from "child_process";
|
|
26872
|
-
import { randomUUID as
|
|
27104
|
+
import { randomUUID as randomUUID24 } from "crypto";
|
|
26873
27105
|
import { closeSync as closeSync2, constants as constants2, mkdtempSync as mkdtempSync2, openSync as openSync2, rmSync as rmSync9, writeFileSync as writeFileSync6 } from "fs";
|
|
26874
27106
|
import { access, lstat, realpath, stat } from "fs/promises";
|
|
26875
27107
|
import { tmpdir as tmpdir2 } from "os";
|
|
@@ -27359,7 +27591,7 @@ function createPreparedDockerBashOperations(runtime, lifecycle) {
|
|
|
27359
27591
|
}
|
|
27360
27592
|
await assertDockerExecutableIdentity(runtime.dockerPath, runtime.executableIdentity);
|
|
27361
27593
|
if (signal?.aborted) throw new Error("aborted");
|
|
27362
|
-
const containerName = lifecycle?.name("bash") ?? `bazilion-bash-${process.pid}-${
|
|
27594
|
+
const containerName = lifecycle?.name("bash") ?? `bazilion-bash-${process.pid}-${randomUUID24().replaceAll("-", "")}`;
|
|
27363
27595
|
const spec = buildDockerRunSpec({
|
|
27364
27596
|
image: runtime.image,
|
|
27365
27597
|
resolvedImage: runtime.imageId,
|
|
@@ -27408,7 +27640,7 @@ async function preflightProtectedDockerEngine(input) {
|
|
|
27408
27640
|
}
|
|
27409
27641
|
async function proveProtectedContainerCreation(engine, workspace, readOnlyMounts, lifecycle, signal) {
|
|
27410
27642
|
if (signal?.aborted) throw new Error("aborted");
|
|
27411
|
-
const containerName = lifecycle?.name("preflight") ?? `bazilion-preflight-${process.pid}-${
|
|
27643
|
+
const containerName = lifecycle?.name("preflight") ?? `bazilion-preflight-${process.pid}-${randomUUID24().replaceAll("-", "")}`;
|
|
27412
27644
|
const dockerClientEnv = { DOCKER_HOST: engine.endpoint };
|
|
27413
27645
|
const spec = buildDockerRunSpec({
|
|
27414
27646
|
image: engine.image,
|
|
@@ -27740,7 +27972,7 @@ function createDockerBashOperations(options) {
|
|
|
27740
27972
|
const dockerClientEnv = await resolveLocalDockerClientEnv(dockerPath, hostEnv);
|
|
27741
27973
|
const resolvedImage = await inspectSandboxImage(dockerPath, image, dockerClientEnv);
|
|
27742
27974
|
if (signal?.aborted) throw new Error("aborted");
|
|
27743
|
-
const containerName = options.lifecycle?.name("bash") ?? `bazilion-bash-${process.pid}-${
|
|
27975
|
+
const containerName = options.lifecycle?.name("bash") ?? `bazilion-bash-${process.pid}-${randomUUID24().replaceAll("-", "")}`;
|
|
27744
27976
|
const spec = buildDockerRunSpec({
|
|
27745
27977
|
image,
|
|
27746
27978
|
env,
|
|
@@ -28396,7 +28628,7 @@ var WorkspaceResources = class {
|
|
|
28396
28628
|
}
|
|
28397
28629
|
register(lease, resource) {
|
|
28398
28630
|
return inTx(this.db, () => {
|
|
28399
|
-
const id =
|
|
28631
|
+
const id = randomUUID25();
|
|
28400
28632
|
lease.attach({ id, kind: resource.kind });
|
|
28401
28633
|
this.db.raw.run(
|
|
28402
28634
|
"INSERT INTO workspace_resources (id, writer_id, kind, identity_json) VALUES (?, ?, ?, ?)",
|
|
@@ -28406,13 +28638,13 @@ var WorkspaceResources = class {
|
|
|
28406
28638
|
});
|
|
28407
28639
|
}
|
|
28408
28640
|
async cleanupResource(id, observedNormalExit = false) {
|
|
28409
|
-
const
|
|
28641
|
+
const row2 = this.db.raw.query(`SELECT r.*, w.recovery_mode FROM workspace_resources r
|
|
28410
28642
|
JOIN workspace_writers w ON w.id = r.writer_id WHERE r.id = ?`).get(id);
|
|
28411
|
-
if (!
|
|
28412
|
-
if (
|
|
28413
|
-
if (
|
|
28414
|
-
const identity2 = JSON.parse(
|
|
28415
|
-
const confirmed =
|
|
28643
|
+
if (!row2) return false;
|
|
28644
|
+
if (row2.recovery_mode === "restored") return false;
|
|
28645
|
+
if (row2.cleanup_confirmed) return true;
|
|
28646
|
+
const identity2 = JSON.parse(row2.identity_json);
|
|
28647
|
+
const confirmed = row2.kind === "worker" ? await terminateWorkerProcess(identity2, observedNormalExit) : await terminateRecordedContainer(identity2, row2.creation_acknowledged === 1);
|
|
28416
28648
|
if (confirmed)
|
|
28417
28649
|
this.db.raw.run("UPDATE workspace_resources SET cleanup_confirmed = 1 WHERE id = ?", [id]);
|
|
28418
28650
|
return confirmed;
|
|
@@ -28423,18 +28655,18 @@ var WorkspaceResources = class {
|
|
|
28423
28655
|
"SELECT * FROM workspace_resources WHERE writer_id = ? ORDER BY CASE kind WHEN 'worker' THEN 0 ELSE 1 END"
|
|
28424
28656
|
).all(writer.id);
|
|
28425
28657
|
if (writer.resources.some(
|
|
28426
|
-
(resource) => !rows.some((
|
|
28658
|
+
(resource) => !rows.some((row2) => row2.id === resource.id && row2.kind === resource.kind)
|
|
28427
28659
|
))
|
|
28428
28660
|
return false;
|
|
28429
|
-
for (const
|
|
28430
|
-
if (!await this.cleanupResource(
|
|
28661
|
+
for (const row2 of rows) {
|
|
28662
|
+
if (!await this.cleanupResource(row2.id)) return false;
|
|
28431
28663
|
}
|
|
28432
28664
|
return true;
|
|
28433
28665
|
}
|
|
28434
28666
|
};
|
|
28435
28667
|
|
|
28436
28668
|
// ../daemon/src/lib/coding-environment/workspace.ts
|
|
28437
|
-
import { randomUUID as
|
|
28669
|
+
import { randomUUID as randomUUID26 } from "crypto";
|
|
28438
28670
|
import { realpathSync as realpathSync3 } from "fs";
|
|
28439
28671
|
import { isAbsolute as isAbsolute3, relative as relative2 } from "path";
|
|
28440
28672
|
var WorkspaceBusyError = class extends Error {
|
|
@@ -28462,15 +28694,15 @@ function workspaceIdentity(registeredRoot) {
|
|
|
28462
28694
|
directory.close();
|
|
28463
28695
|
}
|
|
28464
28696
|
}
|
|
28465
|
-
function view(
|
|
28697
|
+
function view(row2) {
|
|
28466
28698
|
return {
|
|
28467
|
-
id:
|
|
28468
|
-
teamId:
|
|
28469
|
-
root:
|
|
28470
|
-
rootIdentity:
|
|
28471
|
-
kind:
|
|
28472
|
-
resources: JSON.parse(
|
|
28473
|
-
...
|
|
28699
|
+
id: row2.id,
|
|
28700
|
+
teamId: row2.team_id,
|
|
28701
|
+
root: row2.root_path,
|
|
28702
|
+
rootIdentity: row2.root_identity,
|
|
28703
|
+
kind: row2.kind,
|
|
28704
|
+
resources: JSON.parse(row2.resources_json),
|
|
28705
|
+
...row2.recovery_mode === "restored" ? { restored: true } : {}
|
|
28474
28706
|
};
|
|
28475
28707
|
}
|
|
28476
28708
|
var WorkspaceCoordinator = class {
|
|
@@ -28478,7 +28710,7 @@ var WorkspaceCoordinator = class {
|
|
|
28478
28710
|
this.db = db;
|
|
28479
28711
|
}
|
|
28480
28712
|
db;
|
|
28481
|
-
identity =
|
|
28713
|
+
identity = randomUUID26();
|
|
28482
28714
|
leases = /* @__PURE__ */ new Set();
|
|
28483
28715
|
issued = /* @__PURE__ */ new WeakSet();
|
|
28484
28716
|
claim(teamId, registeredRoot, kind) {
|
|
@@ -28486,13 +28718,13 @@ var WorkspaceCoordinator = class {
|
|
|
28486
28718
|
return inTx(this.db, () => {
|
|
28487
28719
|
const exclusive = true;
|
|
28488
28720
|
const rows = this.db.raw.query("SELECT * FROM workspace_writers").all();
|
|
28489
|
-
for (const
|
|
28490
|
-
if (!(
|
|
28721
|
+
for (const row2 of rows) {
|
|
28722
|
+
if (!(row2.recovery_mode === "restored" && row2.team_id === teamId) && !overlappingWorkspaceRoots(row2.root_path, root.root) && row2.root_identity !== root.rootIdentity)
|
|
28491
28723
|
continue;
|
|
28492
|
-
const recovery =
|
|
28493
|
-
if (recovery || exclusive ||
|
|
28724
|
+
const recovery = row2.daemon_identity !== this.identity || row2.state === "recovery";
|
|
28725
|
+
if (recovery || exclusive || row2.exclusive === 1) throw new WorkspaceBusyError(recovery);
|
|
28494
28726
|
}
|
|
28495
|
-
const id =
|
|
28727
|
+
const id = randomUUID26();
|
|
28496
28728
|
this.db.raw.run(
|
|
28497
28729
|
`INSERT INTO workspace_writers
|
|
28498
28730
|
(id, team_id, root_path, root_identity, daemon_identity, kind, exclusive, state, created_at)
|
|
@@ -28527,21 +28759,21 @@ var WorkspaceCoordinator = class {
|
|
|
28527
28759
|
}
|
|
28528
28760
|
/** The recovery host must terminate/reap each recorded resource before acknowledging it. */
|
|
28529
28761
|
async recover(writerId, teardown) {
|
|
28530
|
-
const
|
|
28531
|
-
if (!
|
|
28532
|
-
if (
|
|
28533
|
-
if (this.leases.has(writerId) ||
|
|
28762
|
+
const row2 = this.db.raw.query("SELECT * FROM workspace_writers WHERE id = ?").get(writerId);
|
|
28763
|
+
if (!row2) return true;
|
|
28764
|
+
if (row2.recovery_mode === "restored") return false;
|
|
28765
|
+
if (this.leases.has(writerId) || row2.daemon_identity === this.identity && row2.state === "active")
|
|
28534
28766
|
throw new WorkspaceBusyError();
|
|
28535
28767
|
this.db.raw.run("UPDATE workspace_writers SET state = 'recovery' WHERE id = ?", [writerId]);
|
|
28536
|
-
if (!await teardown(view(
|
|
28768
|
+
if (!await teardown(view(row2))) return false;
|
|
28537
28769
|
this.db.raw.run("DELETE FROM workspace_writers WHERE id = ? AND state = 'recovery'", [writerId]);
|
|
28538
28770
|
return true;
|
|
28539
28771
|
}
|
|
28540
28772
|
attach(id, resource) {
|
|
28541
28773
|
if (!this.leases.has(id)) throw new Error("Workspace lease is no longer active");
|
|
28542
|
-
const
|
|
28543
|
-
if (
|
|
28544
|
-
const resources2 = JSON.parse(
|
|
28774
|
+
const row2 = this.db.raw.query("SELECT * FROM workspace_writers WHERE id = ?").get(id);
|
|
28775
|
+
if (row2?.state !== "active") throw new Error("Workspace lease requires recovery");
|
|
28776
|
+
const resources2 = JSON.parse(row2.resources_json);
|
|
28545
28777
|
if (resources2.some((item) => item.kind === resource.kind && item.id === resource.id)) return;
|
|
28546
28778
|
resources2.push(resource);
|
|
28547
28779
|
this.db.raw.run("UPDATE workspace_writers SET resources_json = ? WHERE id = ?", [
|
|
@@ -28611,7 +28843,7 @@ var WorkspaceLifecycle = class {
|
|
|
28611
28843
|
const prefix = `bazilion-${lease.writer.id}-`;
|
|
28612
28844
|
const records2 = /* @__PURE__ */ new Map();
|
|
28613
28845
|
return {
|
|
28614
|
-
name: (kind) => `${prefix}${kind}-${
|
|
28846
|
+
name: (kind) => `${prefix}${kind}-${randomUUID27()}`,
|
|
28615
28847
|
beforeCreate: async (identity2) => {
|
|
28616
28848
|
if (!identity2.containerName.startsWith(prefix) || !/^bazilion-[a-z0-9-]{1,160}$/.test(identity2.containerName) || records2.has(identity2.containerName))
|
|
28617
28849
|
throw new Error("Invalid turn container identity");
|
|
@@ -28646,7 +28878,7 @@ var WorkspaceLifecycle = class {
|
|
|
28646
28878
|
};
|
|
28647
28879
|
|
|
28648
28880
|
// ../daemon/src/lib/conversation-target.ts
|
|
28649
|
-
import { randomUUID as
|
|
28881
|
+
import { randomUUID as randomUUID29 } from "crypto";
|
|
28650
28882
|
|
|
28651
28883
|
// ../daemon/src/core/repos/conversations.ts
|
|
28652
28884
|
var columns = "id, agent_id AS agentId, title, title_revision AS titleRevision, created_at AS createdAt, updated_at AS updatedAt";
|
|
@@ -28681,11 +28913,11 @@ function get20(db, agentId, id) {
|
|
|
28681
28913
|
).get(agentId, id);
|
|
28682
28914
|
}
|
|
28683
28915
|
function filename(db, agentId, id) {
|
|
28684
|
-
const
|
|
28916
|
+
const row2 = db.raw.query(
|
|
28685
28917
|
"SELECT filename FROM agent_conversations WHERE agent_id = ? AND id = ?"
|
|
28686
28918
|
).get(agentId, id);
|
|
28687
|
-
if (!
|
|
28688
|
-
return
|
|
28919
|
+
if (!row2) throw new Error("Conversation not found");
|
|
28920
|
+
return row2.filename;
|
|
28689
28921
|
}
|
|
28690
28922
|
function list14(db, agentId, limit = 20, offset = 0) {
|
|
28691
28923
|
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100 || !Number.isSafeInteger(offset) || offset < 0)
|
|
@@ -28768,7 +29000,7 @@ function rename(db, agentId, id, value, expectedRevision) {
|
|
|
28768
29000
|
}
|
|
28769
29001
|
|
|
28770
29002
|
// ../daemon/src/lib/conversation-file.ts
|
|
28771
|
-
import { randomUUID as
|
|
29003
|
+
import { randomUUID as randomUUID28 } from "crypto";
|
|
28772
29004
|
import {
|
|
28773
29005
|
closeSync as closeSync4,
|
|
28774
29006
|
constants as constants4,
|
|
@@ -28818,7 +29050,7 @@ function readCanonicalSessionFile(directory, filename2, sessionId, minimumEntryO
|
|
|
28818
29050
|
const header = entries[0]?.entry;
|
|
28819
29051
|
if (header?.type !== "session" || header.id !== sessionId)
|
|
28820
29052
|
throw new Error("Result source session does not match the active Agent session");
|
|
28821
|
-
return entries.filter((
|
|
29053
|
+
return entries.filter((row2, index) => index === 0 || row2.offset >= minimumEntryOffset).map((row2) => row2.entry);
|
|
28822
29054
|
} finally {
|
|
28823
29055
|
closeSync3(fd);
|
|
28824
29056
|
}
|
|
@@ -28833,7 +29065,7 @@ function createConversationFile(paths2, agentId, conversationId, cwd) {
|
|
|
28833
29065
|
if (realpathSync5(directory) !== directory) throw new Error("Conversation escaped its Agent");
|
|
28834
29066
|
const filename2 = `${conversationId}.jsonl`;
|
|
28835
29067
|
const destination = join16(directory, filename2);
|
|
28836
|
-
const staging = join16(directory, `.conversation-${
|
|
29068
|
+
const staging = join16(directory, `.conversation-${randomUUID28()}.tmp`);
|
|
28837
29069
|
const header = SessionManager.inMemory(cwd, { id: conversationId }).getHeader();
|
|
28838
29070
|
const fd = openSync4(staging, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL, 384);
|
|
28839
29071
|
try {
|
|
@@ -28871,7 +29103,7 @@ function resolveConversationTarget(db, paths2, agentId, pinnedId) {
|
|
|
28871
29103
|
db,
|
|
28872
29104
|
agentId,
|
|
28873
29105
|
{
|
|
28874
|
-
requestId:
|
|
29106
|
+
requestId: randomUUID29(),
|
|
28875
29107
|
expectedSelection: { conversationId: null, revision: 0 }
|
|
28876
29108
|
},
|
|
28877
29109
|
(newId) => createConversationFile(paths2, agentId, newId, agent.team.path)
|
|
@@ -28938,22 +29170,22 @@ async function runAgentLifecycleMutation(agentId, mutation) {
|
|
|
28938
29170
|
}
|
|
28939
29171
|
|
|
28940
29172
|
// ../daemon/src/lib/agent-loop-guard.ts
|
|
28941
|
-
import { randomUUID as
|
|
29173
|
+
import { randomUUID as randomUUID30 } from "crypto";
|
|
28942
29174
|
var DEFAULT_MAX_HOPS = 8;
|
|
28943
|
-
function toEvent(
|
|
29175
|
+
function toEvent(row2) {
|
|
28944
29176
|
return {
|
|
28945
|
-
id:
|
|
28946
|
-
causalChainId:
|
|
28947
|
-
parentMessageId:
|
|
28948
|
-
fromAgentId:
|
|
28949
|
-
toAgentId:
|
|
28950
|
-
sourceTeamId:
|
|
28951
|
-
targetTeamId:
|
|
28952
|
-
attemptedHop:
|
|
28953
|
-
maxHops:
|
|
28954
|
-
reason:
|
|
28955
|
-
origin:
|
|
28956
|
-
createdAt:
|
|
29177
|
+
id: row2.id,
|
|
29178
|
+
causalChainId: row2.causal_chain_id,
|
|
29179
|
+
parentMessageId: row2.parent_message_id,
|
|
29180
|
+
fromAgentId: row2.from_agent_id,
|
|
29181
|
+
toAgentId: row2.to_agent_id,
|
|
29182
|
+
sourceTeamId: row2.source_team_id,
|
|
29183
|
+
targetTeamId: row2.target_team_id,
|
|
29184
|
+
attemptedHop: row2.attempted_hop,
|
|
29185
|
+
maxHops: row2.max_hops,
|
|
29186
|
+
reason: row2.reason,
|
|
29187
|
+
origin: row2.origin,
|
|
29188
|
+
createdAt: row2.created_at
|
|
28957
29189
|
};
|
|
28958
29190
|
}
|
|
28959
29191
|
function agentLoopMaxHops(db, env = process.env) {
|
|
@@ -28990,8 +29222,8 @@ function enforceMessageCausality(db, input) {
|
|
|
28990
29222
|
const target = agents_exports.get(db, input.to);
|
|
28991
29223
|
if (!source || !target) return null;
|
|
28992
29224
|
const event2 = {
|
|
28993
|
-
id:
|
|
28994
|
-
causalChainId: input.causality.causalChainId ?? input.causality.parentMessageId ??
|
|
29225
|
+
id: randomUUID30(),
|
|
29226
|
+
causalChainId: input.causality.causalChainId ?? input.causality.parentMessageId ?? randomUUID30(),
|
|
28995
29227
|
parentMessageId: input.causality.parentMessageId,
|
|
28996
29228
|
fromAgentId: input.from,
|
|
28997
29229
|
toAgentId: input.to,
|
|
@@ -30384,8 +30616,8 @@ function assertRepositoryContext(value, teamId) {
|
|
|
30384
30616
|
throw new Error("Invalid repository context report");
|
|
30385
30617
|
const instructions = value.instructions;
|
|
30386
30618
|
const commands = value.commands;
|
|
30387
|
-
const
|
|
30388
|
-
if (!keys(instructions, ["state", "issues", "files"]) || !keys(commands, ["state", "issues", "sources", "candidates"]) || !keys(
|
|
30619
|
+
const git2 = value.git;
|
|
30620
|
+
if (!keys(instructions, ["state", "issues", "files"]) || !keys(commands, ["state", "issues", "sources", "candidates"]) || !keys(git2, [
|
|
30389
30621
|
"state",
|
|
30390
30622
|
"root",
|
|
30391
30623
|
"branch",
|
|
@@ -30416,7 +30648,7 @@ function assertRepositoryContext(value, teamId) {
|
|
|
30416
30648
|
"kind",
|
|
30417
30649
|
"packageManager"
|
|
30418
30650
|
]) && 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)
|
|
30419
|
-
) || !["available", "unavailable", "not_repository"].includes(String(
|
|
30651
|
+
) || !["available", "unavailable", "not_repository"].includes(String(git2.state)) || ![null, "branch", "detached", "unborn"].includes(git2.headState) || ![git2.root, git2.branch, git2.head].every((value2) => value2 === null || string(value2)) || ![git2.staged, git2.unstaged, git2.untracked, git2.conflicted].every(count2) || !list15(git2.issues, 128, issue))
|
|
30420
30652
|
throw new Error("Invalid repository context report");
|
|
30421
30653
|
const report2 = value;
|
|
30422
30654
|
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))
|
|
@@ -36214,7 +36446,7 @@ function createBrowserHost(config2) {
|
|
|
36214
36446
|
}
|
|
36215
36447
|
|
|
36216
36448
|
// ../daemon/src/lib/coding-environment/agent-host.ts
|
|
36217
|
-
import { createHash as createHash10, randomUUID as
|
|
36449
|
+
import { createHash as createHash10, randomUUID as randomUUID33 } from "crypto";
|
|
36218
36450
|
|
|
36219
36451
|
// ../daemon/src/core/repos/coding-command-logs.ts
|
|
36220
36452
|
var CODING_LOG_BYTES = 2 * 1024 * 1024;
|
|
@@ -36233,38 +36465,38 @@ function headBytes(value, limit) {
|
|
|
36233
36465
|
function mayDisclose(view2, audience) {
|
|
36234
36466
|
return audience === "producer" || view2.releasedAt !== null;
|
|
36235
36467
|
}
|
|
36236
|
-
var
|
|
36468
|
+
var COLUMNS2 = `command_id, team_id, agent_id, turn_id, tool_call_id, state, text,
|
|
36237
36469
|
byte_length, observed_bytes, redacted, truncated, created_at, expires_at, released_at, retired_at`;
|
|
36238
|
-
function expiryDue(
|
|
36239
|
-
return
|
|
36470
|
+
function expiryDue(row2, now) {
|
|
36471
|
+
return row2.state === "retained" && row2.expires_at <= now;
|
|
36240
36472
|
}
|
|
36241
|
-
function liveText(
|
|
36242
|
-
return
|
|
36473
|
+
function liveText(row2, now) {
|
|
36474
|
+
return row2.state === "retained" && !expiryDue(row2, now) ? row2.text : null;
|
|
36243
36475
|
}
|
|
36244
|
-
function availabilityOf(
|
|
36245
|
-
if (
|
|
36246
|
-
if (
|
|
36247
|
-
return
|
|
36476
|
+
function availabilityOf(row2, now) {
|
|
36477
|
+
if (row2.state === "deleted") return "deleted";
|
|
36478
|
+
if (row2.state === "expired" || expiryDue(row2, now)) return "expired";
|
|
36479
|
+
return row2.truncated === 1 ? "truncated" : "available";
|
|
36248
36480
|
}
|
|
36249
|
-
function toView(
|
|
36481
|
+
function toView(row2, now) {
|
|
36250
36482
|
return {
|
|
36251
|
-
commandId:
|
|
36252
|
-
teamId:
|
|
36253
|
-
agentId:
|
|
36254
|
-
turnId:
|
|
36255
|
-
toolCallId:
|
|
36256
|
-
availability: availabilityOf(
|
|
36257
|
-
byteLength:
|
|
36258
|
-
observedBytes:
|
|
36259
|
-
redacted:
|
|
36260
|
-
createdAt:
|
|
36261
|
-
expiresAt:
|
|
36262
|
-
releasedAt:
|
|
36263
|
-
retiredAt:
|
|
36483
|
+
commandId: row2.command_id,
|
|
36484
|
+
teamId: row2.team_id,
|
|
36485
|
+
agentId: row2.agent_id,
|
|
36486
|
+
turnId: row2.turn_id,
|
|
36487
|
+
toolCallId: row2.tool_call_id,
|
|
36488
|
+
availability: availabilityOf(row2, now),
|
|
36489
|
+
byteLength: row2.byte_length,
|
|
36490
|
+
observedBytes: row2.observed_bytes,
|
|
36491
|
+
redacted: row2.redacted === 1,
|
|
36492
|
+
createdAt: row2.created_at,
|
|
36493
|
+
expiresAt: row2.expires_at,
|
|
36494
|
+
releasedAt: row2.released_at,
|
|
36495
|
+
retiredAt: row2.retired_at
|
|
36264
36496
|
};
|
|
36265
36497
|
}
|
|
36266
36498
|
function rowFor(db, commandId) {
|
|
36267
|
-
return db.raw.query(`SELECT ${
|
|
36499
|
+
return db.raw.query(`SELECT ${COLUMNS2} FROM coding_command_logs WHERE command_id = ?`).get(commandId) ?? null;
|
|
36268
36500
|
}
|
|
36269
36501
|
function unavailableLog(commandId) {
|
|
36270
36502
|
return {
|
|
@@ -36284,8 +36516,8 @@ function unavailableLog(commandId) {
|
|
|
36284
36516
|
};
|
|
36285
36517
|
}
|
|
36286
36518
|
function getCodingCommandLog(db, commandId, now = Date.now()) {
|
|
36287
|
-
const
|
|
36288
|
-
return
|
|
36519
|
+
const row2 = rowFor(db, commandId);
|
|
36520
|
+
return row2 ? toView(row2, now) : unavailableLog(commandId);
|
|
36289
36521
|
}
|
|
36290
36522
|
function saveCodingCommandLog(db, input) {
|
|
36291
36523
|
const now = input.now ?? Date.now();
|
|
@@ -36294,7 +36526,7 @@ function saveCodingCommandLog(db, input) {
|
|
|
36294
36526
|
const observed = Math.max(input.observedBytes, byteLength);
|
|
36295
36527
|
const truncated = retained.truncated || input.truncated || !input.redacted && input.observedBytes > byteLength;
|
|
36296
36528
|
db.raw.run(
|
|
36297
|
-
`INSERT INTO coding_command_logs (${
|
|
36529
|
+
`INSERT INTO coding_command_logs (${COLUMNS2})
|
|
36298
36530
|
VALUES (?, ?, ?, ?, ?, 'retained', ?, ?, ?, ?, ?, ?, ?, NULL, NULL)
|
|
36299
36531
|
ON CONFLICT(command_id) DO UPDATE SET
|
|
36300
36532
|
state = 'retained',
|
|
@@ -36344,10 +36576,10 @@ function releaseCodingCommandLog(db, commandId, now = Date.now()) {
|
|
|
36344
36576
|
function readCodingCommandLog(db, commandId, options, now = Date.now()) {
|
|
36345
36577
|
const view2 = getCodingCommandLog(db, commandId, now);
|
|
36346
36578
|
if (!mayDisclose(view2, options.audience)) return null;
|
|
36347
|
-
const
|
|
36579
|
+
const row2 = rowFor(db, commandId);
|
|
36348
36580
|
const limit = Math.min(Math.max(options.limit ?? CODING_LOG_PAGE_BYTES, 1), CODING_LOG_BYTES);
|
|
36349
|
-
const text3 =
|
|
36350
|
-
if (!
|
|
36581
|
+
const text3 = row2 ? liveText(row2, now) : null;
|
|
36582
|
+
if (!row2 || text3 === null) {
|
|
36351
36583
|
return {
|
|
36352
36584
|
commandId,
|
|
36353
36585
|
availability: view2.availability,
|
|
@@ -36374,14 +36606,14 @@ function readCodingCommandLog(db, commandId, options, now = Date.now()) {
|
|
|
36374
36606
|
function searchCodingCommandLog(db, commandId, needle, options, now = Date.now()) {
|
|
36375
36607
|
const view2 = getCodingCommandLog(db, commandId, now);
|
|
36376
36608
|
if (!mayDisclose(view2, options.audience)) return null;
|
|
36377
|
-
const
|
|
36609
|
+
const row2 = rowFor(db, commandId);
|
|
36378
36610
|
const empty = {
|
|
36379
36611
|
commandId,
|
|
36380
36612
|
availability: view2.availability,
|
|
36381
36613
|
matches: [],
|
|
36382
36614
|
bounded: false
|
|
36383
36615
|
};
|
|
36384
|
-
const text3 =
|
|
36616
|
+
const text3 = row2 ? liveText(row2, now) : null;
|
|
36385
36617
|
if (text3 === null || !needle) return empty;
|
|
36386
36618
|
const scanned = Buffer.byteLength(text3) > CODING_LOG_SEARCH_SCAN_BYTES;
|
|
36387
36619
|
const haystack = scanned ? headBytes(text3, CODING_LOG_SEARCH_SCAN_BYTES) : text3;
|
|
@@ -36434,7 +36666,7 @@ function pruneCodingCommandLogs(db, now = Date.now(), budgetBytes = CODING_LOG_H
|
|
|
36434
36666
|
}
|
|
36435
36667
|
|
|
36436
36668
|
// ../daemon/src/lib/communication.ts
|
|
36437
|
-
import { randomUUID as
|
|
36669
|
+
import { randomUUID as randomUUID32 } from "crypto";
|
|
36438
36670
|
|
|
36439
36671
|
// ../daemon/src/lib/question-approval.ts
|
|
36440
36672
|
function questionApprovalReference(snapshot, kind) {
|
|
@@ -36529,7 +36761,7 @@ function questionVisible(db, item) {
|
|
|
36529
36761
|
}
|
|
36530
36762
|
|
|
36531
36763
|
// ../daemon/src/core/repos/results.ts
|
|
36532
|
-
import { createHash as createHash9, randomUUID as
|
|
36764
|
+
import { createHash as createHash9, randomUUID as randomUUID31 } from "crypto";
|
|
36533
36765
|
var MAX_RESULT_BYTES = 25 * 1024 * 1024;
|
|
36534
36766
|
var MAX_RETAINED_RESULT_BYTES = 1024 * 1024 * 1024;
|
|
36535
36767
|
var columns2 = `id, team_id AS teamId, agent_id AS agentId, source_kind AS sourceKind,
|
|
@@ -36592,7 +36824,7 @@ function publish(db, input) {
|
|
|
36592
36824
|
"Result storage is full (1 GiB). Delete saved results before delivering more files."
|
|
36593
36825
|
);
|
|
36594
36826
|
}
|
|
36595
|
-
const id =
|
|
36827
|
+
const id = randomUUID31();
|
|
36596
36828
|
db.raw.run(
|
|
36597
36829
|
`INSERT INTO agent_results
|
|
36598
36830
|
(id, team_id, agent_id, source_kind, session_id, tool_call_id, review_packet_id, review_revision,
|
|
@@ -36660,12 +36892,12 @@ function listReleased(db, opts = {}) {
|
|
|
36660
36892
|
return { results, total, limit, offset };
|
|
36661
36893
|
}
|
|
36662
36894
|
function readCaptured(db, id) {
|
|
36663
|
-
const
|
|
36895
|
+
const row2 = db.raw.query(
|
|
36664
36896
|
"SELECT bytes, byte_length, sha256 FROM agent_results WHERE id = ? AND deleted_at IS NULL"
|
|
36665
36897
|
).get(id);
|
|
36666
|
-
if (!
|
|
36667
|
-
const bytes = Buffer.from(
|
|
36668
|
-
if (bytes.byteLength !==
|
|
36898
|
+
if (!row2) throw new Error("Captured result is unavailable");
|
|
36899
|
+
const bytes = Buffer.from(row2.bytes);
|
|
36900
|
+
if (bytes.byteLength !== row2.byte_length || createHash9("sha256").update(bytes).digest("hex") !== row2.sha256) {
|
|
36669
36901
|
throw new Error("Captured result failed integrity verification");
|
|
36670
36902
|
}
|
|
36671
36903
|
return bytes;
|
|
@@ -36912,7 +37144,7 @@ function isUserFacingFrame(frame) {
|
|
|
36912
37144
|
}
|
|
36913
37145
|
function sendAgentMessage(db, input) {
|
|
36914
37146
|
const attemptKind = input.attemptKind ?? "agent_tool";
|
|
36915
|
-
const attemptId = input.attemptId ??
|
|
37147
|
+
const attemptId = input.attemptId ?? randomUUID32();
|
|
36916
37148
|
const outcome = db.raw.transaction(
|
|
36917
37149
|
() => {
|
|
36918
37150
|
const causality = resolveMessageCausality(db, input);
|
|
@@ -37241,29 +37473,29 @@ function claimDeliverableInbox(db, agentId, onAllowed, conversationId) {
|
|
|
37241
37473
|
|
|
37242
37474
|
// ../daemon/src/core/repos/source-snapshots.ts
|
|
37243
37475
|
var SOURCE_SNAPSHOT_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
37244
|
-
var
|
|
37245
|
-
function
|
|
37476
|
+
var COLUMNS3 = "snapshot_id, team_id, captured_by, agent_id, turn_id, tool_call_id, complete, head, base_oid, entry_count, captured_content_bytes, manifest_json, created_at, expires_at";
|
|
37477
|
+
function toRecord2(row2) {
|
|
37246
37478
|
return {
|
|
37247
|
-
snapshotId:
|
|
37248
|
-
teamId:
|
|
37249
|
-
capturedBy:
|
|
37250
|
-
agentId:
|
|
37251
|
-
turnId:
|
|
37252
|
-
toolCallId:
|
|
37253
|
-
complete:
|
|
37254
|
-
head:
|
|
37255
|
-
baseOid:
|
|
37256
|
-
entryCount:
|
|
37257
|
-
capturedContentBytes:
|
|
37258
|
-
manifestJson:
|
|
37259
|
-
createdAt:
|
|
37260
|
-
expiresAt:
|
|
37479
|
+
snapshotId: row2.snapshot_id,
|
|
37480
|
+
teamId: row2.team_id,
|
|
37481
|
+
capturedBy: row2.captured_by === "agent" ? "agent" : "operator",
|
|
37482
|
+
agentId: row2.agent_id,
|
|
37483
|
+
turnId: row2.turn_id,
|
|
37484
|
+
toolCallId: row2.tool_call_id,
|
|
37485
|
+
complete: row2.complete === 1,
|
|
37486
|
+
head: row2.head,
|
|
37487
|
+
baseOid: row2.base_oid,
|
|
37488
|
+
entryCount: row2.entry_count,
|
|
37489
|
+
capturedContentBytes: row2.captured_content_bytes,
|
|
37490
|
+
manifestJson: row2.manifest_json,
|
|
37491
|
+
createdAt: row2.created_at,
|
|
37492
|
+
expiresAt: row2.expires_at
|
|
37261
37493
|
};
|
|
37262
37494
|
}
|
|
37263
37495
|
function saveSourceSnapshot(db, input) {
|
|
37264
37496
|
const now = input.now ?? Date.now();
|
|
37265
37497
|
db.raw.run(
|
|
37266
|
-
`INSERT INTO source_snapshots (${
|
|
37498
|
+
`INSERT INTO source_snapshots (${COLUMNS3})
|
|
37267
37499
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
37268
37500
|
ON CONFLICT(snapshot_id, team_id) DO NOTHING`,
|
|
37269
37501
|
[
|
|
@@ -37286,11 +37518,11 @@ function saveSourceSnapshot(db, input) {
|
|
|
37286
37518
|
pruneSourceSnapshots(db, now);
|
|
37287
37519
|
}
|
|
37288
37520
|
function getSourceSnapshot(db, teamId, snapshotId, now = Date.now()) {
|
|
37289
|
-
const
|
|
37290
|
-
`SELECT ${
|
|
37521
|
+
const row2 = db.raw.query(
|
|
37522
|
+
`SELECT ${COLUMNS3} FROM source_snapshots
|
|
37291
37523
|
WHERE team_id = ? AND snapshot_id = ? AND expires_at > ?`
|
|
37292
37524
|
).get(teamId, snapshotId, now);
|
|
37293
|
-
return
|
|
37525
|
+
return row2 ? toRecord2(row2) : null;
|
|
37294
37526
|
}
|
|
37295
37527
|
function pruneSourceSnapshots(db, now = Date.now()) {
|
|
37296
37528
|
const result = db.raw.run("DELETE FROM source_snapshots WHERE expires_at <= ?", [now]);
|
|
@@ -37298,10 +37530,10 @@ function pruneSourceSnapshots(db, now = Date.now()) {
|
|
|
37298
37530
|
}
|
|
37299
37531
|
function listSourceSnapshots(db, teamId, limit = 50, now = Date.now()) {
|
|
37300
37532
|
return db.raw.query(
|
|
37301
|
-
`SELECT ${
|
|
37533
|
+
`SELECT ${COLUMNS3} FROM source_snapshots
|
|
37302
37534
|
WHERE team_id = ? AND expires_at > ?
|
|
37303
37535
|
ORDER BY created_at DESC, snapshot_id LIMIT ?`
|
|
37304
|
-
).all(teamId, now, limit).map(
|
|
37536
|
+
).all(teamId, now, limit).map(toRecord2);
|
|
37305
37537
|
}
|
|
37306
37538
|
|
|
37307
37539
|
// ../daemon/src/lib/git/capture.ts
|
|
@@ -37327,13 +37559,13 @@ async function captureRepositoryGit(root, budgetMs = INSPECTION_BUDGET_MS) {
|
|
|
37327
37559
|
const marker = root.entry(".git");
|
|
37328
37560
|
if (!marker?.isDirectory() || marker.isSymbolicLink())
|
|
37329
37561
|
throw new ContextReadError("unsupported_git_metadata");
|
|
37330
|
-
const
|
|
37331
|
-
if (
|
|
37562
|
+
const git2 = root.directory(".git");
|
|
37563
|
+
if (git2.entry("commondir") || git2.entry("gitdir")) {
|
|
37332
37564
|
throw new ContextReadError("unsupported_git_metadata");
|
|
37333
37565
|
}
|
|
37334
|
-
const info =
|
|
37566
|
+
const info = git2.entry("info");
|
|
37335
37567
|
if (info) {
|
|
37336
|
-
const dir =
|
|
37568
|
+
const dir = git2.directory("info");
|
|
37337
37569
|
if (dir.entry("sparse-checkout")) throw new ContextReadError("unsupported_git_metadata");
|
|
37338
37570
|
}
|
|
37339
37571
|
const scratch = mkdtempSync4(join25(tmpdir4(), "bazilion-context-git-"));
|
|
@@ -37387,7 +37619,7 @@ async function captureRepositoryGit(root, budgetMs = INSPECTION_BUDGET_MS) {
|
|
|
37387
37619
|
...args
|
|
37388
37620
|
];
|
|
37389
37621
|
const runGit = (args) => rawGit(inspectionArgs(args));
|
|
37390
|
-
const capturedConfig =
|
|
37622
|
+
const capturedConfig = git2.read("config", METADATA_READ);
|
|
37391
37623
|
const configLines = ["[core]", "repositoryformatversion = 0", "bare = false", "filemode = true"];
|
|
37392
37624
|
if (capturedConfig) {
|
|
37393
37625
|
bytes += capturedConfig.length;
|
|
@@ -37442,7 +37674,7 @@ objectformat = ${value}`
|
|
|
37442
37674
|
}
|
|
37443
37675
|
}
|
|
37444
37676
|
if (info) {
|
|
37445
|
-
const exclude =
|
|
37677
|
+
const exclude = git2.directory("info").read("exclude", METADATA_READ);
|
|
37446
37678
|
if (exclude) {
|
|
37447
37679
|
bytes += exclude.length;
|
|
37448
37680
|
mkdirSync9(join25(scratch, "info"), { mode: 448 });
|
|
@@ -37470,7 +37702,7 @@ objectformat = ${value}`
|
|
|
37470
37702
|
}
|
|
37471
37703
|
};
|
|
37472
37704
|
for (const name of ["HEAD", "index", "packed-refs", "shallow"]) {
|
|
37473
|
-
const content =
|
|
37705
|
+
const content = git2.read(name, Math.min(METADATA_READ_LARGE, METADATA_BYTES - bytes));
|
|
37474
37706
|
if (content) {
|
|
37475
37707
|
count3++;
|
|
37476
37708
|
bytes += content.length;
|
|
@@ -37479,13 +37711,13 @@ objectformat = ${value}`
|
|
|
37479
37711
|
}
|
|
37480
37712
|
for (const name of ["refs", "objects"]) {
|
|
37481
37713
|
mkdirSync9(join25(scratch, name), { mode: 448 });
|
|
37482
|
-
if (
|
|
37714
|
+
if (git2.entry(name)) copy(git2.directory(name), join25(scratch, name), 0);
|
|
37483
37715
|
}
|
|
37484
|
-
if (
|
|
37716
|
+
if (git2.list().some((name) => name.startsWith("sharedindex.")))
|
|
37485
37717
|
throw new ContextReadError("unsupported_git_metadata");
|
|
37486
37718
|
writeFileSync12(join25(scratch, "config"), `${configLines.join("\n")}
|
|
37487
37719
|
`, { mode: 384 });
|
|
37488
|
-
const validate2 = () =>
|
|
37720
|
+
const validate2 = () => git2.validate();
|
|
37489
37721
|
validate2();
|
|
37490
37722
|
return { root, runGit, validate: validate2, cleanup };
|
|
37491
37723
|
} catch (error2) {
|
|
@@ -37512,6 +37744,23 @@ var REVIEW_LIMITS2 = {
|
|
|
37512
37744
|
patchBytes: 256 * 1024
|
|
37513
37745
|
};
|
|
37514
37746
|
|
|
37747
|
+
// ../../packages/api-types/src/publication.ts
|
|
37748
|
+
var PUBLICATION_LIMITS = {
|
|
37749
|
+
repository: 200,
|
|
37750
|
+
branch: 200,
|
|
37751
|
+
commitMessage: 2e3,
|
|
37752
|
+
refusalDetail: 400,
|
|
37753
|
+
error: 400,
|
|
37754
|
+
/** Branches that are never published to, whatever the host says. */
|
|
37755
|
+
protectedBranches: ["main", "master", "trunk", "develop", "release"]
|
|
37756
|
+
};
|
|
37757
|
+
|
|
37758
|
+
// ../../packages/api-types/src/verification.ts
|
|
37759
|
+
var VERIFICATION_OUTCOME_LIMITS = [
|
|
37760
|
+
"Facts above are executor-owned. A non-zero exit is a result about the commands that ran, never proof about later code, and this is not an approval to publish, merge or deploy.",
|
|
37761
|
+
"Declared output paths are not enforced, so a change they do not cover appears above rather than being prevented."
|
|
37762
|
+
];
|
|
37763
|
+
|
|
37515
37764
|
// ../../packages/api-types/src/index.ts
|
|
37516
37765
|
var PROFILE_FILES = [
|
|
37517
37766
|
"profile.json",
|
|
@@ -38696,15 +38945,15 @@ function createCodingHost(input) {
|
|
|
38696
38945
|
throw new Error("Command contains protected credential material");
|
|
38697
38946
|
starting = true;
|
|
38698
38947
|
try {
|
|
38699
|
-
const
|
|
38948
|
+
const environment2 = await snapshot(command.cwd);
|
|
38700
38949
|
const receipt = {
|
|
38701
|
-
id:
|
|
38950
|
+
id: randomUUID33(),
|
|
38702
38951
|
agentId: input.agentId,
|
|
38703
38952
|
teamId: input.teamId,
|
|
38704
38953
|
turnId: input.turnId,
|
|
38705
38954
|
toolCallId: raw2.toolCallId,
|
|
38706
38955
|
input: command,
|
|
38707
|
-
environment,
|
|
38956
|
+
environment: environment2,
|
|
38708
38957
|
startedAt: Date.now(),
|
|
38709
38958
|
finishedAt: null,
|
|
38710
38959
|
state: "running",
|
|
@@ -39033,7 +39282,7 @@ function createDbMessagingHost(db, opts = {}) {
|
|
|
39033
39282
|
}
|
|
39034
39283
|
|
|
39035
39284
|
// ../daemon/src/lib/question-service.ts
|
|
39036
|
-
import { randomUUID as
|
|
39285
|
+
import { randomUUID as randomUUID35 } from "crypto";
|
|
39037
39286
|
|
|
39038
39287
|
// ../daemon/src/lib/question-consumption.ts
|
|
39039
39288
|
import { isDeepStrictEqual } from "util";
|
|
@@ -39089,8 +39338,8 @@ function key(db, create7) {
|
|
|
39089
39338
|
db.raw.run("INSERT OR IGNORE INTO question_receipt_key (singleton, key) VALUES (1, ?)", [
|
|
39090
39339
|
randomBytes5(32)
|
|
39091
39340
|
]);
|
|
39092
|
-
const
|
|
39093
|
-
return
|
|
39341
|
+
const row2 = db.raw.query("SELECT key FROM question_receipt_key WHERE singleton = 1").get();
|
|
39342
|
+
return row2 ? Buffer.from(row2.key) : null;
|
|
39094
39343
|
}
|
|
39095
39344
|
function signQuestionReceipt(db, agentId, result) {
|
|
39096
39345
|
const item = get18(db, agentId, result.questionId);
|
|
@@ -39561,7 +39810,7 @@ function parseTelegramQuestionReply(db, authToken, update3) {
|
|
|
39561
39810
|
}
|
|
39562
39811
|
|
|
39563
39812
|
// ../daemon/src/lib/attachments.ts
|
|
39564
|
-
import { randomUUID as
|
|
39813
|
+
import { randomUUID as randomUUID34 } from "crypto";
|
|
39565
39814
|
import { closeSync as closeSync9, constants as constants10, fstatSync as fstatSync7, openSync as openSync9, writeFileSync as writeFileSync13 } from "fs";
|
|
39566
39815
|
import { join as join26, posix } from "path";
|
|
39567
39816
|
var MAX_FILE_BYTES = 25 * 1024 * 1024;
|
|
@@ -39588,7 +39837,7 @@ function saveInputFiles(agentDir, files, options = {}) {
|
|
|
39588
39837
|
lines.push(`[attachment "${label}" skipped: too large (${fmtBytes(buf.byteLength)} > 25 MB)]`);
|
|
39589
39838
|
continue;
|
|
39590
39839
|
}
|
|
39591
|
-
const filename2 = `${
|
|
39840
|
+
const filename2 = `${randomUUID34().slice(0, 8)}-${safeName(label)}`;
|
|
39592
39841
|
const path = join26(dir, filename2);
|
|
39593
39842
|
let fd;
|
|
39594
39843
|
try {
|
|
@@ -39618,13 +39867,13 @@ var CodingEnvironmentRevisionError = class extends Error {
|
|
|
39618
39867
|
}
|
|
39619
39868
|
};
|
|
39620
39869
|
function getCodingEnvironment(db, teamId) {
|
|
39621
|
-
const
|
|
39622
|
-
if (!
|
|
39870
|
+
const row2 = db.raw.query("SELECT * FROM team_coding_environments WHERE team_id = ?").get(teamId);
|
|
39871
|
+
if (!row2) return null;
|
|
39623
39872
|
return {
|
|
39624
|
-
teamId:
|
|
39625
|
-
revision:
|
|
39626
|
-
config: validateCodingEnvironmentConfig(JSON.parse(
|
|
39627
|
-
updatedAt:
|
|
39873
|
+
teamId: row2.team_id,
|
|
39874
|
+
revision: row2.revision,
|
|
39875
|
+
config: validateCodingEnvironmentConfig(JSON.parse(row2.config_json)),
|
|
39876
|
+
updatedAt: row2.updated_at
|
|
39628
39877
|
};
|
|
39629
39878
|
}
|
|
39630
39879
|
function putCodingEnvironment(db, teamId, expectedRevision, input) {
|
|
@@ -39649,14 +39898,14 @@ function putCodingEnvironment(db, teamId, expectedRevision, input) {
|
|
|
39649
39898
|
// ../daemon/src/lib/coding-environment/resolve.ts
|
|
39650
39899
|
function resolveTeamCodingEnvironment(db, teamId, env) {
|
|
39651
39900
|
const fallback = resolveShellSecurityConfig(env).sandboxImage;
|
|
39652
|
-
const
|
|
39653
|
-
if (!
|
|
39901
|
+
const environment2 = getCodingEnvironment(db, teamId);
|
|
39902
|
+
if (!environment2) return { image: fallback };
|
|
39654
39903
|
return {
|
|
39655
|
-
image:
|
|
39904
|
+
image: environment2.config.image,
|
|
39656
39905
|
coding: validateDockerCodingSelection({
|
|
39657
|
-
revision:
|
|
39658
|
-
cwd:
|
|
39659
|
-
env:
|
|
39906
|
+
revision: environment2.revision,
|
|
39907
|
+
cwd: environment2.config.cwd,
|
|
39908
|
+
env: environment2.config.env
|
|
39660
39909
|
})
|
|
39661
39910
|
};
|
|
39662
39911
|
}
|
|
@@ -40461,7 +40710,7 @@ var QuestionService = class {
|
|
|
40461
40710
|
turn.conversation.id
|
|
40462
40711
|
).length;
|
|
40463
40712
|
this.#attached.add(turn);
|
|
40464
|
-
const turnId =
|
|
40713
|
+
const turnId = randomUUID35();
|
|
40465
40714
|
const listeners = /* @__PURE__ */ new Set();
|
|
40466
40715
|
if (onQuestion) listeners.add(onQuestion);
|
|
40467
40716
|
this.#turns.set(turnId, {
|
|
@@ -42505,7 +42754,7 @@ function renderTable(token) {
|
|
|
42505
42754
|
const widths = [];
|
|
42506
42755
|
for (let c = 0; c < cols; c++) {
|
|
42507
42756
|
let w2 = headers[c]?.length ?? 0;
|
|
42508
|
-
for (const
|
|
42757
|
+
for (const row2 of rows) w2 = Math.max(w2, row2[c]?.length ?? 0);
|
|
42509
42758
|
widths[c] = w2;
|
|
42510
42759
|
}
|
|
42511
42760
|
const fmt = (cells) => cells.map((cell, c) => c === cols - 1 ? cell : cell.padEnd(widths[c] ?? 0)).join(" ").trimEnd();
|
|
@@ -43028,15 +43277,15 @@ function captureVerificationRequest(db, paths2, intent, env = process.env) {
|
|
|
43028
43277
|
"the captured change has incomplete coverage, so a result could not be tied to it"
|
|
43029
43278
|
);
|
|
43030
43279
|
}
|
|
43031
|
-
const
|
|
43032
|
-
if (!
|
|
43280
|
+
const environment2 = admittedEnvironment(db, team.id, env);
|
|
43281
|
+
if (!environment2) {
|
|
43033
43282
|
return blocked2(
|
|
43034
43283
|
"environment_unavailable",
|
|
43035
43284
|
"the Team has no usable admitted environment to freeze with the request"
|
|
43036
43285
|
);
|
|
43037
43286
|
}
|
|
43038
43287
|
if (intent.writablePaths && intent.writablePaths.length > 0) {
|
|
43039
|
-
const
|
|
43288
|
+
const bounded4 = [];
|
|
43040
43289
|
for (const path of intent.writablePaths) {
|
|
43041
43290
|
if (typeof path !== "string" || path.length === 0 || path.length > 1e3) {
|
|
43042
43291
|
return blocked2("unsupported", "declared writable paths are outside their bounded contract");
|
|
@@ -43051,12 +43300,22 @@ function captureVerificationRequest(db, paths2, intent, env = process.env) {
|
|
|
43051
43300
|
`declared writable path must be inside the workspace: ${path}`
|
|
43052
43301
|
);
|
|
43053
43302
|
}
|
|
43054
|
-
|
|
43303
|
+
bounded4.push(parts.join("/"));
|
|
43055
43304
|
}
|
|
43056
|
-
if (
|
|
43305
|
+
if (bounded4.length > 16) {
|
|
43057
43306
|
return blocked2("unsupported", "too many declared writable paths");
|
|
43058
43307
|
}
|
|
43059
|
-
|
|
43308
|
+
environment2.writablePaths = bounded4;
|
|
43309
|
+
}
|
|
43310
|
+
for (const check of intent.checks) {
|
|
43311
|
+
try {
|
|
43312
|
+
codingRelativePath(check.cwd);
|
|
43313
|
+
} catch {
|
|
43314
|
+
return blocked2(
|
|
43315
|
+
"unsupported",
|
|
43316
|
+
`a check working directory must be a path inside the workspace: ${String(check.cwd)}`
|
|
43317
|
+
);
|
|
43318
|
+
}
|
|
43060
43319
|
}
|
|
43061
43320
|
try {
|
|
43062
43321
|
const request2 = createVerificationRequest(db, {
|
|
@@ -43070,7 +43329,7 @@ function captureVerificationRequest(db, paths2, intent, env = process.env) {
|
|
|
43070
43329
|
snapshotComplete: snapshot.complete,
|
|
43071
43330
|
head: snapshot.head,
|
|
43072
43331
|
baseOid: snapshot.baseOid,
|
|
43073
|
-
environment,
|
|
43332
|
+
environment: environment2,
|
|
43074
43333
|
summary: intent.summary ?? null,
|
|
43075
43334
|
checks: intent.checks
|
|
43076
43335
|
});
|
|
@@ -43566,7 +43825,7 @@ function bound(value) {
|
|
|
43566
43825
|
}
|
|
43567
43826
|
|
|
43568
43827
|
// ../daemon/src/lib/review/dispatch.ts
|
|
43569
|
-
import { randomUUID as
|
|
43828
|
+
import { randomUUID as randomUUID36 } from "crypto";
|
|
43570
43829
|
|
|
43571
43830
|
// ../daemon/src/lib/review/preparation.ts
|
|
43572
43831
|
async function prepareChangeReviewTurn(input) {
|
|
@@ -43785,6 +44044,25 @@ async function readRevisionPatch(db, paths2, packet, path) {
|
|
|
43785
44044
|
}
|
|
43786
44045
|
return { path, patch: change.patch, truncated: change.patchTruncated, reason: null };
|
|
43787
44046
|
}
|
|
44047
|
+
async function readRevisionContentAvailability(db, paths2, packet) {
|
|
44048
|
+
let comparison = null;
|
|
44049
|
+
try {
|
|
44050
|
+
const applicability = await readSnapshotApplicability(
|
|
44051
|
+
db,
|
|
44052
|
+
paths2,
|
|
44053
|
+
packet.teamId,
|
|
44054
|
+
packet.snapshotId
|
|
44055
|
+
);
|
|
44056
|
+
comparison = applicability.comparison;
|
|
44057
|
+
} catch {
|
|
44058
|
+
comparison = null;
|
|
44059
|
+
}
|
|
44060
|
+
if (comparison === "identical") return { contentAvailable: true, contentUnavailableReason: null };
|
|
44061
|
+
return {
|
|
44062
|
+
contentAvailable: false,
|
|
44063
|
+
contentUnavailableReason: comparison === "changed" ? "the working tree changed after the capture, so the reviewed revision\u2019s content is no longer reproducible" : "the reviewed revision could not be compared with the working tree"
|
|
44064
|
+
};
|
|
44065
|
+
}
|
|
43788
44066
|
|
|
43789
44067
|
// ../daemon/src/lib/review/reviewer-capability.ts
|
|
43790
44068
|
function createReviewCapabilityHost(input) {
|
|
@@ -43798,17 +44076,15 @@ function createReviewCapabilityHost(input) {
|
|
|
43798
44076
|
contentUnavailableReason: revision4.reason
|
|
43799
44077
|
};
|
|
43800
44078
|
}
|
|
43801
|
-
const
|
|
44079
|
+
const { contentAvailable, contentUnavailableReason } = await readRevisionContentAvailability(
|
|
43802
44080
|
input.db,
|
|
43803
44081
|
input.paths,
|
|
43804
|
-
packet
|
|
43805
|
-
|
|
43806
|
-
).catch(() => null);
|
|
43807
|
-
const contentAvailable = applicability?.comparison === "identical";
|
|
44082
|
+
packet
|
|
44083
|
+
);
|
|
43808
44084
|
return {
|
|
43809
44085
|
changes: revision4.changes,
|
|
43810
44086
|
contentAvailable,
|
|
43811
|
-
contentUnavailableReason
|
|
44087
|
+
contentUnavailableReason
|
|
43812
44088
|
};
|
|
43813
44089
|
}
|
|
43814
44090
|
return {
|
|
@@ -43912,7 +44188,7 @@ function refused(message) {
|
|
|
43912
44188
|
}
|
|
43913
44189
|
|
|
43914
44190
|
// ../daemon/src/lib/review/dispatch.ts
|
|
43915
|
-
var REVIEW_DISPATCH_OWNER =
|
|
44191
|
+
var REVIEW_DISPATCH_OWNER = randomUUID36();
|
|
43916
44192
|
var REVIEW_LEASE_MS = 10 * 60 * 1e3;
|
|
43917
44193
|
var dispatchRegistry = () => {
|
|
43918
44194
|
const global2 = globalThis;
|
|
@@ -44100,10 +44376,10 @@ function buildReviewDigest(input, options = {}) {
|
|
|
44100
44376
|
}
|
|
44101
44377
|
selected.reverse();
|
|
44102
44378
|
const firstUserIndex = selected.findIndex((entry) => entry.role === "user");
|
|
44103
|
-
const
|
|
44104
|
-
characters =
|
|
44105
|
-
const first =
|
|
44106
|
-
const last =
|
|
44379
|
+
const bounded4 = firstUserIndex >= 0 ? selected.slice(firstUserIndex) : selected;
|
|
44380
|
+
characters = bounded4.reduce((total, entry) => total + entry.text.length, 0);
|
|
44381
|
+
const first = bounded4[0];
|
|
44382
|
+
const last = bounded4.at(-1);
|
|
44107
44383
|
if (!first || !last) return null;
|
|
44108
44384
|
return {
|
|
44109
44385
|
sessionId: last.sessionId,
|
|
@@ -44111,7 +44387,7 @@ function buildReviewDigest(input, options = {}) {
|
|
|
44111
44387
|
endOrdinal: last.ordinal,
|
|
44112
44388
|
inputCharacters: characters,
|
|
44113
44389
|
turnsReviewed: userTurns,
|
|
44114
|
-
entries:
|
|
44390
|
+
entries: bounded4
|
|
44115
44391
|
};
|
|
44116
44392
|
}
|
|
44117
44393
|
|
|
@@ -44353,9 +44629,9 @@ async function dispatchClaimableReviews(now = Date.now()) {
|
|
|
44353
44629
|
}
|
|
44354
44630
|
|
|
44355
44631
|
// ../daemon/src/lib/verification/admission.ts
|
|
44356
|
-
import { randomUUID as
|
|
44632
|
+
import { randomUUID as randomUUID37 } from "crypto";
|
|
44357
44633
|
var VERIFICATION_LEASE_MS = 10 * 60 * 1e3;
|
|
44358
|
-
var VERIFICATION_DISPATCH_OWNER =
|
|
44634
|
+
var VERIFICATION_DISPATCH_OWNER = randomUUID37();
|
|
44359
44635
|
async function admitVerificationRequest(db, paths2, requestId2, now = Date.now()) {
|
|
44360
44636
|
const request2 = getVerificationRequestById(db, requestId2, now);
|
|
44361
44637
|
if (!request2) return { kind: "deferred", requestId: requestId2, reason: "unknown_or_expired" };
|
|
@@ -44493,7 +44769,7 @@ function safeTeam3(db, paths2, teamId) {
|
|
|
44493
44769
|
}
|
|
44494
44770
|
|
|
44495
44771
|
// ../daemon/src/lib/verification/executor.ts
|
|
44496
|
-
import { randomUUID as
|
|
44772
|
+
import { randomUUID as randomUUID38 } from "crypto";
|
|
44497
44773
|
import { existsSync as existsSync17 } from "fs";
|
|
44498
44774
|
import { join as join28, posix as posix2, relative as relative8, sep as sep7 } from "path";
|
|
44499
44775
|
import { createLocalBashOperations as createLocalBashOperations3 } from "@earendil-works/pi-coding-agent";
|
|
@@ -44524,14 +44800,14 @@ function createProtectedCheckExecutor(input) {
|
|
|
44524
44800
|
}
|
|
44525
44801
|
const container = buildContainerOperations(input, env, config2.envAllowlist, absoluteCwd);
|
|
44526
44802
|
if ("blocked" in container) return blocked3("environment_unavailable", container.blocked);
|
|
44527
|
-
const commandId =
|
|
44803
|
+
const commandId = randomUUID38();
|
|
44528
44804
|
const startedAt = Date.now();
|
|
44529
44805
|
const receipt = {
|
|
44530
44806
|
id: commandId,
|
|
44531
44807
|
agentId: input.request.recipientAgentId,
|
|
44532
44808
|
teamId: input.request.teamId,
|
|
44533
44809
|
turnId: input.attemptId,
|
|
44534
|
-
toolCallId: `verification:${input.attemptId}:${
|
|
44810
|
+
toolCallId: `verification:${input.attemptId}:${randomUUID38()}`,
|
|
44535
44811
|
input: {
|
|
44536
44812
|
command,
|
|
44537
44813
|
cwd: relative9,
|
|
@@ -44824,12 +45100,7 @@ function renderResult2(input) {
|
|
|
44824
45100
|
}
|
|
44825
45101
|
}
|
|
44826
45102
|
if (attempt.error) lines.push("", `Limitation: ${attempt.error}`);
|
|
44827
|
-
lines.push(
|
|
44828
|
-
"",
|
|
44829
|
-
"Facts above are executor-owned. A non-zero exit is a result about the commands that ran, never",
|
|
44830
|
-
"proof about later code, and this is not an approval to publish, merge or deploy. Declared output",
|
|
44831
|
-
"paths are not enforced, so a change they do not cover appears above rather than being prevented."
|
|
44832
|
-
);
|
|
45103
|
+
lines.push("", VERIFICATION_OUTCOME_LIMITS[0], VERIFICATION_OUTCOME_LIMITS[1]);
|
|
44833
45104
|
const payload = lines.join("\n");
|
|
44834
45105
|
return payload.length > MAX_RESULT_CHARACTERS2 ? `${payload.slice(0, MAX_RESULT_CHARACTERS2)}
|
|
44835
45106
|
[result truncated]` : payload;
|
|
@@ -45029,7 +45300,7 @@ async function fingerprintWorkspace(root) {
|
|
|
45029
45300
|
let children;
|
|
45030
45301
|
try {
|
|
45031
45302
|
children = await readdir(join29(root, dir), { withFileTypes: true }).then(
|
|
45032
|
-
(rows) => rows.map((
|
|
45303
|
+
(rows) => rows.map((row2) => row2.name)
|
|
45033
45304
|
);
|
|
45034
45305
|
} catch {
|
|
45035
45306
|
continue;
|
|
@@ -45266,7 +45537,7 @@ async function dispatchPendingVerifications(now = Date.now()) {
|
|
|
45266
45537
|
ORDER BY created_at LIMIT 20`
|
|
45267
45538
|
).all(now);
|
|
45268
45539
|
void paths2;
|
|
45269
|
-
await Promise.allSettled(pending.map((
|
|
45540
|
+
await Promise.allSettled(pending.map((row2) => dispatchVerificationRequest(row2.id)));
|
|
45270
45541
|
}
|
|
45271
45542
|
function currentSecrets() {
|
|
45272
45543
|
const { db, authToken } = getCtx();
|
|
@@ -45673,6 +45944,7 @@ async function tick() {
|
|
|
45673
45944
|
for (const agentId of recipients) {
|
|
45674
45945
|
work.push(fireInboxWake(agentId));
|
|
45675
45946
|
}
|
|
45947
|
+
recoverExpiredPublications(ctx.db, now);
|
|
45676
45948
|
work.push(dispatchClaimableReviews(now));
|
|
45677
45949
|
work.push(dispatchPendingVerifications(now));
|
|
45678
45950
|
for (const packet of dispatchableReviews()) {
|
|
@@ -45743,6 +46015,7 @@ function bootstrap(paths2) {
|
|
|
45743
46015
|
interruptCodingCommands(db);
|
|
45744
46016
|
recoverInterruptedVerificationAttempts(db, VERIFICATION_DISPATCH_OWNER);
|
|
45745
46017
|
recoverInterruptedReviewAttempts(db, Date.now());
|
|
46018
|
+
recoverExpiredPublications(db);
|
|
45746
46019
|
reconcileApprovalHolds(db);
|
|
45747
46020
|
recoverInterruptedResultDeliveries(db);
|
|
45748
46021
|
reconcilePrivateResults(db);
|
|
@@ -45910,7 +46183,7 @@ async function authMiddleware(c, next) {
|
|
|
45910
46183
|
}
|
|
45911
46184
|
|
|
45912
46185
|
// ../daemon/src/routes/agents.ts
|
|
45913
|
-
import { randomUUID as
|
|
46186
|
+
import { randomUUID as randomUUID40 } from "crypto";
|
|
45914
46187
|
import { existsSync as existsSync19, readFileSync as readFileSync12 } from "fs";
|
|
45915
46188
|
import { join as join30 } from "path";
|
|
45916
46189
|
import { Hono } from "hono";
|
|
@@ -47235,7 +47508,7 @@ async function notifyTelegramQueueStatus(db, agentId, itemId) {
|
|
|
47235
47508
|
}
|
|
47236
47509
|
|
|
47237
47510
|
// ../daemon/src/lib/user-queue-admission.ts
|
|
47238
|
-
import { randomUUID as
|
|
47511
|
+
import { randomUUID as randomUUID39 } from "crypto";
|
|
47239
47512
|
async function enqueueTelegramInput(binding, message, attachments2, context = getCtx()) {
|
|
47240
47513
|
validateInput(message, attachments2);
|
|
47241
47514
|
const { db, paths: paths2, authToken } = context;
|
|
@@ -47254,7 +47527,7 @@ async function enqueueTelegramInput(binding, message, attachments2, context = ge
|
|
|
47254
47527
|
const existing = findAttempt(db, "telegram", binding.authorization.attemptId);
|
|
47255
47528
|
return db.raw.transaction(() => {
|
|
47256
47529
|
const item = accept(db, {
|
|
47257
|
-
id: existing?.id ??
|
|
47530
|
+
id: existing?.id ?? randomUUID39(),
|
|
47258
47531
|
agentId,
|
|
47259
47532
|
teamId: existing?.teamId ?? agent.team.id,
|
|
47260
47533
|
conversationId,
|
|
@@ -49074,7 +49347,7 @@ agentsRouter.post("/:id/chat", async (c) => {
|
|
|
49074
49347
|
if (!message && attachments2.length === 0) {
|
|
49075
49348
|
return c.json({ error: "message or an attachment is required" }, 400);
|
|
49076
49349
|
}
|
|
49077
|
-
const requestAttemptId = c.req.header("x-request-id") ??
|
|
49350
|
+
const requestAttemptId = c.req.header("x-request-id") ?? randomUUID40();
|
|
49078
49351
|
let preparedTurn;
|
|
49079
49352
|
try {
|
|
49080
49353
|
preparedTurn = await prepareAgentTurn({
|
|
@@ -51432,13 +51705,13 @@ function assertSnapshotIntegrity(path) {
|
|
|
51432
51705
|
try {
|
|
51433
51706
|
const rows = snapshot.prepare("PRAGMA integrity_check").all();
|
|
51434
51707
|
if (rows.length !== 1 || rows[0]?.integrity_check !== "ok") {
|
|
51435
|
-
const detail3 = rows.map((
|
|
51708
|
+
const detail3 = rows.map((row2) => row2.integrity_check).join("; ") || "no result";
|
|
51436
51709
|
throw new Error(`SQLite snapshot failed integrity_check: ${detail3}`);
|
|
51437
51710
|
}
|
|
51438
|
-
for (const
|
|
51439
|
-
const bytes =
|
|
51440
|
-
if (!(bytes instanceof Uint8Array) || bytes.byteLength !==
|
|
51441
|
-
throw new Error(`Result snapshot integrity verification failed: ${
|
|
51711
|
+
for (const row2 of snapshot.prepare("SELECT id, bytes, byte_length, sha256 FROM agent_results WHERE deleted_at IS NULL").iterate()) {
|
|
51712
|
+
const bytes = row2.bytes;
|
|
51713
|
+
if (!(bytes instanceof Uint8Array) || bytes.byteLength !== row2.byte_length || createHash17("sha256").update(bytes).digest("hex") !== row2.sha256) {
|
|
51714
|
+
throw new Error(`Result snapshot integrity verification failed: ${row2.id}`);
|
|
51442
51715
|
}
|
|
51443
51716
|
}
|
|
51444
51717
|
const foreignKeyErrors = snapshot.prepare("PRAGMA foreign_key_check").all();
|
|
@@ -51505,7 +51778,7 @@ function createBackupArchive(paths2, snapshot) {
|
|
|
51505
51778
|
}
|
|
51506
51779
|
|
|
51507
51780
|
// ../daemon/src/lib/daemon-liveness.ts
|
|
51508
|
-
import { createHash as createHash18, randomUUID as
|
|
51781
|
+
import { createHash as createHash18, randomUUID as randomUUID41 } from "crypto";
|
|
51509
51782
|
import {
|
|
51510
51783
|
chmodSync as chmodSync2,
|
|
51511
51784
|
closeSync as closeSync10,
|
|
@@ -51675,7 +51948,7 @@ function acquireDaemonLiveness(paths2) {
|
|
|
51675
51948
|
mkdirSync11(dirname6(resolve7(paths2.home)), { recursive: true });
|
|
51676
51949
|
const path = daemonLivenessPath(paths2.home);
|
|
51677
51950
|
mkdirSync11(dirname6(path), { recursive: true });
|
|
51678
|
-
const instanceId =
|
|
51951
|
+
const instanceId = randomUUID41();
|
|
51679
51952
|
const startedAt = Date.now();
|
|
51680
51953
|
let fd = null;
|
|
51681
51954
|
let reclaimClaim = null;
|
|
@@ -52190,7 +52463,7 @@ import { bodyLimit } from "hono/body-limit";
|
|
|
52190
52463
|
import { HTTPException } from "hono/http-exception";
|
|
52191
52464
|
|
|
52192
52465
|
// ../daemon/src/lib/notification-control.ts
|
|
52193
|
-
import { randomUUID as
|
|
52466
|
+
import { randomUUID as randomUUID42 } from "crypto";
|
|
52194
52467
|
|
|
52195
52468
|
// ../daemon/src/lib/notification-authorization.ts
|
|
52196
52469
|
function authorizeAttentionNotification(db, item, captured) {
|
|
@@ -52355,7 +52628,7 @@ var NotificationControl = class {
|
|
|
52355
52628
|
);
|
|
52356
52629
|
for (const item of items) byKind[item.kind]++;
|
|
52357
52630
|
const value = {
|
|
52358
|
-
id:
|
|
52631
|
+
id: randomUUID42(),
|
|
52359
52632
|
settingsRevision: revision4,
|
|
52360
52633
|
destinationId: binding.id,
|
|
52361
52634
|
kinds,
|
|
@@ -52573,7 +52846,7 @@ var NotificationDispatcher = class {
|
|
|
52573
52846
|
const known = new Set(
|
|
52574
52847
|
this.db.raw.query(
|
|
52575
52848
|
"SELECT source_kind || ':' || source_id key FROM notification_receipts WHERE destination_id=?"
|
|
52576
|
-
).all(binding.id).map((
|
|
52849
|
+
).all(binding.id).map((row2) => row2.key)
|
|
52577
52850
|
);
|
|
52578
52851
|
let admitted = 0;
|
|
52579
52852
|
const cutoffs = eligibilityCutoffs(this.db);
|
|
@@ -53265,7 +53538,7 @@ async function parseImportInput(request2) {
|
|
|
53265
53538
|
}
|
|
53266
53539
|
|
|
53267
53540
|
// ../daemon/src/routes/team-templates.ts
|
|
53268
|
-
import { randomUUID as
|
|
53541
|
+
import { randomUUID as randomUUID43 } from "crypto";
|
|
53269
53542
|
import { Hono as Hono17 } from "hono";
|
|
53270
53543
|
var teamTemplatesRouter = new Hono17();
|
|
53271
53544
|
teamTemplatesRouter.get("/", (c) => {
|
|
@@ -53305,7 +53578,7 @@ teamTemplatesRouter.post("/import", async (c) => {
|
|
|
53305
53578
|
if (!profiles_exports.get(db, parsed.profileId)) {
|
|
53306
53579
|
throw new Error(`profile not found: ${parsed.profileId}`);
|
|
53307
53580
|
}
|
|
53308
|
-
const slotId =
|
|
53581
|
+
const slotId = randomUUID43();
|
|
53309
53582
|
keyToSlot.set(clientKey, slotId);
|
|
53310
53583
|
return { ...parsed, slotId };
|
|
53311
53584
|
});
|
|
@@ -53597,7 +53870,7 @@ function canonicalError(c, error2) {
|
|
|
53597
53870
|
}
|
|
53598
53871
|
|
|
53599
53872
|
// ../daemon/src/routes/teams.ts
|
|
53600
|
-
import { join as
|
|
53873
|
+
import { join as join39 } from "path";
|
|
53601
53874
|
import { Hono as Hono18 } from "hono";
|
|
53602
53875
|
|
|
53603
53876
|
// ../daemon/src/lib/coding-environment/management.ts
|
|
@@ -53753,6 +54026,604 @@ function lineRange(request2, _captured) {
|
|
|
53753
54026
|
return { start, end };
|
|
53754
54027
|
}
|
|
53755
54028
|
|
|
54029
|
+
// ../daemon/src/lib/publication/config.ts
|
|
54030
|
+
var PUBLICATION_CONFIG = {
|
|
54031
|
+
host: "PUBLICATION_HOST",
|
|
54032
|
+
repository: "PUBLICATION_REPOSITORY",
|
|
54033
|
+
baseBranch: "PUBLICATION_BASE_BRANCH"
|
|
54034
|
+
};
|
|
54035
|
+
var PUBLICATION_CREDENTIAL_KEY = "GITHUB_TOKEN";
|
|
54036
|
+
var HOSTS = ["github", "local"];
|
|
54037
|
+
function resolvePublicationTarget(db, authToken) {
|
|
54038
|
+
const config2 = openConfig(db);
|
|
54039
|
+
const configured = config2.get(PUBLICATION_CONFIG.host)?.trim().toLowerCase() ?? "";
|
|
54040
|
+
if (!configured) {
|
|
54041
|
+
return {
|
|
54042
|
+
ok: false,
|
|
54043
|
+
reason: "host_not_configured",
|
|
54044
|
+
detail: `no publication host is configured (set ${PUBLICATION_CONFIG.host}); nothing was sent`
|
|
54045
|
+
};
|
|
54046
|
+
}
|
|
54047
|
+
if (!HOSTS.includes(configured)) {
|
|
54048
|
+
return {
|
|
54049
|
+
ok: false,
|
|
54050
|
+
reason: "host_not_configured",
|
|
54051
|
+
detail: `the configured publication host is not supported by this build: ${configured}`
|
|
54052
|
+
};
|
|
54053
|
+
}
|
|
54054
|
+
const repository = config2.get(PUBLICATION_CONFIG.repository)?.trim() ?? "";
|
|
54055
|
+
if (!repository) {
|
|
54056
|
+
return {
|
|
54057
|
+
ok: false,
|
|
54058
|
+
reason: "host_not_configured",
|
|
54059
|
+
detail: `no repository is configured (set ${PUBLICATION_CONFIG.repository}); nothing was sent`
|
|
54060
|
+
};
|
|
54061
|
+
}
|
|
54062
|
+
const baseBranch = config2.get(PUBLICATION_CONFIG.baseBranch)?.trim() || "main";
|
|
54063
|
+
const credential = openSecrets(db, authToken).get(PUBLICATION_CREDENTIAL_KEY)?.trim() ?? "";
|
|
54064
|
+
if (!credential) {
|
|
54065
|
+
return {
|
|
54066
|
+
ok: false,
|
|
54067
|
+
reason: "credential_missing",
|
|
54068
|
+
detail: `no credential is stored for ${configured} (set ${PUBLICATION_CREDENTIAL_KEY}); nothing was sent`
|
|
54069
|
+
};
|
|
54070
|
+
}
|
|
54071
|
+
return {
|
|
54072
|
+
ok: true,
|
|
54073
|
+
target: { host: configured, repository, baseBranch, credential }
|
|
54074
|
+
};
|
|
54075
|
+
}
|
|
54076
|
+
|
|
54077
|
+
// ../daemon/src/lib/publication/revision-content.ts
|
|
54078
|
+
import { createHash as createHash19 } from "crypto";
|
|
54079
|
+
import { readFileSync as readFileSync15 } from "fs";
|
|
54080
|
+
import { join as join36 } from "path";
|
|
54081
|
+
function readReviewedRevisionFiles(db, paths2, packet) {
|
|
54082
|
+
const record3 = getSourceSnapshot(db, packet.teamId, packet.snapshotId);
|
|
54083
|
+
if (!record3) {
|
|
54084
|
+
return {
|
|
54085
|
+
ok: false,
|
|
54086
|
+
reason: "revision_unavailable",
|
|
54087
|
+
detail: "the reviewed revision is no longer retained, so its content cannot be committed"
|
|
54088
|
+
};
|
|
54089
|
+
}
|
|
54090
|
+
if (!record3.complete) {
|
|
54091
|
+
return {
|
|
54092
|
+
ok: false,
|
|
54093
|
+
reason: "revision_unavailable",
|
|
54094
|
+
detail: "the reviewed revision has incomplete coverage, so publishing it would commit a partial change"
|
|
54095
|
+
};
|
|
54096
|
+
}
|
|
54097
|
+
let snapshot;
|
|
54098
|
+
try {
|
|
54099
|
+
snapshot = JSON.parse(record3.manifestJson);
|
|
54100
|
+
} catch {
|
|
54101
|
+
return {
|
|
54102
|
+
ok: false,
|
|
54103
|
+
reason: "revision_unavailable",
|
|
54104
|
+
detail: "the reviewed revision manifest could not be read"
|
|
54105
|
+
};
|
|
54106
|
+
}
|
|
54107
|
+
const files = [];
|
|
54108
|
+
const removed = [];
|
|
54109
|
+
for (const entry of snapshot.entries) {
|
|
54110
|
+
if (entry.kind === "deleted") {
|
|
54111
|
+
removed.push(entry.path);
|
|
54112
|
+
continue;
|
|
54113
|
+
}
|
|
54114
|
+
if (entry.kind !== "file") {
|
|
54115
|
+
return {
|
|
54116
|
+
ok: false,
|
|
54117
|
+
reason: "revision_not_reproducible",
|
|
54118
|
+
detail: `the reviewed revision records ${entry.path} as ${entry.kind}, so its content cannot be committed`
|
|
54119
|
+
};
|
|
54120
|
+
}
|
|
54121
|
+
if (!entry.digest) {
|
|
54122
|
+
return {
|
|
54123
|
+
ok: false,
|
|
54124
|
+
reason: "revision_not_reproducible",
|
|
54125
|
+
detail: `the reviewed revision captured no content for ${entry.path}`
|
|
54126
|
+
};
|
|
54127
|
+
}
|
|
54128
|
+
let content;
|
|
54129
|
+
try {
|
|
54130
|
+
content = readFileSync15(join36(paths2.teamDir(packet.teamId), entry.path));
|
|
54131
|
+
} catch {
|
|
54132
|
+
return {
|
|
54133
|
+
ok: false,
|
|
54134
|
+
reason: "revision_not_reproducible",
|
|
54135
|
+
detail: `the reviewed content for ${entry.path} can no longer be read`
|
|
54136
|
+
};
|
|
54137
|
+
}
|
|
54138
|
+
const digest4 = createHash19("sha256").update(content).digest("hex");
|
|
54139
|
+
if (digest4 !== entry.digest) {
|
|
54140
|
+
return {
|
|
54141
|
+
ok: false,
|
|
54142
|
+
reason: "revision_not_reproducible",
|
|
54143
|
+
detail: `the content of ${entry.path} no longer matches the reviewed revision, so committing it would publish a different change`
|
|
54144
|
+
};
|
|
54145
|
+
}
|
|
54146
|
+
files.push({ path: entry.path, content });
|
|
54147
|
+
}
|
|
54148
|
+
if (files.length === 0 && removed.length === 0) {
|
|
54149
|
+
return {
|
|
54150
|
+
ok: false,
|
|
54151
|
+
reason: "revision_unavailable",
|
|
54152
|
+
detail: "the reviewed revision records no changed content to publish"
|
|
54153
|
+
};
|
|
54154
|
+
}
|
|
54155
|
+
return { ok: true, files, removed };
|
|
54156
|
+
}
|
|
54157
|
+
|
|
54158
|
+
// ../daemon/src/lib/publication/capture.ts
|
|
54159
|
+
function defaultHeadBranch(packetId) {
|
|
54160
|
+
return `bazilion/review-${packetId.slice(0, 8)}`;
|
|
54161
|
+
}
|
|
54162
|
+
function validateHeadBranch(branch) {
|
|
54163
|
+
if (branch.length === 0 || branch.length > PUBLICATION_LIMITS.branch) {
|
|
54164
|
+
return { ok: false, detail: "the branch name is empty or too long" };
|
|
54165
|
+
}
|
|
54166
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._/-]*$/.test(branch)) {
|
|
54167
|
+
return {
|
|
54168
|
+
ok: false,
|
|
54169
|
+
detail: `the branch name has characters this build will not publish: ${branch}`
|
|
54170
|
+
};
|
|
54171
|
+
}
|
|
54172
|
+
if (branch.includes("..") || branch.includes("//") || branch.endsWith("/") || branch.endsWith(".lock")) {
|
|
54173
|
+
return { ok: false, detail: `the branch name is not a valid ref: ${branch}` };
|
|
54174
|
+
}
|
|
54175
|
+
const protectedName = PUBLICATION_LIMITS.protectedBranches.find(
|
|
54176
|
+
(name) => name === branch || branch.endsWith(`/${name}`)
|
|
54177
|
+
);
|
|
54178
|
+
if (protectedName) {
|
|
54179
|
+
return {
|
|
54180
|
+
ok: false,
|
|
54181
|
+
detail: `this build never publishes to ${branch}: it is the protected branch ${protectedName}`
|
|
54182
|
+
};
|
|
54183
|
+
}
|
|
54184
|
+
return { ok: true };
|
|
54185
|
+
}
|
|
54186
|
+
async function capturePublication(db, paths2, authToken, intent) {
|
|
54187
|
+
const packet = getReviewPacket(db, intent.packetId);
|
|
54188
|
+
if (!packet || packet.teamId !== intent.teamId) {
|
|
54189
|
+
return refused2("packet_unknown", "the review packet is unknown in this Team");
|
|
54190
|
+
}
|
|
54191
|
+
if (packet.state !== "reviewed") {
|
|
54192
|
+
return refused2(
|
|
54193
|
+
"packet_not_reviewed",
|
|
54194
|
+
`the packet is ${packet.state}: publishing is a decision about a reviewed revision, not a promise about one`
|
|
54195
|
+
);
|
|
54196
|
+
}
|
|
54197
|
+
const conclusions = listReviewConclusions(db, packet.id);
|
|
54198
|
+
if (conclusions.length === 0) {
|
|
54199
|
+
return refused2(
|
|
54200
|
+
"missing_reviewer_conclusion",
|
|
54201
|
+
"the packet has no recorded conclusion, so there is nothing reviewed to publish"
|
|
54202
|
+
);
|
|
54203
|
+
}
|
|
54204
|
+
const target = resolvePublicationTarget(db, authToken);
|
|
54205
|
+
if (!target.ok) return refused2(target.reason, target.detail);
|
|
54206
|
+
const headBranch = (intent.headBranch ?? "").trim() || defaultHeadBranch(packet.id);
|
|
54207
|
+
const branch = validateHeadBranch(headBranch);
|
|
54208
|
+
if (!branch.ok) return refused2("branch_protected", branch.detail);
|
|
54209
|
+
const files = readReviewedRevisionFiles(db, paths2, packet);
|
|
54210
|
+
if (!files.ok) {
|
|
54211
|
+
if (files.reason === "revision_not_reproducible") {
|
|
54212
|
+
return refused2("revision_not_reproducible", files.detail);
|
|
54213
|
+
}
|
|
54214
|
+
return refused2("revision_unavailable", files.detail);
|
|
54215
|
+
}
|
|
54216
|
+
if (files.files.length === 0 && files.removed.length === 0) {
|
|
54217
|
+
return refused2("nothing_to_publish", "the reviewed revision holds no change to publish");
|
|
54218
|
+
}
|
|
54219
|
+
const commitMessage = (intent.commitMessage ?? "").trim() || `${conclusionTitle(conclusions[0]?.conclusion ?? "reviewed")}: ${packet.summary?.trim() || "reviewed change"}`;
|
|
54220
|
+
try {
|
|
54221
|
+
const publication = createPublication(db, {
|
|
54222
|
+
teamId: intent.teamId,
|
|
54223
|
+
packetId: packet.id,
|
|
54224
|
+
snapshotId: packet.snapshotId,
|
|
54225
|
+
host: target.target.host,
|
|
54226
|
+
repository: target.target.repository,
|
|
54227
|
+
baseBranch: target.target.baseBranch,
|
|
54228
|
+
headBranch,
|
|
54229
|
+
baseOid: packet.baseOid,
|
|
54230
|
+
commitMessage: bounded3(commitMessage, PUBLICATION_LIMITS.commitMessage),
|
|
54231
|
+
notifyAgentId: packet.requesterKind === "agent" ? packet.requesterAgentId : null
|
|
54232
|
+
});
|
|
54233
|
+
return { kind: "captured", publication };
|
|
54234
|
+
} catch (error2) {
|
|
54235
|
+
if (error2 instanceof PublicationError) {
|
|
54236
|
+
return refused2(error2.code, error2.message);
|
|
54237
|
+
}
|
|
54238
|
+
throw error2;
|
|
54239
|
+
}
|
|
54240
|
+
}
|
|
54241
|
+
function conclusionTitle(conclusion) {
|
|
54242
|
+
return conclusion === "changes_requested" ? "Reviewed change with requested changes" : conclusion === "recommended" ? "Reviewed change" : "Reviewed change (inconclusive review)";
|
|
54243
|
+
}
|
|
54244
|
+
function bounded3(value, max) {
|
|
54245
|
+
return value.length <= max ? value : `${value.slice(0, max - 1)}\u2026`;
|
|
54246
|
+
}
|
|
54247
|
+
function refused2(reason, detail3) {
|
|
54248
|
+
return { kind: "refused", reason, detail: bounded3(detail3, PUBLICATION_LIMITS.refusalDetail) };
|
|
54249
|
+
}
|
|
54250
|
+
|
|
54251
|
+
// ../daemon/src/lib/publication/git-publish.ts
|
|
54252
|
+
import { execFile as execFile2 } from "child_process";
|
|
54253
|
+
import { mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync7, rmSync as rmSync18, writeFileSync as writeFileSync17 } from "fs";
|
|
54254
|
+
import { dirname as dirname7, join as join37 } from "path";
|
|
54255
|
+
import { promisify } from "util";
|
|
54256
|
+
var execFileAsync = promisify(execFile2);
|
|
54257
|
+
var COMMAND_BUDGET_MS = 6e4;
|
|
54258
|
+
var MAX_OUTPUT = 64 * 1024;
|
|
54259
|
+
var AUTHOR_NAME = "Bazilion";
|
|
54260
|
+
var AUTHOR_EMAIL = "bazilion@localhost";
|
|
54261
|
+
async function publishRevisionCommit(input) {
|
|
54262
|
+
const scratch = mkdtempSync7(join37(input.scratchParentDir ?? "/tmp", "bazilion-publish-"));
|
|
54263
|
+
const gitDir = join37(scratch, "repo");
|
|
54264
|
+
const gitEnv = environment(scratch, input.remoteUrl, input.credential);
|
|
54265
|
+
const run = (args, cwd = scratch) => git(["-C", gitDir, ...args], cwd, gitEnv);
|
|
54266
|
+
try {
|
|
54267
|
+
await git(
|
|
54268
|
+
[
|
|
54269
|
+
"-c",
|
|
54270
|
+
"init.templateDir=",
|
|
54271
|
+
"clone",
|
|
54272
|
+
"--no-checkout",
|
|
54273
|
+
"--no-hardlinks",
|
|
54274
|
+
"--quiet",
|
|
54275
|
+
input.teamDir,
|
|
54276
|
+
gitDir
|
|
54277
|
+
],
|
|
54278
|
+
scratch,
|
|
54279
|
+
gitEnv
|
|
54280
|
+
);
|
|
54281
|
+
try {
|
|
54282
|
+
await run(["rev-parse", "--verify", "--quiet", `${input.baseOid}^{commit}`]);
|
|
54283
|
+
} catch {
|
|
54284
|
+
return {
|
|
54285
|
+
ok: false,
|
|
54286
|
+
reason: "base_unknown",
|
|
54287
|
+
detail: "the pinned base commit is not present in the Team repository"
|
|
54288
|
+
};
|
|
54289
|
+
}
|
|
54290
|
+
const existing = await remoteHeads(input, gitEnv);
|
|
54291
|
+
if (existing.includes(input.headBranch)) {
|
|
54292
|
+
return {
|
|
54293
|
+
ok: false,
|
|
54294
|
+
reason: "head_branch_exists",
|
|
54295
|
+
detail: `the remote already has a branch named ${input.headBranch}; publishing over it is not something this build will do`
|
|
54296
|
+
};
|
|
54297
|
+
}
|
|
54298
|
+
await run(["checkout", "--quiet", "--detach", input.baseOid]);
|
|
54299
|
+
for (const file of input.files) {
|
|
54300
|
+
const target = join37(gitDir, file.path);
|
|
54301
|
+
mkdirSync12(dirname7(target), { recursive: true });
|
|
54302
|
+
writeFileSync17(target, file.content);
|
|
54303
|
+
}
|
|
54304
|
+
for (const path of input.removed) {
|
|
54305
|
+
await run(["rm", "--quiet", "--ignore-unmatch", "--", path]);
|
|
54306
|
+
}
|
|
54307
|
+
await run(["add", "--all", "--", "."]);
|
|
54308
|
+
await run([
|
|
54309
|
+
"-c",
|
|
54310
|
+
"commit.gpgsign=false",
|
|
54311
|
+
"-c",
|
|
54312
|
+
`user.name=${AUTHOR_NAME}`,
|
|
54313
|
+
"-c",
|
|
54314
|
+
`user.email=${AUTHOR_EMAIL}`,
|
|
54315
|
+
"commit",
|
|
54316
|
+
"--quiet",
|
|
54317
|
+
"--no-verify",
|
|
54318
|
+
"-m",
|
|
54319
|
+
input.commitMessage
|
|
54320
|
+
]);
|
|
54321
|
+
const commitOid = await run(["rev-parse", "HEAD"]);
|
|
54322
|
+
try {
|
|
54323
|
+
await run(["push", "--quiet", input.remoteUrl, `HEAD:refs/heads/${input.headBranch}`]);
|
|
54324
|
+
} catch (error2) {
|
|
54325
|
+
return {
|
|
54326
|
+
ok: false,
|
|
54327
|
+
reason: "push_rejected",
|
|
54328
|
+
detail: `the push was refused: ${summarize(error2)}`
|
|
54329
|
+
};
|
|
54330
|
+
}
|
|
54331
|
+
return { ok: true, commitOid };
|
|
54332
|
+
} catch (error2) {
|
|
54333
|
+
return { ok: false, reason: "commit_failed", detail: summarize(error2) };
|
|
54334
|
+
} finally {
|
|
54335
|
+
rmSync18(scratch, { recursive: true, force: true });
|
|
54336
|
+
}
|
|
54337
|
+
}
|
|
54338
|
+
async function remoteHeads(input, env) {
|
|
54339
|
+
const output = await git(["ls-remote", "--heads", input.remoteUrl], process.cwd(), env);
|
|
54340
|
+
return output.split("\n").map((line) => line.trim()).filter((line) => line.length > 0).map((line) => line.split(/\s+/)[1] ?? "").filter((ref) => ref.startsWith("refs/heads/")).map((ref) => ref.slice("refs/heads/".length));
|
|
54341
|
+
}
|
|
54342
|
+
function environment(scratch, remoteUrl, credential) {
|
|
54343
|
+
const env = {
|
|
54344
|
+
PATH: process.env.PATH,
|
|
54345
|
+
HOME: scratch,
|
|
54346
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
54347
|
+
GIT_CONFIG_GLOBAL: "/dev/null",
|
|
54348
|
+
// Never prompt: a missing credential must fail, not hang a daemon thread waiting for a terminal.
|
|
54349
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
54350
|
+
GIT_ASKPASS: "",
|
|
54351
|
+
SSH_ASKPASS: "",
|
|
54352
|
+
GIT_LFS_SKIP_SMUDGE: "1"
|
|
54353
|
+
};
|
|
54354
|
+
const entries = [
|
|
54355
|
+
["credential.helper", ""],
|
|
54356
|
+
["core.hooksPath", "/dev/null"],
|
|
54357
|
+
["core.autocrlf", "false"],
|
|
54358
|
+
["gc.auto", "0"],
|
|
54359
|
+
["http.followRedirects", "false"]
|
|
54360
|
+
];
|
|
54361
|
+
if (/^https?:\/\//.test(remoteUrl)) {
|
|
54362
|
+
const basic = Buffer.from(`x-access-token:${credential}`, "utf8").toString("base64");
|
|
54363
|
+
entries.push(["http.extraheader", `Authorization: Basic ${basic}`]);
|
|
54364
|
+
}
|
|
54365
|
+
entries.forEach(([key3, value], index) => {
|
|
54366
|
+
env[`GIT_CONFIG_KEY_${index}`] = key3;
|
|
54367
|
+
env[`GIT_CONFIG_VALUE_${index}`] = value;
|
|
54368
|
+
});
|
|
54369
|
+
env.GIT_CONFIG_COUNT = String(entries.length);
|
|
54370
|
+
return env;
|
|
54371
|
+
}
|
|
54372
|
+
async function git(args, cwd, env) {
|
|
54373
|
+
try {
|
|
54374
|
+
const { stdout } = await execFileAsync("git", args, {
|
|
54375
|
+
cwd,
|
|
54376
|
+
env,
|
|
54377
|
+
timeout: COMMAND_BUDGET_MS,
|
|
54378
|
+
maxBuffer: MAX_OUTPUT,
|
|
54379
|
+
encoding: "utf8"
|
|
54380
|
+
});
|
|
54381
|
+
return stdout.trim();
|
|
54382
|
+
} catch (error2) {
|
|
54383
|
+
throw new Error(summarize(error2));
|
|
54384
|
+
}
|
|
54385
|
+
}
|
|
54386
|
+
function summarize(error2) {
|
|
54387
|
+
const stderr = typeof error2 === "object" && error2 !== null && "stderr" in error2 ? String(error2.stderr ?? "") : "";
|
|
54388
|
+
const message = stderr.trim() || (error2 instanceof Error ? error2.message : String(error2)) || "unknown failure";
|
|
54389
|
+
return message.length > 300 ? `${message.slice(0, 300)}\u2026` : message;
|
|
54390
|
+
}
|
|
54391
|
+
|
|
54392
|
+
// ../daemon/src/lib/publication/host/github.ts
|
|
54393
|
+
var API = "https://api.github.com";
|
|
54394
|
+
var REQUEST_TIMEOUT_MS = 3e4;
|
|
54395
|
+
function createGitHubAdapter(input) {
|
|
54396
|
+
const apiBase = input.apiBaseUrl ?? API;
|
|
54397
|
+
const doFetch = input.fetchImpl ?? fetch;
|
|
54398
|
+
const headers = {
|
|
54399
|
+
accept: "application/vnd.github+json",
|
|
54400
|
+
authorization: `Bearer ${input.credential}`,
|
|
54401
|
+
"content-type": "application/json",
|
|
54402
|
+
"user-agent": "bazilion",
|
|
54403
|
+
"x-github-api-version": "2022-11-28"
|
|
54404
|
+
};
|
|
54405
|
+
return {
|
|
54406
|
+
remoteUrl(target) {
|
|
54407
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*\/[A-Za-z0-9][A-Za-z0-9._-]*$/.test(target.repository)) {
|
|
54408
|
+
return {
|
|
54409
|
+
ok: false,
|
|
54410
|
+
reason: "origin_not_configured",
|
|
54411
|
+
detail: `the configured repository is not a GitHub owner/name: ${target.repository}`
|
|
54412
|
+
};
|
|
54413
|
+
}
|
|
54414
|
+
return { ok: true, url: `https://github.com/${target.repository}.git` };
|
|
54415
|
+
},
|
|
54416
|
+
async openPullRequest(target) {
|
|
54417
|
+
let response;
|
|
54418
|
+
try {
|
|
54419
|
+
response = await doFetch(`${apiBase}/repos/${target.repository}/pulls`, {
|
|
54420
|
+
method: "POST",
|
|
54421
|
+
headers,
|
|
54422
|
+
body: JSON.stringify({
|
|
54423
|
+
title: target.title,
|
|
54424
|
+
head: target.headBranch,
|
|
54425
|
+
base: target.baseBranch,
|
|
54426
|
+
body: target.body
|
|
54427
|
+
}),
|
|
54428
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
54429
|
+
});
|
|
54430
|
+
} catch {
|
|
54431
|
+
return {
|
|
54432
|
+
ok: false,
|
|
54433
|
+
reason: "host_unavailable",
|
|
54434
|
+
detail: "the host could not be reached, so whether the branch has a pull request is unknown"
|
|
54435
|
+
};
|
|
54436
|
+
}
|
|
54437
|
+
if (!response.ok) {
|
|
54438
|
+
const text3 = await safeText(response);
|
|
54439
|
+
return {
|
|
54440
|
+
ok: false,
|
|
54441
|
+
reason: "host_refused",
|
|
54442
|
+
detail: `the host refused the pull request (${response.status}): ${text3}`
|
|
54443
|
+
};
|
|
54444
|
+
}
|
|
54445
|
+
const body = await response.json().catch(() => null);
|
|
54446
|
+
const outcome = {
|
|
54447
|
+
pullRequestNumber: typeof body?.number === "number" ? body.number : null,
|
|
54448
|
+
pullRequestUrl: typeof body?.html_url === "string" ? body.html_url : null
|
|
54449
|
+
};
|
|
54450
|
+
return { ok: true, outcome };
|
|
54451
|
+
}
|
|
54452
|
+
};
|
|
54453
|
+
}
|
|
54454
|
+
async function safeText(response) {
|
|
54455
|
+
try {
|
|
54456
|
+
const text3 = await response.text();
|
|
54457
|
+
return text3.replace(/\s+/g, " ").slice(0, 200);
|
|
54458
|
+
} catch {
|
|
54459
|
+
return "no response body";
|
|
54460
|
+
}
|
|
54461
|
+
}
|
|
54462
|
+
|
|
54463
|
+
// ../daemon/src/lib/publication/host/local.ts
|
|
54464
|
+
function createLocalAdapter(input) {
|
|
54465
|
+
return {
|
|
54466
|
+
remoteUrl(target) {
|
|
54467
|
+
if (!target.repository.startsWith("/")) {
|
|
54468
|
+
return {
|
|
54469
|
+
ok: false,
|
|
54470
|
+
reason: "origin_not_configured",
|
|
54471
|
+
detail: `a local publication needs an absolute repository path, got: ${target.repository}`
|
|
54472
|
+
};
|
|
54473
|
+
}
|
|
54474
|
+
void input.credentialPresent;
|
|
54475
|
+
return { ok: true, url: target.repository };
|
|
54476
|
+
},
|
|
54477
|
+
async openPullRequest() {
|
|
54478
|
+
return {
|
|
54479
|
+
ok: true,
|
|
54480
|
+
outcome: { pullRequestNumber: null, pullRequestUrl: null }
|
|
54481
|
+
};
|
|
54482
|
+
}
|
|
54483
|
+
};
|
|
54484
|
+
}
|
|
54485
|
+
|
|
54486
|
+
// ../daemon/src/lib/publication/execute.ts
|
|
54487
|
+
var PUBLICATION_LEASE_MS = 2 * 60 * 1e3;
|
|
54488
|
+
var PUBLICATION_OWNER = `publication-${process.pid}`;
|
|
54489
|
+
async function executePublication(db, paths2, authToken, publicationId, opts = {}) {
|
|
54490
|
+
const claimed = claimPublication(db, {
|
|
54491
|
+
id: publicationId,
|
|
54492
|
+
leaseOwner: PUBLICATION_OWNER,
|
|
54493
|
+
leaseMs: opts.leaseMs ?? PUBLICATION_LEASE_MS,
|
|
54494
|
+
...opts.now !== void 0 ? { now: opts.now } : {}
|
|
54495
|
+
});
|
|
54496
|
+
if (!claimed) return "not_claimed";
|
|
54497
|
+
const refuse = (reason, detail3) => {
|
|
54498
|
+
refusePublication(db, {
|
|
54499
|
+
id: claimed.id,
|
|
54500
|
+
reason,
|
|
54501
|
+
detail: detail3.slice(0, 400),
|
|
54502
|
+
...opts.now !== void 0 ? { now: opts.now } : {}
|
|
54503
|
+
});
|
|
54504
|
+
return "refused";
|
|
54505
|
+
};
|
|
54506
|
+
const packet = getReviewPacket(db, claimed.packetId);
|
|
54507
|
+
if (!packet) return refuse("packet_unknown", "the review packet is gone");
|
|
54508
|
+
const files = readReviewedRevisionFiles(db, paths2, packet);
|
|
54509
|
+
if (!files.ok) return refuse(files.reason, files.detail);
|
|
54510
|
+
const resolved = resolvePublicationTarget(db, authToken);
|
|
54511
|
+
if (!resolved.ok) return refuse(resolved.reason, resolved.detail);
|
|
54512
|
+
const adapter = opts.adapter ?? adapterFor(resolved.target.host, resolved.target.credential);
|
|
54513
|
+
const hostTarget = {
|
|
54514
|
+
host: resolved.target.host,
|
|
54515
|
+
repository: resolved.target.repository,
|
|
54516
|
+
baseBranch: claimed.baseBranch,
|
|
54517
|
+
headBranch: claimed.headBranch,
|
|
54518
|
+
commitMessage: claimed.commitMessage,
|
|
54519
|
+
title: claimed.commitMessage,
|
|
54520
|
+
body: publicationBody(claimed, packet.summary)
|
|
54521
|
+
};
|
|
54522
|
+
const remote = adapter.remoteUrl(hostTarget);
|
|
54523
|
+
if (!remote.ok) return refuse(remote.reason, remote.detail);
|
|
54524
|
+
const pushed = await publishRevisionCommit({
|
|
54525
|
+
teamDir: paths2.teamDir(claimed.teamId),
|
|
54526
|
+
baseOid: claimed.baseOid,
|
|
54527
|
+
headBranch: claimed.headBranch,
|
|
54528
|
+
commitMessage: claimed.commitMessage,
|
|
54529
|
+
files: files.files,
|
|
54530
|
+
removed: files.removed,
|
|
54531
|
+
remoteUrl: remote.url,
|
|
54532
|
+
credential: resolved.target.credential,
|
|
54533
|
+
...opts.scratchParentDir ? { scratchParentDir: opts.scratchParentDir } : {}
|
|
54534
|
+
});
|
|
54535
|
+
if (!pushed.ok) {
|
|
54536
|
+
return refuse(pushed.reason, pushed.detail);
|
|
54537
|
+
}
|
|
54538
|
+
const opened = await adapter.openPullRequest(hostTarget);
|
|
54539
|
+
const settled = settlePublicationPublished(db, {
|
|
54540
|
+
id: claimed.id,
|
|
54541
|
+
commitOid: pushed.commitOid,
|
|
54542
|
+
pullRequestNumber: opened.ok ? opened.outcome.pullRequestNumber : null,
|
|
54543
|
+
pullRequestUrl: opened.ok ? opened.outcome.pullRequestUrl : null,
|
|
54544
|
+
...opts.now !== void 0 ? { now: opts.now } : {}
|
|
54545
|
+
});
|
|
54546
|
+
if (!opened.ok) {
|
|
54547
|
+
noteBranchWithoutPullRequest(db, settled, opened.detail);
|
|
54548
|
+
}
|
|
54549
|
+
notifyOutcome(db, settled, opened.ok ? null : opened.detail);
|
|
54550
|
+
return "published";
|
|
54551
|
+
}
|
|
54552
|
+
function adapterFor(host2, credential) {
|
|
54553
|
+
return host2 === "github" ? createGitHubAdapter({ credential }) : createLocalAdapter({ credentialPresent: credential.length > 0 });
|
|
54554
|
+
}
|
|
54555
|
+
function publicationBody(publication, summary) {
|
|
54556
|
+
return [
|
|
54557
|
+
`Reviewed revision ${publication.snapshotId.slice(0, 12)} (base ${publication.baseOid.slice(0, 12)}).`,
|
|
54558
|
+
summary ? `
|
|
54559
|
+
${summary}` : "",
|
|
54560
|
+
"",
|
|
54561
|
+
"Published by Bazilion from a reviewed packet. The commit is unsigned.",
|
|
54562
|
+
"Nothing was merged or deployed."
|
|
54563
|
+
].join("\n").trim();
|
|
54564
|
+
}
|
|
54565
|
+
function noteBranchWithoutPullRequest(db, publication, detail3) {
|
|
54566
|
+
notePublicationError(
|
|
54567
|
+
db,
|
|
54568
|
+
publication.id,
|
|
54569
|
+
`the branch was published, but no pull request was opened: ${detail3}`
|
|
54570
|
+
);
|
|
54571
|
+
}
|
|
54572
|
+
function notifyOutcome(db, publication, detail3) {
|
|
54573
|
+
const to = publication.notifyAgentId;
|
|
54574
|
+
if (!to) return;
|
|
54575
|
+
const packet = getReviewPacket(db, publication.packetId);
|
|
54576
|
+
const from = packet?.reviewerAgentId;
|
|
54577
|
+
if (!from) return;
|
|
54578
|
+
const lines = [
|
|
54579
|
+
`Publication of ${publication.packetId}: ${publication.state}.`,
|
|
54580
|
+
`branch ${publication.headBranch}`,
|
|
54581
|
+
publication.commitOid ? `commit ${publication.commitOid}` : "",
|
|
54582
|
+
publication.pullRequestUrl ? `pull request ${publication.pullRequestUrl}` : "no pull request was opened",
|
|
54583
|
+
"The commit is unsigned, and nothing was merged or deployed.",
|
|
54584
|
+
detail3 ?? ""
|
|
54585
|
+
].filter((line) => line.length > 0);
|
|
54586
|
+
try {
|
|
54587
|
+
sendAgentMessage(db, {
|
|
54588
|
+
from,
|
|
54589
|
+
to,
|
|
54590
|
+
payload: lines.join("\n"),
|
|
54591
|
+
origin: "publication_result",
|
|
54592
|
+
attemptKind: "publication_result",
|
|
54593
|
+
attemptId: publication.id
|
|
54594
|
+
});
|
|
54595
|
+
} catch {
|
|
54596
|
+
}
|
|
54597
|
+
}
|
|
54598
|
+
|
|
54599
|
+
// ../daemon/src/lib/publication/report.ts
|
|
54600
|
+
function buildPublicationReport(publication) {
|
|
54601
|
+
const facts = {
|
|
54602
|
+
// Any non-refused row got this far only after every path's digest matched the capture.
|
|
54603
|
+
contentFromReviewedRevision: publication.state !== "refused",
|
|
54604
|
+
nothingSent: publication.state === "refused",
|
|
54605
|
+
pullRequestOpened: publication.pullRequestUrl !== null && publication.pullRequestNumber !== null,
|
|
54606
|
+
unsigned: !publication.signed
|
|
54607
|
+
};
|
|
54608
|
+
return { publication, facts, guidance: guidanceFor(publication) };
|
|
54609
|
+
}
|
|
54610
|
+
function guidanceFor(publication) {
|
|
54611
|
+
switch (publication.state) {
|
|
54612
|
+
case "pending":
|
|
54613
|
+
return "Nothing has been sent. Publishing commits the reviewed revision to a new branch and opens a pull request; it never merges or deploys.";
|
|
54614
|
+
case "publishing":
|
|
54615
|
+
return "An attempt is in progress. Until it settles, whether the branch reached the host is unknown.";
|
|
54616
|
+
case "published":
|
|
54617
|
+
return publication.pullRequestUrl ? "The branch is on the host and a pull request is open. Nothing was merged and nothing was deployed; those stay yours to report." : "The branch is on the host, but no pull request came back. Nothing was merged and nothing was deployed.";
|
|
54618
|
+
case "refused":
|
|
54619
|
+
return "Nothing was sent: no commit, no push, no pull request. Fix the reason below and publish again; the review itself is unchanged.";
|
|
54620
|
+
case "failed":
|
|
54621
|
+
return "The attempt ended without publishing. Nothing is known to be on the host, but check before retrying if the failure happened late.";
|
|
54622
|
+
case "uncertain":
|
|
54623
|
+
return "Whether the branch reached the host is unknown, so this is never retried automatically. Check the host first: a branch that is already there will make a retry refuse.";
|
|
54624
|
+
}
|
|
54625
|
+
}
|
|
54626
|
+
|
|
53756
54627
|
// ../daemon/src/lib/review/export.ts
|
|
53757
54628
|
var MAX_PATCH_BYTES = 2e5;
|
|
53758
54629
|
async function buildReviewExport(db, paths2, teamId, packetId) {
|
|
@@ -54010,11 +54881,11 @@ function renderExportDocument(exported) {
|
|
|
54010
54881
|
}
|
|
54011
54882
|
|
|
54012
54883
|
// ../daemon/src/lib/review/file-link.ts
|
|
54013
|
-
import { execFile as
|
|
54884
|
+
import { execFile as execFile3 } from "child_process";
|
|
54014
54885
|
import { hostname } from "os";
|
|
54015
|
-
import { isAbsolute as isAbsolute10, join as
|
|
54016
|
-
import { promisify } from "util";
|
|
54017
|
-
var
|
|
54886
|
+
import { isAbsolute as isAbsolute10, join as join38 } from "path";
|
|
54887
|
+
import { promisify as promisify2 } from "util";
|
|
54888
|
+
var execFileAsync2 = promisify2(execFile3);
|
|
54018
54889
|
var EDITOR_TEMPLATE_ENV = "BAZILION_REVIEW_EDITOR";
|
|
54019
54890
|
var EDITOR_MAP_ENV = "BAZILION_REVIEW_EDITOR_MAP";
|
|
54020
54891
|
function buildFileLink(input) {
|
|
@@ -54025,7 +54896,7 @@ function buildFileLink(input) {
|
|
|
54025
54896
|
const known = revision4.ok && revision4.changes.some((change) => change.path === input.path);
|
|
54026
54897
|
const line = input.line !== null && input.line >= 1 ? input.line : null;
|
|
54027
54898
|
const copyTarget = line === null ? input.path : `${input.path}:${line}`;
|
|
54028
|
-
const hostPath = known ?
|
|
54899
|
+
const hostPath = known ? join38(team.path, input.path) : null;
|
|
54029
54900
|
const template = env[EDITOR_TEMPLATE_ENV]?.trim();
|
|
54030
54901
|
const mapped = hostPath ? mapHostPath(hostPath, env[EDITOR_MAP_ENV]) : null;
|
|
54031
54902
|
if (!known) {
|
|
@@ -54079,7 +54950,7 @@ async function openFileLink(link) {
|
|
|
54079
54950
|
const [command, ...args] = argv;
|
|
54080
54951
|
if (!command) return { opened: false, detail: "the configured editor command is empty" };
|
|
54081
54952
|
try {
|
|
54082
|
-
await
|
|
54953
|
+
await execFileAsync2(command, args, { timeout: 1e4 });
|
|
54083
54954
|
return { opened: true, detail: `ran ${command} on ${link.hostPath} (daemon host)` };
|
|
54084
54955
|
} catch (error2) {
|
|
54085
54956
|
return {
|
|
@@ -54276,6 +55147,7 @@ teamsRouter.post("/:id/reviews/:packetId/findings", async (c) => {
|
|
|
54276
55147
|
return c.json({ error: "The path is outside the reviewed scope", code: "invalid_path" }, 400);
|
|
54277
55148
|
}
|
|
54278
55149
|
try {
|
|
55150
|
+
const availability = await readRevisionContentAvailability(db, paths2, packet);
|
|
54279
55151
|
const finding = addReviewFinding(db, {
|
|
54280
55152
|
packetId,
|
|
54281
55153
|
authorKind: "operator",
|
|
@@ -54285,7 +55157,8 @@ teamsRouter.post("/:id/reviews/:packetId/findings", async (c) => {
|
|
|
54285
55157
|
lineStart: readLine(body.lineStart),
|
|
54286
55158
|
lineEnd: readLine(body.lineEnd),
|
|
54287
55159
|
// The finding is about the revision this packet captured — not about whatever is on disk now.
|
|
54288
|
-
snapshotId: packet.snapshotId
|
|
55160
|
+
snapshotId: packet.snapshotId,
|
|
55161
|
+
state: availability.contentAvailable ? "open" : "unverified"
|
|
54289
55162
|
});
|
|
54290
55163
|
const report2 = await readReviewPacketReport(db, paths2, packet.teamId, packetId);
|
|
54291
55164
|
return c.json({ finding, report: report2 }, 201);
|
|
@@ -54610,14 +55483,14 @@ teamsRouter.put("/:id/coding-environment", async (c) => {
|
|
|
54610
55483
|
return c.json({ error: "Invalid coding environment request" }, 400);
|
|
54611
55484
|
const request2 = body;
|
|
54612
55485
|
try {
|
|
54613
|
-
const
|
|
55486
|
+
const environment2 = await configureTeamCodingEnvironment(
|
|
54614
55487
|
db,
|
|
54615
55488
|
team,
|
|
54616
55489
|
request2.expectedRevision,
|
|
54617
55490
|
request2.config
|
|
54618
55491
|
);
|
|
54619
55492
|
c.header("Cache-Control", "no-store");
|
|
54620
|
-
return c.json(
|
|
55493
|
+
return c.json(environment2);
|
|
54621
55494
|
} catch (error2) {
|
|
54622
55495
|
if (error2 instanceof WorkspaceBusyError)
|
|
54623
55496
|
return c.json({ error: error2.message, code: error2.message }, 409);
|
|
@@ -54697,12 +55570,12 @@ teamsRouter.get("/:id/policy/blocks", (c) => {
|
|
|
54697
55570
|
WHERE ${filters.join(" AND ")}
|
|
54698
55571
|
ORDER BY created_at DESC, id DESC LIMIT ?`
|
|
54699
55572
|
).all(...params);
|
|
54700
|
-
const page = rows.slice(0, limit).map((
|
|
54701
|
-
...
|
|
54702
|
-
policyRefs: JSON.parse(String(
|
|
54703
|
-
componentOutcomes: JSON.parse(String(
|
|
54704
|
-
matchedEdgeIds: JSON.parse(String(
|
|
54705
|
-
requiredEdgeIds: JSON.parse(String(
|
|
55573
|
+
const page = rows.slice(0, limit).map((row2) => ({
|
|
55574
|
+
...row2,
|
|
55575
|
+
policyRefs: JSON.parse(String(row2.policy_refs_json)),
|
|
55576
|
+
componentOutcomes: JSON.parse(String(row2.component_outcomes_json)),
|
|
55577
|
+
matchedEdgeIds: JSON.parse(String(row2.matched_edge_ids_json)),
|
|
55578
|
+
requiredEdgeIds: JSON.parse(String(row2.required_edge_ids_json)),
|
|
54706
55579
|
policy_refs_json: void 0,
|
|
54707
55580
|
component_outcomes_json: void 0,
|
|
54708
55581
|
matched_edge_ids_json: void 0,
|
|
@@ -54906,7 +55779,7 @@ async function openMemory(rawId) {
|
|
|
54906
55779
|
const { db, paths: paths2 } = getCtx();
|
|
54907
55780
|
const team = teams_exports.get(db, rawId, paths2);
|
|
54908
55781
|
if (!team) throw new TeamMemoryNotFoundError(`team not found: ${rawId}`);
|
|
54909
|
-
const mem = qmdBackend(
|
|
55782
|
+
const mem = qmdBackend(join39(team.path, "memory"));
|
|
54910
55783
|
await mem.init();
|
|
54911
55784
|
return { mem, team };
|
|
54912
55785
|
}
|
|
@@ -55074,6 +55947,93 @@ teamsRouter.post("/:id/verifications/:requestId/cancel", async (c) => {
|
|
|
55074
55947
|
async function report(db, paths2, record3) {
|
|
55075
55948
|
return readVerificationReport(db, paths2, record3.teamId, record3.id);
|
|
55076
55949
|
}
|
|
55950
|
+
teamsRouter.get("/:id/publications", async (c) => {
|
|
55951
|
+
const { db, paths: paths2 } = getCtx();
|
|
55952
|
+
c.header("Cache-Control", "no-store");
|
|
55953
|
+
try {
|
|
55954
|
+
const team = requireTeam(db, paths2, c.req.param("id"));
|
|
55955
|
+
return c.json({ publications: listPublications(db, team.id).map(toWirePublication) });
|
|
55956
|
+
} catch (error2) {
|
|
55957
|
+
return reviewFailure(c, error2);
|
|
55958
|
+
}
|
|
55959
|
+
});
|
|
55960
|
+
teamsRouter.post("/:id/publications", async (c) => {
|
|
55961
|
+
const { db, paths: paths2, authToken } = getCtx();
|
|
55962
|
+
c.header("Cache-Control", "no-store");
|
|
55963
|
+
const body = await c.req.json().catch(() => null);
|
|
55964
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) {
|
|
55965
|
+
return c.json({ error: "Invalid publication request" }, 400);
|
|
55966
|
+
}
|
|
55967
|
+
const input = body;
|
|
55968
|
+
if (typeof input.packetId !== "string") {
|
|
55969
|
+
return c.json({ error: "Invalid publication request" }, 400);
|
|
55970
|
+
}
|
|
55971
|
+
if (input.headBranch !== void 0 && typeof input.headBranch !== "string") {
|
|
55972
|
+
return c.json({ error: "Invalid publication request" }, 400);
|
|
55973
|
+
}
|
|
55974
|
+
if (input.commitMessage !== void 0 && typeof input.commitMessage !== "string") {
|
|
55975
|
+
return c.json({ error: "Invalid publication request" }, 400);
|
|
55976
|
+
}
|
|
55977
|
+
try {
|
|
55978
|
+
const team = requireTeam(db, paths2, c.req.param("id"));
|
|
55979
|
+
const captured = await capturePublication(db, paths2, authToken, {
|
|
55980
|
+
teamId: team.id,
|
|
55981
|
+
packetId: input.packetId,
|
|
55982
|
+
...typeof input.headBranch === "string" ? { headBranch: input.headBranch } : {},
|
|
55983
|
+
...typeof input.commitMessage === "string" ? { commitMessage: input.commitMessage } : {}
|
|
55984
|
+
});
|
|
55985
|
+
if (captured.kind === "refused") {
|
|
55986
|
+
return c.json({ blocked: { reason: captured.reason, detail: captured.detail } }, 409);
|
|
55987
|
+
}
|
|
55988
|
+
await executePublication(db, paths2, authToken, captured.publication.id);
|
|
55989
|
+
const settled = getPublication(db, captured.publication.id);
|
|
55990
|
+
if (!settled) return c.json({ error: "Publication not found" }, 404);
|
|
55991
|
+
return c.json({ report: buildPublicationReport(settled) }, 201);
|
|
55992
|
+
} catch (error2) {
|
|
55993
|
+
if (error2 instanceof PublicationError) {
|
|
55994
|
+
return c.json({ blocked: { reason: error2.code, detail: error2.message } }, 409);
|
|
55995
|
+
}
|
|
55996
|
+
return reviewFailure(c, error2);
|
|
55997
|
+
}
|
|
55998
|
+
});
|
|
55999
|
+
teamsRouter.get("/:id/publications/:publicationId", async (c) => {
|
|
56000
|
+
const { db, paths: paths2 } = getCtx();
|
|
56001
|
+
c.header("Cache-Control", "no-store");
|
|
56002
|
+
try {
|
|
56003
|
+
const team = requireTeam(db, paths2, c.req.param("id"));
|
|
56004
|
+
const publication = getPublication(db, c.req.param("publicationId"));
|
|
56005
|
+
if (!publication || publication.teamId !== team.id) {
|
|
56006
|
+
return c.json({ error: "Publication not found" }, 404);
|
|
56007
|
+
}
|
|
56008
|
+
return c.json({ report: buildPublicationReport(publication) });
|
|
56009
|
+
} catch (error2) {
|
|
56010
|
+
return reviewFailure(c, error2);
|
|
56011
|
+
}
|
|
56012
|
+
});
|
|
56013
|
+
function toWirePublication(record3) {
|
|
56014
|
+
return {
|
|
56015
|
+
id: record3.id,
|
|
56016
|
+
teamId: record3.teamId,
|
|
56017
|
+
packetId: record3.packetId,
|
|
56018
|
+
snapshotId: record3.snapshotId,
|
|
56019
|
+
host: record3.host,
|
|
56020
|
+
repository: record3.repository,
|
|
56021
|
+
baseBranch: record3.baseBranch,
|
|
56022
|
+
headBranch: record3.headBranch,
|
|
56023
|
+
baseOid: record3.baseOid,
|
|
56024
|
+
commitMessage: record3.commitMessage,
|
|
56025
|
+
state: record3.state,
|
|
56026
|
+
signed: record3.signed,
|
|
56027
|
+
commitOid: record3.commitOid,
|
|
56028
|
+
pullRequestNumber: record3.pullRequestNumber,
|
|
56029
|
+
pullRequestUrl: record3.pullRequestUrl,
|
|
56030
|
+
refusalReason: record3.refusalReason,
|
|
56031
|
+
refusalDetail: record3.refusalDetail,
|
|
56032
|
+
error: record3.error,
|
|
56033
|
+
createdAt: record3.createdAt,
|
|
56034
|
+
finishedAt: record3.finishedAt
|
|
56035
|
+
};
|
|
56036
|
+
}
|
|
55077
56037
|
|
|
55078
56038
|
// ../daemon/src/routes/telegram.ts
|
|
55079
56039
|
import { Hono as Hono19 } from "hono";
|