sentinelayer-cli 0.30.0 → 0.30.1
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/package.json
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import fsp from "node:fs/promises";
|
|
11
11
|
import path from "node:path";
|
|
12
12
|
import crypto from "node:crypto";
|
|
13
|
+
import { spawnSync } from "node:child_process";
|
|
13
14
|
|
|
14
15
|
import { recordProvisionedIdentity } from "../ai/identity-store.js";
|
|
15
16
|
import { runDevTestBotSession } from "../agents/devtestbot/tool.js";
|
|
@@ -67,6 +68,26 @@ function parsePlannerJson(text) {
|
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
70
|
|
|
71
|
+
// Derive a stable repo key for the managed-proxy DD entitlement gate (#94651):
|
|
72
|
+
// owner/repo from the git remote when present, else a non-identifying local key
|
|
73
|
+
// (hash of the absolute repo root — no raw path leak). Fail-safe to the local key.
|
|
74
|
+
function deriveRepoKey(rootPath) {
|
|
75
|
+
try {
|
|
76
|
+
const remote = spawnSync("git", ["-C", rootPath || ".", "remote", "get-url", "origin"], {
|
|
77
|
+
encoding: "utf-8",
|
|
78
|
+
});
|
|
79
|
+
if (remote.status === 0) {
|
|
80
|
+
const url = String(remote.stdout || "").trim();
|
|
81
|
+
const match = url.match(/[:/]([^/:]+\/[^/]+?)(?:\.git)?$/);
|
|
82
|
+
if (match && match[1]) return match[1].toLowerCase();
|
|
83
|
+
}
|
|
84
|
+
} catch {
|
|
85
|
+
// fall through to the local key
|
|
86
|
+
}
|
|
87
|
+
const abs = path.resolve(rootPath || ".");
|
|
88
|
+
return `local/${crypto.createHash("sha256").update(abs).digest("hex").slice(0, 12)}`;
|
|
89
|
+
}
|
|
90
|
+
|
|
70
91
|
function buildPlannerPrompt({ rootPath, files = [], findings = [], budget = {} }) {
|
|
71
92
|
const severityCounts = {};
|
|
72
93
|
for (const finding of findings || []) {
|
|
@@ -86,9 +107,22 @@ function buildPlannerPrompt({ rootPath, files = [], findings = [], budget = {} }
|
|
|
86
107
|
].join("\n");
|
|
87
108
|
}
|
|
88
109
|
|
|
89
|
-
async function callPlannerClient({ plannerClient, rootPath, files, findings, budget, sessionUsage }) {
|
|
110
|
+
export async function callPlannerClient({ plannerClient, rootPath, files, findings, budget, sessionUsage }) {
|
|
90
111
|
if (!plannerClient) return { planned: {}, usageLedger: null };
|
|
91
112
|
const prompt = buildPlannerPrompt({ rootPath, files, findings, budget });
|
|
113
|
+
// DD entitlement gate metadata (#94651): only label proxy calls when there
|
|
114
|
+
// is a real session usage anchor. API-side DD actions are fail-closed and
|
|
115
|
+
// reject incomplete session context before provider spend.
|
|
116
|
+
const sessionId = String(sessionUsage?.sessionId || "").trim();
|
|
117
|
+
const ddProxyFields = sessionId
|
|
118
|
+
? {
|
|
119
|
+
action: INVESTOR_DD_USAGE_ACTIONS.devTestBotPlanner,
|
|
120
|
+
sessionId,
|
|
121
|
+
agentId: "investor-dd-devtestbot-planner",
|
|
122
|
+
usageIdempotencyKey: `investor-dd-devtestbot-${crypto.randomUUID()}`,
|
|
123
|
+
metadata: { repoKey: deriveRepoKey(rootPath), phase: "devtestbot" },
|
|
124
|
+
}
|
|
125
|
+
: {};
|
|
92
126
|
if (typeof plannerClient.decideDevTestBotPhase === "function") {
|
|
93
127
|
return {
|
|
94
128
|
planned: await plannerClient.decideDevTestBotPhase({ rootPath, files, findings, budget, prompt }),
|
|
@@ -105,7 +139,7 @@ async function callPlannerClient({ plannerClient, rootPath, files, findings, bud
|
|
|
105
139
|
}
|
|
106
140
|
const startedAtIso = new Date().toISOString();
|
|
107
141
|
if (typeof plannerClient.invoke === "function") {
|
|
108
|
-
const response = await plannerClient.invoke({ prompt, stream: false });
|
|
142
|
+
const response = await plannerClient.invoke({ prompt, stream: false, ...ddProxyFields });
|
|
109
143
|
const usageLedger = sessionUsage
|
|
110
144
|
? await recordInvestorDdLlmUsage({
|
|
111
145
|
usageContext: sessionUsage,
|
|
@@ -128,6 +162,7 @@ async function callPlannerClient({ plannerClient, rootPath, files, findings, bud
|
|
|
128
162
|
if (typeof plannerClient.generatePlan === "function") {
|
|
129
163
|
const response = await plannerClient.generatePlan([{ role: "user", content: prompt }], {
|
|
130
164
|
phase: "devtestbot",
|
|
165
|
+
...ddProxyFields,
|
|
131
166
|
});
|
|
132
167
|
const usageLedger = sessionUsage
|
|
133
168
|
? await recordInvestorDdLlmUsage({
|