@moda-ai/cli 1.55.10 → 1.55.11
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/agent-n0ch2j90.js +459 -0
- package/dist/cli-11fevr8y.js +811 -0
- package/dist/{cli-0qnghzg4.js → cli-429zt7g4.js} +1 -65
- package/dist/cli-4qe6n8am.js +345 -0
- package/dist/cli-97fnztpy.js +140 -0
- package/dist/{cli-d3c95kks.js → cli-fq7kk77e.js} +18 -1733
- package/dist/cli-fwec3m42.js +946 -0
- package/dist/cli-g7ferymy.js +496 -0
- package/dist/cli-k5qqj2bp.js +70 -0
- package/dist/cli-m16taf4z.js +30 -0
- package/dist/{cli-v27q5dvh.js → cli-m857n028.js} +189 -970
- package/dist/{cli-7s48d6ty.js → cli-n9gexgma.js} +2 -2
- package/dist/{cli-4f0p8erk.js → cli-t4jjhn3g.js} +5 -7
- package/dist/cli-tmqd1f0m.js +159 -0
- package/dist/cli.js +1409 -6991
- package/dist/doctor-spvy2zb3.js +23 -0
- package/dist/fix-ax6bbg37.js +1444 -0
- package/dist/{harness-github-actions-wpkr7jjr.js → harness-github-actions-mtksqp3c.js} +7 -2
- package/dist/{harness-0tnqw849.js → harness-jbqpbp6n.js} +7 -2
- package/dist/{index-jqexf7kn.js → index-2d0q94sv.js} +31 -20
- package/dist/production-intelligence-1tf98n79.js +1802 -0
- package/dist/profile-commands-f6599bcx.js +481 -0
- package/dist/prompt-source-mcp.js +7 -2
- package/dist/prompts-y3xd9heh.js +40 -0
- package/dist/{provision-5pkn25hh.js → provision-cjpsswa9.js} +7 -5
- package/dist/registry-1dvxsekd.js +1201 -0
- package/dist/skills-1k0hbkaf.js +19 -0
- package/dist/sync-by81xqk4.js +54 -0
- package/package.json +6 -6
- package/skills/integration/index.json +2 -2
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
stripAnsi
|
|
3
|
+
} from "./cli-97fnztpy.js";
|
|
4
|
+
import {
|
|
5
|
+
createCommandContext,
|
|
6
|
+
stringOption
|
|
7
|
+
} from "./cli-k5qqj2bp.js";
|
|
8
|
+
import {
|
|
9
|
+
assertFlags,
|
|
10
|
+
assertPositionals,
|
|
11
|
+
requireTenant
|
|
12
|
+
} from "./cli-g7ferymy.js";
|
|
13
|
+
import {
|
|
14
|
+
ApiError,
|
|
15
|
+
callControlAPI
|
|
16
|
+
} from "./cli-tmqd1f0m.js";
|
|
17
|
+
import {
|
|
3
18
|
CliInputError,
|
|
4
19
|
CliInputRequiredError,
|
|
5
20
|
DEFAULT_MAX_INVENTORY_FILES,
|
|
@@ -8,7 +23,6 @@ import {
|
|
|
8
23
|
MAX_SCANNED_FILE_BYTES,
|
|
9
24
|
SECRET_KEYS,
|
|
10
25
|
SKIPPED_DIRS,
|
|
11
|
-
createCommandContext,
|
|
12
26
|
embeddedTenantIdFromApiKey,
|
|
13
27
|
getActiveProfile,
|
|
14
28
|
isEvalLikePath,
|
|
@@ -21,13 +35,11 @@ import {
|
|
|
21
35
|
redactDeep,
|
|
22
36
|
redactString,
|
|
23
37
|
resolveApiKey,
|
|
24
|
-
resolveApiTenantId,
|
|
25
38
|
resolveIngestUrl,
|
|
26
39
|
resolveModaBaseUrl,
|
|
27
40
|
resolveTenantId,
|
|
28
|
-
shouldInventoryFile
|
|
29
|
-
|
|
30
|
-
} from "./cli-0qnghzg4.js";
|
|
41
|
+
shouldInventoryFile
|
|
42
|
+
} from "./cli-429zt7g4.js";
|
|
31
43
|
import {
|
|
32
44
|
__commonJS,
|
|
33
45
|
__require,
|
|
@@ -9456,7 +9468,7 @@ var require_typescript = __commonJS((exports, module) => {
|
|
|
9456
9468
|
commandLineOptionOfCustomType: () => commandLineOptionOfCustomType,
|
|
9457
9469
|
commentPragmas: () => commentPragmas,
|
|
9458
9470
|
commonOptionsWithBuild: () => commonOptionsWithBuild,
|
|
9459
|
-
compact: () =>
|
|
9471
|
+
compact: () => compact,
|
|
9460
9472
|
compareBooleans: () => compareBooleans,
|
|
9461
9473
|
compareDataObjects: () => compareDataObjects,
|
|
9462
9474
|
compareDiagnostics: () => compareDiagnostics,
|
|
@@ -11976,7 +11988,7 @@ var require_typescript = __commonJS((exports, module) => {
|
|
|
11976
11988
|
}
|
|
11977
11989
|
return true;
|
|
11978
11990
|
}
|
|
11979
|
-
function
|
|
11991
|
+
function compact(array) {
|
|
11980
11992
|
let result;
|
|
11981
11993
|
if (array !== undefined) {
|
|
11982
11994
|
for (let i = 0;i < array.length; i++) {
|
|
@@ -97633,7 +97645,7 @@ ${lanes.join(`
|
|
|
97633
97645
|
const savedPendingExpressions = pendingExpressions;
|
|
97634
97646
|
pendingExpressions = undefined;
|
|
97635
97647
|
node = factory2.updateBinaryExpression(node, visitNode(node.left, assignmentTargetVisitor, isExpression), node.operatorToken, visitNode(node.right, visitor, isExpression));
|
|
97636
|
-
const expr = some(pendingExpressions) ? factory2.inlineExpressions(
|
|
97648
|
+
const expr = some(pendingExpressions) ? factory2.inlineExpressions(compact([...pendingExpressions, node])) : node;
|
|
97637
97649
|
pendingExpressions = savedPendingExpressions;
|
|
97638
97650
|
return expr;
|
|
97639
97651
|
}
|
|
@@ -107437,14 +107449,14 @@ ${lanes.join(`
|
|
|
107437
107449
|
}
|
|
107438
107450
|
}
|
|
107439
107451
|
function createImportCallExpressionAMD(arg, containsLexicalThis) {
|
|
107440
|
-
const
|
|
107452
|
+
const resolve7 = factory2.createUniqueName("resolve");
|
|
107441
107453
|
const reject = factory2.createUniqueName("reject");
|
|
107442
107454
|
const parameters = [
|
|
107443
|
-
factory2.createParameterDeclaration(undefined, undefined,
|
|
107455
|
+
factory2.createParameterDeclaration(undefined, undefined, resolve7),
|
|
107444
107456
|
factory2.createParameterDeclaration(undefined, undefined, reject)
|
|
107445
107457
|
];
|
|
107446
107458
|
const body = factory2.createBlock([
|
|
107447
|
-
factory2.createExpressionStatement(factory2.createCallExpression(factory2.createIdentifier("require"), undefined, [factory2.createArrayLiteralExpression([arg || factory2.createOmittedExpression()]),
|
|
107459
|
+
factory2.createExpressionStatement(factory2.createCallExpression(factory2.createIdentifier("require"), undefined, [factory2.createArrayLiteralExpression([arg || factory2.createOmittedExpression()]), resolve7, reject]))
|
|
107448
107460
|
]);
|
|
107449
107461
|
let func;
|
|
107450
107462
|
if (languageVersion >= 2) {
|
|
@@ -110425,7 +110437,7 @@ ${lanes.join(`
|
|
|
110425
110437
|
let parameterProperties;
|
|
110426
110438
|
if (ctor) {
|
|
110427
110439
|
const oldDiag2 = getSymbolAccessibilityDiagnostic;
|
|
110428
|
-
parameterProperties =
|
|
110440
|
+
parameterProperties = compact(flatMap(ctor.parameters, (param) => {
|
|
110429
110441
|
if (!hasSyntacticModifier(param, 31) || shouldStripInternal(param))
|
|
110430
110442
|
return;
|
|
110431
110443
|
getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(param);
|
|
@@ -141758,7 +141770,7 @@ ${newComment.split(`
|
|
|
141758
141770
|
}
|
|
141759
141771
|
const checker = context.program.getTypeChecker();
|
|
141760
141772
|
const trackChanges = (cb) => ts_textChanges_exports.ChangeTracker.with(context, cb);
|
|
141761
|
-
return
|
|
141773
|
+
return compact([
|
|
141762
141774
|
getDeclarationSiteFix(context, expression, errorCode, checker, trackChanges),
|
|
141763
141775
|
getUseSiteFix(context, expression, errorCode, checker, trackChanges)
|
|
141764
141776
|
]);
|
|
@@ -160752,7 +160764,7 @@ ${content}
|
|
|
160752
160764
|
const lastToken = last(children);
|
|
160753
160765
|
const separateLastToken = separateTrailingSemicolon && lastToken.kind === 27;
|
|
160754
160766
|
const rightChildren = children.slice(splitTokenIndex + 1, separateLastToken ? children.length - 1 : undefined);
|
|
160755
|
-
const result =
|
|
160767
|
+
const result = compact([
|
|
160756
160768
|
leftChildren.length ? createSyntaxList2(leftChildren) : undefined,
|
|
160757
160769
|
splitToken,
|
|
160758
160770
|
rightChildren.length ? createSyntaxList2(rightChildren) : undefined
|
|
@@ -165456,7 +165468,7 @@ ${options.prefix}` : `
|
|
|
165456
165468
|
commandLineOptionOfCustomType: () => commandLineOptionOfCustomType,
|
|
165457
165469
|
commentPragmas: () => commentPragmas,
|
|
165458
165470
|
commonOptionsWithBuild: () => commonOptionsWithBuild,
|
|
165459
|
-
compact: () =>
|
|
165471
|
+
compact: () => compact,
|
|
165460
165472
|
compareBooleans: () => compareBooleans,
|
|
165461
165473
|
compareDataObjects: () => compareDataObjects,
|
|
165462
165474
|
compareDiagnostics: () => compareDiagnostics,
|
|
@@ -177619,8 +177631,8 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
|
|
|
177619
177631
|
installPackage(options) {
|
|
177620
177632
|
this.packageInstallId++;
|
|
177621
177633
|
const request = { kind: "installPackage", ...options, id: this.packageInstallId };
|
|
177622
|
-
const promise = new Promise((
|
|
177623
|
-
(this.packageInstalledPromise ?? (this.packageInstalledPromise = /* @__PURE__ */ new Map)).set(this.packageInstallId, { resolve:
|
|
177634
|
+
const promise = new Promise((resolve7, reject) => {
|
|
177635
|
+
(this.packageInstalledPromise ?? (this.packageInstalledPromise = /* @__PURE__ */ new Map)).set(this.packageInstallId, { resolve: resolve7, reject });
|
|
177624
177636
|
});
|
|
177625
177637
|
this.installer.send(request);
|
|
177626
177638
|
return promise;
|
|
@@ -177889,668 +177901,14 @@ import {
|
|
|
177889
177901
|
lstatSync as lstatSync10,
|
|
177890
177902
|
mkdtempSync as mkdtempSync2,
|
|
177891
177903
|
mkdirSync as mkdirSync6,
|
|
177892
|
-
readFileSync as
|
|
177904
|
+
readFileSync as readFileSync17,
|
|
177893
177905
|
readdirSync as readdirSync4,
|
|
177894
177906
|
writeFileSync as writeFileSync6,
|
|
177895
177907
|
rmSync as rmSync4
|
|
177896
177908
|
} from "node:fs";
|
|
177897
|
-
import { basename as basename7, delimiter, dirname as dirname9, join as join10, relative as relative8, resolve as
|
|
177909
|
+
import { basename as basename7, delimiter, dirname as dirname9, join as join10, relative as relative8, resolve as resolve13, sep as sep5 } from "node:path";
|
|
177898
177910
|
import { confirm as confirm2, select } from "@inquirer/prompts";
|
|
177899
177911
|
|
|
177900
|
-
// src/parity-commands.ts
|
|
177901
|
-
import { readFileSync } from "node:fs";
|
|
177902
|
-
import { resolve } from "node:path";
|
|
177903
|
-
|
|
177904
|
-
// src/api-key-headers.ts
|
|
177905
|
-
var PLATFORM_API_KEY_PREFIX = "moda_pk_";
|
|
177906
|
-
var TENANT_HEADER = "x-moda-tenant-id";
|
|
177907
|
-
function isPlatformApiKey(key) {
|
|
177908
|
-
return Boolean(key?.startsWith(PLATFORM_API_KEY_PREFIX));
|
|
177909
|
-
}
|
|
177910
|
-
var platformTenantOverride;
|
|
177911
|
-
function setPlatformTenantOverride(tenantId) {
|
|
177912
|
-
platformTenantOverride = tenantId;
|
|
177913
|
-
}
|
|
177914
|
-
var TENANT_PATH = /\/tenants\/([^/?#]+)/;
|
|
177915
|
-
function tenantFromUrl(url) {
|
|
177916
|
-
const match = url ? TENANT_PATH.exec(url) : null;
|
|
177917
|
-
return match ? decodeURIComponent(match[1]) : undefined;
|
|
177918
|
-
}
|
|
177919
|
-
function apiKeyHeaders(key, options = {}, url) {
|
|
177920
|
-
const headers = { "x-api-key": key };
|
|
177921
|
-
if (isPlatformApiKey(key)) {
|
|
177922
|
-
const tenantId = tenantFromUrl(url) || platformTenantOverride || resolveTenantId(options);
|
|
177923
|
-
if (tenantId)
|
|
177924
|
-
headers[TENANT_HEADER] = tenantId;
|
|
177925
|
-
}
|
|
177926
|
-
return headers;
|
|
177927
|
-
}
|
|
177928
|
-
|
|
177929
|
-
// src/api-client.ts
|
|
177930
|
-
var REQUEST_TIMEOUT_MS = 30000;
|
|
177931
|
-
var MAX_RETRIES = 3;
|
|
177932
|
-
var INITIAL_BACKOFF_MS = 500;
|
|
177933
|
-
var NETWORK_RETRY_DELAY_MS = 1000;
|
|
177934
|
-
|
|
177935
|
-
class ApiError extends Error {
|
|
177936
|
-
statusCode;
|
|
177937
|
-
responseBody;
|
|
177938
|
-
code;
|
|
177939
|
-
suggestions;
|
|
177940
|
-
readable;
|
|
177941
|
-
constructor(message, statusCode, responseBody) {
|
|
177942
|
-
const typed = parseTypedErrorBody(responseBody);
|
|
177943
|
-
const platform = platformFailure(responseBody);
|
|
177944
|
-
const readable = typed?.code === "audit_too_large" || platform !== null;
|
|
177945
|
-
super(readable ? `API error (${statusCode}): ${typed?.message ?? platform?.message}` : message);
|
|
177946
|
-
this.statusCode = statusCode;
|
|
177947
|
-
this.responseBody = responseBody;
|
|
177948
|
-
this.name = "ApiError";
|
|
177949
|
-
this.code = typed?.code ?? platform?.code;
|
|
177950
|
-
this.suggestions = typed?.suggestions;
|
|
177951
|
-
this.readable = readable;
|
|
177952
|
-
}
|
|
177953
|
-
}
|
|
177954
|
-
function parseTypedErrorBody(body) {
|
|
177955
|
-
if (!body.trimStart().startsWith("{"))
|
|
177956
|
-
return null;
|
|
177957
|
-
try {
|
|
177958
|
-
const parsed = JSON.parse(body);
|
|
177959
|
-
if (typeof parsed.code !== "string")
|
|
177960
|
-
return null;
|
|
177961
|
-
const suggestions = Array.isArray(parsed.suggestions) ? parsed.suggestions.filter((s) => typeof s === "string") : undefined;
|
|
177962
|
-
return {
|
|
177963
|
-
code: parsed.code,
|
|
177964
|
-
message: typeof parsed.message === "string" ? parsed.message : undefined,
|
|
177965
|
-
suggestions
|
|
177966
|
-
};
|
|
177967
|
-
} catch {
|
|
177968
|
-
return null;
|
|
177969
|
-
}
|
|
177970
|
-
}
|
|
177971
|
-
var DETERMINISTIC_PLATFORM_FAILURES = [
|
|
177972
|
-
"FUNCTION_INVOCATION_FAILED",
|
|
177973
|
-
"FUNCTION_RESPONSE_PAYLOAD_TOO_LARGE"
|
|
177974
|
-
];
|
|
177975
|
-
function platformFailure(body) {
|
|
177976
|
-
const code = DETERMINISTIC_PLATFORM_FAILURES.find((c) => body.includes(c));
|
|
177977
|
-
if (!code)
|
|
177978
|
-
return null;
|
|
177979
|
-
const requestId = /\b([a-z]{3}\d::[A-Za-z0-9:-]+)/.exec(body)?.[1];
|
|
177980
|
-
const cause = code === "FUNCTION_RESPONSE_PAYLOAD_TOO_LARGE" ? "the response was larger than the hosting platform allows" : "the server function crashed (typically out of memory or an oversized response)";
|
|
177981
|
-
return {
|
|
177982
|
-
code,
|
|
177983
|
-
message: `The Moda API could not complete this request: ${cause} [${code}` + `${requestId ? `, request ${requestId}` : ""}]. Retrying the same request will fail the same way; ` + "narrow it (a smaller --limit, a single trace, or fewer results) and report it with `moda feedback` if it persists."
|
|
177984
|
-
};
|
|
177985
|
-
}
|
|
177986
|
-
function isRetryableResponse(status, body) {
|
|
177987
|
-
if (!isRetryable(status))
|
|
177988
|
-
return false;
|
|
177989
|
-
return platformFailure(body) === null;
|
|
177990
|
-
}
|
|
177991
|
-
|
|
177992
|
-
class NetworkError extends Error {
|
|
177993
|
-
constructor(message) {
|
|
177994
|
-
super(message);
|
|
177995
|
-
this.name = "NetworkError";
|
|
177996
|
-
}
|
|
177997
|
-
}
|
|
177998
|
-
function networkErrorMessage(error, url) {
|
|
177999
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
178000
|
-
const cause = error instanceof Error ? error.cause : undefined;
|
|
178001
|
-
const code = typeof cause?.code === "string" ? `: ${cause.code}` : "";
|
|
178002
|
-
return `Network error: ${message} (could not reach ${url.split("?")[0]}${code})`;
|
|
178003
|
-
}
|
|
178004
|
-
function isRetryable(status) {
|
|
178005
|
-
return status === 429 || status >= 500;
|
|
178006
|
-
}
|
|
178007
|
-
async function callDataAPI(endpoint, init = { method: "GET" }, requestOptions = {}) {
|
|
178008
|
-
const url = `${resolveModaBaseUrl()}/api/v1/data${endpoint}`;
|
|
178009
|
-
return callModaAPI(url, init, {}, requestOptions);
|
|
178010
|
-
}
|
|
178011
|
-
async function callControlAPI(endpoint, options = {}, profileOptions = {}, requestOptions = {}) {
|
|
178012
|
-
const url = `${resolveModaBaseUrl(profileOptions)}/api${endpoint}`;
|
|
178013
|
-
return callModaAPI(url, options, profileOptions, requestOptions);
|
|
178014
|
-
}
|
|
178015
|
-
async function callModaAPI(url, options, profileOptions = {}, requestOptions = {}) {
|
|
178016
|
-
const timeoutMs = requestOptions.timeoutMs ?? REQUEST_TIMEOUT_MS;
|
|
178017
|
-
const method = (options.method ?? "GET").toUpperCase();
|
|
178018
|
-
const maxRetries = requestOptions.retries ?? (method === "GET" || method === "HEAD" ? MAX_RETRIES : 0);
|
|
178019
|
-
const initialNetworkRetryBudget = requestOptions.retryOnceOnNetworkError ? 1 : 0;
|
|
178020
|
-
let networkRetryBudget = initialNetworkRetryBudget;
|
|
178021
|
-
let connectionClose = false;
|
|
178022
|
-
const maxAttempts = maxRetries + initialNetworkRetryBudget + 1;
|
|
178023
|
-
for (let attempt = 0;attempt < maxAttempts; attempt++) {
|
|
178024
|
-
if (attempt > 0) {
|
|
178025
|
-
const backoff = connectionClose ? requestOptions.networkRetryDelayMs ?? NETWORK_RETRY_DELAY_MS : INITIAL_BACKOFF_MS * Math.pow(2, attempt - 1);
|
|
178026
|
-
await new Promise((resolve) => setTimeout(resolve, backoff));
|
|
178027
|
-
}
|
|
178028
|
-
const controller = new AbortController;
|
|
178029
|
-
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
178030
|
-
try {
|
|
178031
|
-
recordApiRequest();
|
|
178032
|
-
const response = await fetch(url, {
|
|
178033
|
-
...options,
|
|
178034
|
-
headers: {
|
|
178035
|
-
...apiKeyHeaders(resolveApiKey(profileOptions) ?? "", profileOptions, url),
|
|
178036
|
-
"Content-Type": "application/json",
|
|
178037
|
-
...options.headers ?? {},
|
|
178038
|
-
...connectionClose ? { Connection: "close" } : {}
|
|
178039
|
-
},
|
|
178040
|
-
signal: controller.signal
|
|
178041
|
-
});
|
|
178042
|
-
if (!response.ok) {
|
|
178043
|
-
const errorText = await response.text();
|
|
178044
|
-
const error = new ApiError(`API error (${response.status}): ${errorText}`, response.status, errorText);
|
|
178045
|
-
if (isRetryableResponse(response.status, errorText) && attempt < maxRetries) {
|
|
178046
|
-
continue;
|
|
178047
|
-
}
|
|
178048
|
-
throw error;
|
|
178049
|
-
}
|
|
178050
|
-
if (response.status === 204)
|
|
178051
|
-
return null;
|
|
178052
|
-
if (typeof response.text !== "function")
|
|
178053
|
-
return response.json();
|
|
178054
|
-
const text = await response.text();
|
|
178055
|
-
return text.trim() === "" ? null : JSON.parse(text);
|
|
178056
|
-
} catch (error) {
|
|
178057
|
-
if (error instanceof ApiError)
|
|
178058
|
-
throw error;
|
|
178059
|
-
const isAbort = error instanceof DOMException && error.name === "AbortError";
|
|
178060
|
-
const wrapped = isAbort ? new Error(`Request timed out after ${timeoutMs}ms: ${url}`) : new NetworkError(networkErrorMessage(error, url));
|
|
178061
|
-
if (attempt < maxRetries) {
|
|
178062
|
-
continue;
|
|
178063
|
-
}
|
|
178064
|
-
if (!isAbort && networkRetryBudget > 0) {
|
|
178065
|
-
networkRetryBudget -= 1;
|
|
178066
|
-
connectionClose = true;
|
|
178067
|
-
requestOptions.onNetworkRetry?.();
|
|
178068
|
-
continue;
|
|
178069
|
-
}
|
|
178070
|
-
throw wrapped;
|
|
178071
|
-
} finally {
|
|
178072
|
-
clearTimeout(timeout);
|
|
178073
|
-
}
|
|
178074
|
-
}
|
|
178075
|
-
throw new NetworkError(`Request retries exhausted: ${url}`);
|
|
178076
|
-
}
|
|
178077
|
-
|
|
178078
|
-
// src/parity-commands.ts
|
|
178079
|
-
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
178080
|
-
var WINDOWS = ["24h", "7d", "30d", "90d"];
|
|
178081
|
-
function profileOptions(context) {
|
|
178082
|
-
return { profile: context.profile, env: context.env };
|
|
178083
|
-
}
|
|
178084
|
-
function requireKey(context) {
|
|
178085
|
-
if (!resolveApiKey(profileOptions(context))) {
|
|
178086
|
-
throw new CliInputError(`No Moda API key found for moda ${context.command}.`, "Set MODA_API_KEY, run `moda auth login --api-key`, or select a profile with an API key.");
|
|
178087
|
-
}
|
|
178088
|
-
}
|
|
178089
|
-
function requireTenant(context) {
|
|
178090
|
-
const key = resolveApiKey(profileOptions(context));
|
|
178091
|
-
const keyTenant = key ? embeddedTenantIdFromApiKey(key) : undefined;
|
|
178092
|
-
const flagTenant = context.flags["tenant-id"];
|
|
178093
|
-
if (flagTenant && keyTenant && flagTenant !== keyTenant) {
|
|
178094
|
-
throw new CliInputError(`--tenant-id=${flagTenant} does not match this API key's tenant (${keyTenant}), so nothing was sent.`, "Drop --tenant-id (the key names its tenant) or use a key for that tenant.");
|
|
178095
|
-
}
|
|
178096
|
-
const tenantId = flagTenant || resolveApiTenantId(profileOptions(context));
|
|
178097
|
-
if (!tenantId) {
|
|
178098
|
-
throw new CliInputError("Could not determine the tenant.", "Use a signed API key (it names its tenant), set MODA_TENANT_ID, or pass --tenant-id=<id>.");
|
|
178099
|
-
}
|
|
178100
|
-
if (isPlatformApiKey(key))
|
|
178101
|
-
setPlatformTenantOverride(tenantId);
|
|
178102
|
-
return tenantId;
|
|
178103
|
-
}
|
|
178104
|
-
function assertFlags(command, flags, allowed) {
|
|
178105
|
-
if (command.startsWith("signals "))
|
|
178106
|
-
allowed = [...allowed, "tenant-id"];
|
|
178107
|
-
const globals = [
|
|
178108
|
-
"agent",
|
|
178109
|
-
"json",
|
|
178110
|
-
"human",
|
|
178111
|
-
"prose",
|
|
178112
|
-
"quiet",
|
|
178113
|
-
"verbose",
|
|
178114
|
-
"yes",
|
|
178115
|
-
"profile",
|
|
178116
|
-
"progress",
|
|
178117
|
-
"format",
|
|
178118
|
-
"no-telemetry",
|
|
178119
|
-
"no-update-check",
|
|
178120
|
-
"help",
|
|
178121
|
-
"version",
|
|
178122
|
-
"json-schemas",
|
|
178123
|
-
"stream",
|
|
178124
|
-
"no-stream",
|
|
178125
|
-
"tui",
|
|
178126
|
-
"no-tui"
|
|
178127
|
-
];
|
|
178128
|
-
const known = new Set([...allowed, ...globals]);
|
|
178129
|
-
const unknown = Object.keys(flags).filter((flag) => !known.has(flag));
|
|
178130
|
-
if (unknown.includes("dry-run")) {
|
|
178131
|
-
throw new CliInputError(`'moda ${command}' has no dry-run mode, so nothing was sent.`, "Remove --dry-run to run it for real.");
|
|
178132
|
-
}
|
|
178133
|
-
if (unknown.length > 0) {
|
|
178134
|
-
throw new CliInputError(`Unknown flag${unknown.length > 1 ? "s" : ""} ${unknown.map((flag) => `--${flag}`).join(", ")} for 'moda ${command}'.`, `Valid flags: ${allowed.map((flag) => `--${flag}`).join(", ") || "(none)"}.`);
|
|
178135
|
-
}
|
|
178136
|
-
}
|
|
178137
|
-
function assertPositionals(command, positionals, max, usage) {
|
|
178138
|
-
if (positionals.length > max) {
|
|
178139
|
-
throw new CliInputError(`Unexpected argument${positionals.length - max > 1 ? "s" : ""} '${positionals.slice(max).join(" ")}' for 'moda ${command}', so nothing was sent.`, `Usage: ${usage}`);
|
|
178140
|
-
}
|
|
178141
|
-
}
|
|
178142
|
-
function oneOf(name, value, allowed) {
|
|
178143
|
-
if (value === undefined)
|
|
178144
|
-
return;
|
|
178145
|
-
if (!allowed.includes(value)) {
|
|
178146
|
-
throw new CliInputError(`--${name} must be one of ${allowed.join(", ")} (got '${value}').`);
|
|
178147
|
-
}
|
|
178148
|
-
return value;
|
|
178149
|
-
}
|
|
178150
|
-
function csv(value) {
|
|
178151
|
-
if (value === undefined)
|
|
178152
|
-
return;
|
|
178153
|
-
const items = value.split(",").map((item) => item.trim()).filter(Boolean);
|
|
178154
|
-
return items.length > 0 ? items : undefined;
|
|
178155
|
-
}
|
|
178156
|
-
function readBodyFile(flags, cwd) {
|
|
178157
|
-
if (!flags.file)
|
|
178158
|
-
return {};
|
|
178159
|
-
if (flags.file === "true")
|
|
178160
|
-
throw new CliInputError("Missing path for --file.");
|
|
178161
|
-
let parsed;
|
|
178162
|
-
try {
|
|
178163
|
-
parsed = JSON.parse(readFileSync(resolve(cwd, flags.file), "utf8"));
|
|
178164
|
-
} catch (error) {
|
|
178165
|
-
throw new CliInputError(`Could not read --file ${flags.file}: ${error instanceof Error ? error.message : String(error)}`);
|
|
178166
|
-
}
|
|
178167
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
178168
|
-
throw new CliInputError("--file must contain a JSON object (the request body).");
|
|
178169
|
-
}
|
|
178170
|
-
return parsed;
|
|
178171
|
-
}
|
|
178172
|
-
function compact(value) {
|
|
178173
|
-
return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined));
|
|
178174
|
-
}
|
|
178175
|
-
var LLM_WRITE_TIMEOUT_MS = 180000;
|
|
178176
|
-
async function send(context, plane, method, endpoint, body, options = {}) {
|
|
178177
|
-
const init = { method, ...body !== undefined ? { body: JSON.stringify(body) } : {} };
|
|
178178
|
-
if (method !== "GET" && context.dryRun) {
|
|
178179
|
-
context.output.writeData({
|
|
178180
|
-
dryRun: true,
|
|
178181
|
-
planned: { method, endpoint: plane === "data" ? `/api/v1/data${endpoint}` : `/api${endpoint}`, ...body !== undefined ? { body } : {} }
|
|
178182
|
-
}, { summary: { text: `Dry run: would ${method} ${endpoint}. Nothing was sent.`, confidence: "high" } });
|
|
178183
|
-
return;
|
|
178184
|
-
}
|
|
178185
|
-
const requestOptions = method === "GET" ? {} : { retries: 0, ...options.slow ? { timeoutMs: LLM_WRITE_TIMEOUT_MS } : {} };
|
|
178186
|
-
const data = plane === "data" ? await callDataAPI(endpoint, init, requestOptions) : await callControlAPI(endpoint, init, profileOptions(context), requestOptions);
|
|
178187
|
-
context.output.writeData(data ?? { ok: true });
|
|
178188
|
-
}
|
|
178189
|
-
var USER_COHORTS = ["all", "power_users", "heavy_tool_users", "frustrated", "at_risk", "new_this_week", "silent_sufferers"];
|
|
178190
|
-
var USER_SORTS = ["last_seen", "health_score", "conversation_count", "frustration_max"];
|
|
178191
|
-
var HEALTH = ["healthy", "at_risk", "frustrated"];
|
|
178192
|
-
async function runUsersCommand(context) {
|
|
178193
|
-
const flags = context.flags;
|
|
178194
|
-
assertFlags("users", flags, [
|
|
178195
|
-
"window",
|
|
178196
|
-
"page",
|
|
178197
|
-
"page-size",
|
|
178198
|
-
"limit",
|
|
178199
|
-
"search",
|
|
178200
|
-
"cohort",
|
|
178201
|
-
"sort",
|
|
178202
|
-
"order",
|
|
178203
|
-
"health-status",
|
|
178204
|
-
"min-health",
|
|
178205
|
-
"max-health",
|
|
178206
|
-
"min-conversations",
|
|
178207
|
-
"min-tool-failures",
|
|
178208
|
-
"tenant-id"
|
|
178209
|
-
]);
|
|
178210
|
-
if (context.positionals.length > 0) {
|
|
178211
|
-
throw new CliInputError(`'moda users' takes no arguments. For one user use 'moda user <user_id>'.`);
|
|
178212
|
-
}
|
|
178213
|
-
if (flags.limit !== undefined && flags["page-size"] !== undefined && flags.limit !== flags["page-size"]) {
|
|
178214
|
-
throw new CliInputError(`Got --limit=${flags.limit} and --page-size=${flags["page-size"]}; they are the same flag for 'moda users', so nothing was sent.`, "Pass only one of --limit / --page-size.", "flag_conflict");
|
|
178215
|
-
}
|
|
178216
|
-
requireKey(context);
|
|
178217
|
-
const tenantId = requireTenant(context);
|
|
178218
|
-
const query = new URLSearchParams(compact({
|
|
178219
|
-
window: oneOf("window", flags.window, WINDOWS),
|
|
178220
|
-
page: flags.page,
|
|
178221
|
-
pageSize: flags["page-size"] ?? flags.limit,
|
|
178222
|
-
search: flags.search,
|
|
178223
|
-
cohort: oneOf("cohort", flags.cohort, USER_COHORTS),
|
|
178224
|
-
sortBy: oneOf("sort", flags.sort, USER_SORTS),
|
|
178225
|
-
sortOrder: oneOf("order", flags.order, ["asc", "desc"]),
|
|
178226
|
-
healthStatus: csv(flags["health-status"])?.map((value) => oneOf("health-status", value, HEALTH)).join(","),
|
|
178227
|
-
minHealthScore: flags["min-health"],
|
|
178228
|
-
maxHealthScore: flags["max-health"],
|
|
178229
|
-
minConversations: flags["min-conversations"],
|
|
178230
|
-
minToolFailures: flags["min-tool-failures"]
|
|
178231
|
-
}));
|
|
178232
|
-
const suffix = query.toString() ? `?${query.toString()}` : "";
|
|
178233
|
-
await send(context, "control", "GET", `/tenants/${encodeURIComponent(tenantId)}/users${suffix}`);
|
|
178234
|
-
return { exitCode: 0 };
|
|
178235
|
-
}
|
|
178236
|
-
async function runUserCommand(context) {
|
|
178237
|
-
const flags = context.flags;
|
|
178238
|
-
assertFlags("user", flags, ["window", "activity-cursor", "tenant-id"]);
|
|
178239
|
-
assertPositionals("user", context.positionals, 1, "moda user <user_id> [--window=24h|7d|30d|90d]");
|
|
178240
|
-
const userId = context.positionals[0];
|
|
178241
|
-
if (!userId)
|
|
178242
|
-
throw new CliInputError("<user_id> is required.", "Usage: moda user <user_id> [--window=24h|7d|30d|90d]");
|
|
178243
|
-
requireKey(context);
|
|
178244
|
-
const tenantId = requireTenant(context);
|
|
178245
|
-
const query = new URLSearchParams(compact({
|
|
178246
|
-
window: oneOf("window", flags.window, WINDOWS),
|
|
178247
|
-
activityCursor: flags["activity-cursor"]
|
|
178248
|
-
}));
|
|
178249
|
-
const suffix = query.toString() ? `?${query.toString()}` : "";
|
|
178250
|
-
await send(context, "control", "GET", `/tenants/${encodeURIComponent(tenantId)}/users/${encodeURIComponent(userId)}${suffix}`);
|
|
178251
|
-
return { exitCode: 0 };
|
|
178252
|
-
}
|
|
178253
|
-
async function runProblemReopenCommand(context) {
|
|
178254
|
-
assertFlags("problem-reopen", context.flags, ["reason", "dry-run"]);
|
|
178255
|
-
assertPositionals("problem-reopen", context.positionals, 1, "moda problem-reopen <problem_id> [--reason=TEXT]");
|
|
178256
|
-
const problemId = context.positionals[0];
|
|
178257
|
-
const usage = "Usage: moda problem-reopen <problem_id> [--reason=TEXT]";
|
|
178258
|
-
if (!problemId || !UUID_RE.test(problemId))
|
|
178259
|
-
throw new CliInputError("<problem_id> (UUID) is required.", usage);
|
|
178260
|
-
const reason = context.flags.reason;
|
|
178261
|
-
if (reason !== undefined && reason.length > 500)
|
|
178262
|
-
throw new CliInputError("--reason must be 500 characters or fewer.");
|
|
178263
|
-
requireKey(context);
|
|
178264
|
-
await send(context, "data", "POST", `/problems/${problemId}/reopen`, compact({ reason }));
|
|
178265
|
-
return { exitCode: 0 };
|
|
178266
|
-
}
|
|
178267
|
-
var SIGNAL_FIELD_FLAGS = [
|
|
178268
|
-
"name",
|
|
178269
|
-
"description",
|
|
178270
|
-
"pass-criteria",
|
|
178271
|
-
"fail-criteria",
|
|
178272
|
-
"polarity",
|
|
178273
|
-
"locus",
|
|
178274
|
-
"tool-names",
|
|
178275
|
-
"keyword-hints",
|
|
178276
|
-
"use-case-id",
|
|
178277
|
-
"message-types",
|
|
178278
|
-
"note",
|
|
178279
|
-
"file"
|
|
178280
|
-
];
|
|
178281
|
-
function signalBody(flags, cwd) {
|
|
178282
|
-
const fromFile = readBodyFile(flags, cwd);
|
|
178283
|
-
const scope = compact({
|
|
178284
|
-
toolNames: csv(flags["tool-names"]),
|
|
178285
|
-
keywordHints: csv(flags["keyword-hints"]),
|
|
178286
|
-
useCaseId: flags["use-case-id"],
|
|
178287
|
-
messageTypes: csv(flags["message-types"])
|
|
178288
|
-
});
|
|
178289
|
-
return {
|
|
178290
|
-
...fromFile,
|
|
178291
|
-
...compact({
|
|
178292
|
-
name: flags.name,
|
|
178293
|
-
description: flags.description,
|
|
178294
|
-
passCriteria: flags["pass-criteria"],
|
|
178295
|
-
failCriteria: flags["fail-criteria"],
|
|
178296
|
-
polarity: oneOf("polarity", flags.polarity, ["violation", "expectation"]),
|
|
178297
|
-
locus: oneOf("locus", flags.locus, ["agent", "tool_output", "user_input"]),
|
|
178298
|
-
note: flags.note
|
|
178299
|
-
}),
|
|
178300
|
-
...Object.keys(scope).length > 0 ? { scope: { ...fromFile.scope ?? {}, ...scope } } : {}
|
|
178301
|
-
};
|
|
178302
|
-
}
|
|
178303
|
-
var SIGNAL_USAGE = [
|
|
178304
|
-
"moda signals list custom signals",
|
|
178305
|
-
'moda signals draft --note="…" AI-draft criteria from a description',
|
|
178306
|
-
"moda signals create --name --description --pass-criteria --fail-criteria [--polarity --locus --tool-names=a,b] [--file=body.json]",
|
|
178307
|
-
"moda signals update <id> [same flags] edit a signal",
|
|
178308
|
-
"moda signals activate|pause|delete <id> (delete: drafts only; archive is dashboard-only)",
|
|
178309
|
-
"moda signals examples <id> add|update|remove --conversation-id=ID [--label=fits|does_not_fit --note --msg-index]",
|
|
178310
|
-
'moda signals refine <id> --request="…" propose a criteria edit',
|
|
178311
|
-
"moda signals revise <id> --conversation-ids=a,b re-derive criteria from labelled traces",
|
|
178312
|
-
"moda signals proposals <id> | accept <id> <proposal_id> | reject <id> <proposal_id>",
|
|
178313
|
-
"moda signals search <id> [--mode=wizard|full] | search-status <id> <search_id> | search-stop <id> <search_id>",
|
|
178314
|
-
"moda signals preview --file=detector.json [--conversation-ids=a,b --max-examples=N]",
|
|
178315
|
-
"All write subcommands accept --dry-run (prints the request, sends nothing)."
|
|
178316
|
-
].join(`
|
|
178317
|
-
`);
|
|
178318
|
-
async function runSignalsManagementCommand(sub, context) {
|
|
178319
|
-
const flags = context.flags;
|
|
178320
|
-
const args = context.positionals.slice(1);
|
|
178321
|
-
const arity = {
|
|
178322
|
-
draft: 0,
|
|
178323
|
-
create: 0,
|
|
178324
|
-
preview: 0,
|
|
178325
|
-
update: 1,
|
|
178326
|
-
activate: 1,
|
|
178327
|
-
pause: 1,
|
|
178328
|
-
delete: 1,
|
|
178329
|
-
examples: 2,
|
|
178330
|
-
refine: 1,
|
|
178331
|
-
revise: 1,
|
|
178332
|
-
proposals: 1,
|
|
178333
|
-
accept: 2,
|
|
178334
|
-
reject: 2,
|
|
178335
|
-
search: 1,
|
|
178336
|
-
"search-status": 2,
|
|
178337
|
-
"search-stop": 2
|
|
178338
|
-
};
|
|
178339
|
-
if (sub in arity)
|
|
178340
|
-
assertPositionals(`signals ${sub}`, args, arity[sub], SIGNAL_USAGE.split(`
|
|
178341
|
-
`)[0]);
|
|
178342
|
-
const base = () => `/tenants/${encodeURIComponent(requireTenant(context))}/custom-signals`;
|
|
178343
|
-
const id = (index = 0, what = "a signal id") => {
|
|
178344
|
-
const value = args[index];
|
|
178345
|
-
if (!value)
|
|
178346
|
-
throw new CliInputError(`moda signals ${sub} needs ${what}.`, `Usage:
|
|
178347
|
-
${SIGNAL_USAGE}`);
|
|
178348
|
-
return encodeURIComponent(value);
|
|
178349
|
-
};
|
|
178350
|
-
const start = () => requireKey(context);
|
|
178351
|
-
switch (sub) {
|
|
178352
|
-
case "draft": {
|
|
178353
|
-
assertFlags("signals draft", flags, ["note", "file", "dry-run"]);
|
|
178354
|
-
const body = { ...readBodyFile(flags, context.cwd), ...compact({ note: flags.note }) };
|
|
178355
|
-
if (!body.note)
|
|
178356
|
-
throw new CliInputError("--note is required (describe what the signal should catch).");
|
|
178357
|
-
start();
|
|
178358
|
-
await send(context, "control", "POST", `${base()}/draft`, body, { slow: true });
|
|
178359
|
-
return { exitCode: 0 };
|
|
178360
|
-
}
|
|
178361
|
-
case "create": {
|
|
178362
|
-
assertFlags("signals create", flags, [...SIGNAL_FIELD_FLAGS, "dry-run"]);
|
|
178363
|
-
const body = signalBody(flags, context.cwd);
|
|
178364
|
-
const missing = ["name", "description", "passCriteria", "failCriteria"].filter((field) => !body[field]);
|
|
178365
|
-
if (missing.length > 0) {
|
|
178366
|
-
throw new CliInputError(`Missing ${missing.join(", ")} for signals create.`, 'Pass --name --description --pass-criteria --fail-criteria, or a --file with those fields. Tip: `moda signals draft --note="…"` drafts them.');
|
|
178367
|
-
}
|
|
178368
|
-
start();
|
|
178369
|
-
await send(context, "control", "POST", base(), body);
|
|
178370
|
-
return { exitCode: 0 };
|
|
178371
|
-
}
|
|
178372
|
-
case "update": {
|
|
178373
|
-
assertFlags("signals update", flags, [...SIGNAL_FIELD_FLAGS, "dry-run"]);
|
|
178374
|
-
const signalId = id();
|
|
178375
|
-
const body = signalBody(flags, context.cwd);
|
|
178376
|
-
if (Object.keys(body).length === 0)
|
|
178377
|
-
throw new CliInputError("Nothing to update: pass at least one field flag or --file.");
|
|
178378
|
-
start();
|
|
178379
|
-
await send(context, "control", "PATCH", `${base()}/${signalId}`, body);
|
|
178380
|
-
return { exitCode: 0 };
|
|
178381
|
-
}
|
|
178382
|
-
case "activate":
|
|
178383
|
-
case "pause": {
|
|
178384
|
-
assertFlags(`signals ${sub}`, flags, ["dry-run"]);
|
|
178385
|
-
const signalId = id();
|
|
178386
|
-
start();
|
|
178387
|
-
await send(context, "control", "POST", `${base()}/${signalId}/${sub}`);
|
|
178388
|
-
return { exitCode: 0 };
|
|
178389
|
-
}
|
|
178390
|
-
case "delete": {
|
|
178391
|
-
assertFlags("signals delete", flags, ["dry-run"]);
|
|
178392
|
-
const signalId = id();
|
|
178393
|
-
start();
|
|
178394
|
-
await send(context, "control", "DELETE", `${base()}/${signalId}`);
|
|
178395
|
-
return { exitCode: 0 };
|
|
178396
|
-
}
|
|
178397
|
-
case "examples": {
|
|
178398
|
-
const signalId = id();
|
|
178399
|
-
const action = args[1];
|
|
178400
|
-
const conversationId = flags["conversation-id"];
|
|
178401
|
-
if (!action || !["add", "update", "remove"].includes(action)) {
|
|
178402
|
-
throw new CliInputError("Usage: moda signals examples <id> add|update|remove --conversation-id=ID …");
|
|
178403
|
-
}
|
|
178404
|
-
if (!conversationId)
|
|
178405
|
-
throw new CliInputError("--conversation-id is required.");
|
|
178406
|
-
if (action === "add") {
|
|
178407
|
-
assertFlags("signals examples add", flags, ["conversation-id", "label", "note", "msg-index", "msg-dedup-token", "criteria", "verdict", "dry-run"]);
|
|
178408
|
-
const label = oneOf("label", flags.label, ["fits", "does_not_fit"]);
|
|
178409
|
-
if (!label)
|
|
178410
|
-
throw new CliInputError("--label=fits|does_not_fit is required.");
|
|
178411
|
-
start();
|
|
178412
|
-
await send(context, "control", "POST", `${base()}/${signalId}/examples`, compact({
|
|
178413
|
-
conversationId,
|
|
178414
|
-
label,
|
|
178415
|
-
source: "api",
|
|
178416
|
-
note: flags.note,
|
|
178417
|
-
msgIndex: flags["msg-index"] !== undefined ? Number(flags["msg-index"]) : undefined,
|
|
178418
|
-
msgDedupToken: flags["msg-dedup-token"],
|
|
178419
|
-
criteria: oneOf("criteria", flags.criteria, ["pass", "fail"]),
|
|
178420
|
-
verdict: oneOf("verdict", flags.verdict, ["accept", "reject"])
|
|
178421
|
-
}));
|
|
178422
|
-
} else if (action === "update") {
|
|
178423
|
-
assertFlags("signals examples update", flags, ["conversation-id", "label", "note", "blurb", "dry-run"]);
|
|
178424
|
-
const body = compact({ label: oneOf("label", flags.label, ["fits", "does_not_fit"]), note: flags.note, blurb: flags.blurb });
|
|
178425
|
-
if (Object.keys(body).length === 0)
|
|
178426
|
-
throw new CliInputError("Nothing to update: pass --label, --note, or --blurb.");
|
|
178427
|
-
start();
|
|
178428
|
-
await send(context, "control", "PATCH", `${base()}/${signalId}/examples/${encodeURIComponent(conversationId)}`, body);
|
|
178429
|
-
} else {
|
|
178430
|
-
assertFlags("signals examples remove", flags, ["conversation-id", "dry-run"]);
|
|
178431
|
-
start();
|
|
178432
|
-
await send(context, "control", "DELETE", `${base()}/${signalId}/examples/${encodeURIComponent(conversationId)}`);
|
|
178433
|
-
}
|
|
178434
|
-
return { exitCode: 0 };
|
|
178435
|
-
}
|
|
178436
|
-
case "refine": {
|
|
178437
|
-
assertFlags("signals refine", flags, ["request", "dry-run"]);
|
|
178438
|
-
const signalId = id();
|
|
178439
|
-
const request = flags.request;
|
|
178440
|
-
if (!request || request.length > 2000)
|
|
178441
|
-
throw new CliInputError("--request (1–2000 characters) is required.");
|
|
178442
|
-
start();
|
|
178443
|
-
await send(context, "control", "POST", `${base()}/${signalId}/refine`, { request }, { slow: true });
|
|
178444
|
-
return { exitCode: 0 };
|
|
178445
|
-
}
|
|
178446
|
-
case "revise": {
|
|
178447
|
-
assertFlags("signals revise", flags, ["conversation-ids", "dry-run"]);
|
|
178448
|
-
const signalId = id();
|
|
178449
|
-
const conversationIds = csv(flags["conversation-ids"]);
|
|
178450
|
-
if (!conversationIds)
|
|
178451
|
-
throw new CliInputError("--conversation-ids=a,b is required.");
|
|
178452
|
-
start();
|
|
178453
|
-
await send(context, "control", "POST", `${base()}/${signalId}/revise`, { conversationIds }, { slow: true });
|
|
178454
|
-
return { exitCode: 0 };
|
|
178455
|
-
}
|
|
178456
|
-
case "proposals": {
|
|
178457
|
-
assertFlags("signals proposals", flags, []);
|
|
178458
|
-
const signalId = id();
|
|
178459
|
-
start();
|
|
178460
|
-
await send(context, "control", "GET", `${base()}/${signalId}/proposals`);
|
|
178461
|
-
return { exitCode: 0 };
|
|
178462
|
-
}
|
|
178463
|
-
case "accept":
|
|
178464
|
-
case "reject": {
|
|
178465
|
-
assertFlags(`signals ${sub}`, flags, ["dry-run"]);
|
|
178466
|
-
const signalId = id();
|
|
178467
|
-
const proposalId = id(1, "a proposal id (see `moda signals proposals <id>`)");
|
|
178468
|
-
start();
|
|
178469
|
-
await send(context, "control", "POST", `${base()}/${signalId}/proposals/${proposalId}/${sub}`);
|
|
178470
|
-
return { exitCode: 0 };
|
|
178471
|
-
}
|
|
178472
|
-
case "search": {
|
|
178473
|
-
assertFlags("signals search", flags, ["mode", "exclude-conversation-ids", "dry-run"]);
|
|
178474
|
-
const signalId = id();
|
|
178475
|
-
start();
|
|
178476
|
-
await send(context, "control", "POST", `${base()}/${signalId}/search`, compact({
|
|
178477
|
-
mode: oneOf("mode", flags.mode, ["wizard", "full"]),
|
|
178478
|
-
excludeConversationIds: csv(flags["exclude-conversation-ids"])
|
|
178479
|
-
}), { slow: true });
|
|
178480
|
-
return { exitCode: 0 };
|
|
178481
|
-
}
|
|
178482
|
-
case "search-status":
|
|
178483
|
-
case "search-stop": {
|
|
178484
|
-
assertFlags(`signals ${sub}`, flags, sub === "search-stop" ? ["dry-run"] : []);
|
|
178485
|
-
const signalId = id();
|
|
178486
|
-
const searchId = id(1, "a search id (returned by `moda signals search <id>`)");
|
|
178487
|
-
start();
|
|
178488
|
-
await send(context, "control", sub === "search-stop" ? "POST" : "GET", `${base()}/${signalId}/searches/${searchId}${sub === "search-stop" ? "/stop" : ""}`);
|
|
178489
|
-
return { exitCode: 0 };
|
|
178490
|
-
}
|
|
178491
|
-
case "preview": {
|
|
178492
|
-
assertFlags("signals preview", flags, ["file", "conversation-ids", "max-examples"]);
|
|
178493
|
-
const body = readBodyFile(flags, context.cwd);
|
|
178494
|
-
if (!body.detector)
|
|
178495
|
-
throw new CliInputError('--file must contain {"detector": {...}} (optionally scope).');
|
|
178496
|
-
start();
|
|
178497
|
-
try {
|
|
178498
|
-
await send(context, "control", "POST", `${base()}/detector-preview`, {
|
|
178499
|
-
...body,
|
|
178500
|
-
...compact({
|
|
178501
|
-
conversationIds: csv(flags["conversation-ids"]),
|
|
178502
|
-
maxExamples: flags["max-examples"] !== undefined ? Number(flags["max-examples"]) : undefined
|
|
178503
|
-
})
|
|
178504
|
-
});
|
|
178505
|
-
} catch (error) {
|
|
178506
|
-
if (isTenantFeatureNotFound(error)) {
|
|
178507
|
-
throw new CliAccessError("The signal builder is not enabled for this tenant, so `moda signals preview` is unavailable (the API answered 404).", { guidance: "Ask Moda to enable the signal-builder feature for this tenant. Other `moda signals` subcommands still work." });
|
|
178508
|
-
}
|
|
178509
|
-
throw error;
|
|
178510
|
-
}
|
|
178511
|
-
return { exitCode: 0 };
|
|
178512
|
-
}
|
|
178513
|
-
default:
|
|
178514
|
-
throw unknownSignalsSubcommandError(sub, args);
|
|
178515
|
-
}
|
|
178516
|
-
}
|
|
178517
|
-
function isTenantFeatureNotFound(error) {
|
|
178518
|
-
if (!(error instanceof ApiError) || error.statusCode !== 404)
|
|
178519
|
-
return false;
|
|
178520
|
-
try {
|
|
178521
|
-
const body = JSON.parse(error.responseBody);
|
|
178522
|
-
return body.message === "Not Found" && body.error === undefined;
|
|
178523
|
-
} catch {
|
|
178524
|
-
return false;
|
|
178525
|
-
}
|
|
178526
|
-
}
|
|
178527
|
-
var SIGNALS_MANAGEMENT_SUBCOMMANDS = new Set([
|
|
178528
|
-
"draft",
|
|
178529
|
-
"create",
|
|
178530
|
-
"update",
|
|
178531
|
-
"activate",
|
|
178532
|
-
"pause",
|
|
178533
|
-
"delete",
|
|
178534
|
-
"examples",
|
|
178535
|
-
"refine",
|
|
178536
|
-
"revise",
|
|
178537
|
-
"proposals",
|
|
178538
|
-
"accept",
|
|
178539
|
-
"reject",
|
|
178540
|
-
"search",
|
|
178541
|
-
"search-status",
|
|
178542
|
-
"search-stop",
|
|
178543
|
-
"preview"
|
|
178544
|
-
]);
|
|
178545
|
-
function unknownSignalsSubcommandError(sub, args = []) {
|
|
178546
|
-
if (sub === "archive") {
|
|
178547
|
-
const id = args[0] ?? "<signal_id>";
|
|
178548
|
-
return new CliInputError(`Unknown signals subcommand 'archive': archiving a signal is dashboard-only, so nothing was sent.`, `To stop a signal from running, pause it: moda signals pause ${id}. Drafts can be deleted with moda signals delete ${id}.`);
|
|
178549
|
-
}
|
|
178550
|
-
return new CliInputError(`Unknown signals subcommand '${sub}', so nothing was sent. Valid subcommands: ${[...SIGNALS_MANAGEMENT_SUBCOMMANDS].join(", ")}.`, `Bare 'moda signals' lists custom signals; 'moda signal <signal_id>' opens one. Usage:
|
|
178551
|
-
${SIGNAL_USAGE}`);
|
|
178552
|
-
}
|
|
178553
|
-
|
|
178554
177912
|
// src/analyst-tui.ts
|
|
178555
177913
|
class AnalystTui {
|
|
178556
177914
|
state;
|
|
@@ -178655,16 +178013,16 @@ class AnalystTui {
|
|
|
178655
178013
|
this.active = false;
|
|
178656
178014
|
}
|
|
178657
178015
|
pushTimeline(label, message) {
|
|
178658
|
-
const
|
|
178659
|
-
if (!
|
|
178016
|
+
const compact = compactWhitespace(message);
|
|
178017
|
+
if (!compact)
|
|
178660
178018
|
return;
|
|
178661
178019
|
const last = this.state.timeline.at(-1);
|
|
178662
|
-
if (last?.label === label && last.message ===
|
|
178020
|
+
if (last?.label === label && last.message === compact)
|
|
178663
178021
|
return;
|
|
178664
178022
|
this.state.timeline.push({
|
|
178665
178023
|
time: timeOfDay(new Date),
|
|
178666
178024
|
label,
|
|
178667
|
-
message:
|
|
178025
|
+
message: compact
|
|
178668
178026
|
});
|
|
178669
178027
|
if (this.state.timeline.length > 80)
|
|
178670
178028
|
this.state.timeline.splice(0, this.state.timeline.length - 80);
|
|
@@ -178804,7 +178162,7 @@ function fitToScreen(lines, rows, width) {
|
|
|
178804
178162
|
function trimVisible(value, width) {
|
|
178805
178163
|
if (visibleLength(value) <= width)
|
|
178806
178164
|
return value;
|
|
178807
|
-
const stripped =
|
|
178165
|
+
const stripped = stripAnsi2(value);
|
|
178808
178166
|
return stripped.length > width ? `${stripped.slice(0, Math.max(0, width - 3))}...` : stripped;
|
|
178809
178167
|
}
|
|
178810
178168
|
function rule(width) {
|
|
@@ -178833,165 +178191,26 @@ function compactWhitespace(value) {
|
|
|
178833
178191
|
return value.replace(/\s+/g, " ").trim();
|
|
178834
178192
|
}
|
|
178835
178193
|
function visibleLength(value) {
|
|
178836
|
-
return
|
|
178194
|
+
return stripAnsi2(value).length;
|
|
178837
178195
|
}
|
|
178838
|
-
function
|
|
178196
|
+
function stripAnsi2(value) {
|
|
178839
178197
|
return value.replace(/\u001b\[[0-9;?]*[A-Za-z]/g, "");
|
|
178840
178198
|
}
|
|
178841
178199
|
|
|
178842
178200
|
// src/harness-remote.ts
|
|
178843
|
-
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as
|
|
178201
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
178844
178202
|
import { join as join2 } from "node:path";
|
|
178845
178203
|
|
|
178846
|
-
// src/markdown-terminal.ts
|
|
178847
|
-
function shouldColorTerminalOutput(opts = {}) {
|
|
178848
|
-
const env = opts.env ?? process.env;
|
|
178849
|
-
const isTTY = opts.isTTY ?? process.stdout.isTTY === true;
|
|
178850
|
-
if (!isTTY)
|
|
178851
|
-
return false;
|
|
178852
|
-
if (env.NO_COLOR !== undefined)
|
|
178853
|
-
return false;
|
|
178854
|
-
if (env.TERM === "dumb")
|
|
178855
|
-
return false;
|
|
178856
|
-
return true;
|
|
178857
|
-
}
|
|
178858
|
-
function terminalStyles(color) {
|
|
178859
|
-
const paint = (open, close) => (text) => color ? `\x1B[${open}m${text}\x1B[${close}m` : text;
|
|
178860
|
-
return {
|
|
178861
|
-
bold: paint("1", "22"),
|
|
178862
|
-
italic: paint("3", "23"),
|
|
178863
|
-
dim: paint("2", "22"),
|
|
178864
|
-
code: paint("36", "39"),
|
|
178865
|
-
heading: paint("1;4", "22;24")
|
|
178866
|
-
};
|
|
178867
|
-
}
|
|
178868
|
-
var FENCE_RE = /^\s*(`{3,}|~{3,})/;
|
|
178869
|
-
var FENCE_CLOSE_RE = /^\s*(`{3,}|~{3,})\s*$/;
|
|
178870
|
-
var TABLE_ROW_RE = /^\s*\|.*\S/;
|
|
178871
|
-
var ANSI_RE = /\u001b(?:\[[0-9;?]*[ -/]*[@-~]|\][^\u0007\u001b]*(?:\u0007|\u001b\\)|[@-Z\\-_])/g;
|
|
178872
|
-
function stripAnsi2(text) {
|
|
178873
|
-
return text.replace(ANSI_RE, "");
|
|
178874
|
-
}
|
|
178875
|
-
function parseFenceOpen(line) {
|
|
178876
|
-
const match = FENCE_RE.exec(line);
|
|
178877
|
-
if (!match)
|
|
178878
|
-
return null;
|
|
178879
|
-
return { char: match[1][0], len: match[1].length };
|
|
178880
|
-
}
|
|
178881
|
-
function isFenceClose(line, fence) {
|
|
178882
|
-
const match = FENCE_CLOSE_RE.exec(line);
|
|
178883
|
-
return match !== null && match[1][0] === fence.char && match[1].length >= fence.len;
|
|
178884
|
-
}
|
|
178885
|
-
var HEADER_RE = /^(#{1,6})\s+(.*?)\s*#*\s*$/;
|
|
178886
|
-
var BULLET_RE = /^(\s*)([-*+])\s+(.*)$/;
|
|
178887
|
-
var ORDERED_RE = /^(\s*)(\d+)[.)]\s+(.*)$/;
|
|
178888
|
-
function renderMarkdownForTerminal(markdown, opts) {
|
|
178889
|
-
const style = terminalStyles(opts.color);
|
|
178890
|
-
const out = [];
|
|
178891
|
-
const listStack = [];
|
|
178892
|
-
let fence = null;
|
|
178893
|
-
for (const raw of markdown.replace(/\r\n/g, `
|
|
178894
|
-
`).split(`
|
|
178895
|
-
`)) {
|
|
178896
|
-
if (fence) {
|
|
178897
|
-
out.push(stripAnsi2(raw));
|
|
178898
|
-
if (isFenceClose(raw, fence))
|
|
178899
|
-
fence = null;
|
|
178900
|
-
continue;
|
|
178901
|
-
}
|
|
178902
|
-
const opened = parseFenceOpen(raw);
|
|
178903
|
-
if (opened) {
|
|
178904
|
-
fence = opened;
|
|
178905
|
-
listStack.length = 0;
|
|
178906
|
-
out.push(stripAnsi2(raw));
|
|
178907
|
-
continue;
|
|
178908
|
-
}
|
|
178909
|
-
if (TABLE_ROW_RE.test(raw)) {
|
|
178910
|
-
out.push(stripAnsi2(raw));
|
|
178911
|
-
continue;
|
|
178912
|
-
}
|
|
178913
|
-
const line = raw.replace(/\s+$/, "");
|
|
178914
|
-
if (line === "") {
|
|
178915
|
-
out.push("");
|
|
178916
|
-
continue;
|
|
178917
|
-
}
|
|
178918
|
-
const header = HEADER_RE.exec(line);
|
|
178919
|
-
if (header) {
|
|
178920
|
-
listStack.length = 0;
|
|
178921
|
-
const text = renderInline(header[2], terminalStyles(false));
|
|
178922
|
-
if (out.length > 0 && out[out.length - 1] !== "")
|
|
178923
|
-
out.push("");
|
|
178924
|
-
out.push(header[1].length <= 2 ? style.heading(text) : style.bold(text));
|
|
178925
|
-
continue;
|
|
178926
|
-
}
|
|
178927
|
-
const bullet = BULLET_RE.exec(line);
|
|
178928
|
-
const ordered = bullet ? null : ORDERED_RE.exec(line);
|
|
178929
|
-
if (bullet || ordered) {
|
|
178930
|
-
const match = bullet ?? ordered;
|
|
178931
|
-
const level = resolveListLevel(match[1].length, listStack);
|
|
178932
|
-
const indent = " ".repeat(level);
|
|
178933
|
-
const text = renderInline(match[3], style);
|
|
178934
|
-
if (bullet) {
|
|
178935
|
-
out.push(`${indent}${level === 0 ? "•" : "-"} ${text}`);
|
|
178936
|
-
} else {
|
|
178937
|
-
out.push(`${indent}${match[2]}. ${text}`);
|
|
178938
|
-
}
|
|
178939
|
-
continue;
|
|
178940
|
-
}
|
|
178941
|
-
if (!/^\s{2,}/.test(line))
|
|
178942
|
-
listStack.length = 0;
|
|
178943
|
-
out.push(renderInline(line, style));
|
|
178944
|
-
}
|
|
178945
|
-
return collapseBlankRuns(out).join(`
|
|
178946
|
-
`);
|
|
178947
|
-
}
|
|
178948
|
-
function resolveListLevel(indent, stack) {
|
|
178949
|
-
while (stack.length > 0 && indent < stack[stack.length - 1] - 1)
|
|
178950
|
-
stack.pop();
|
|
178951
|
-
if (stack.length === 0 || indent > stack[stack.length - 1] + 1)
|
|
178952
|
-
stack.push(indent);
|
|
178953
|
-
return stack.length - 1;
|
|
178954
|
-
}
|
|
178955
|
-
function renderInline(text, style) {
|
|
178956
|
-
const codeSpans = [];
|
|
178957
|
-
let result = stripAnsi2(text).replace(/`([^`]+)`/g, (_, code) => {
|
|
178958
|
-
codeSpans.push(code);
|
|
178959
|
-
return `\x00${codeSpans.length - 1}\x00`;
|
|
178960
|
-
});
|
|
178961
|
-
result = result.replace(/\*\*([^\s*](?:[^*]*[^\s*])?)\*\*/g, (_, inner) => style.bold(inner));
|
|
178962
|
-
result = result.replace(/__([^\s_](?:[^_]*[^\s_])?)__/g, (_, inner) => style.bold(inner));
|
|
178963
|
-
result = result.replace(/(?<![\w*])\*([^\s*](?:[^*\n]*[^\s*])?)\*(?![\w*])/g, (_, inner) => style.italic(inner));
|
|
178964
|
-
result = result.replace(/(?<![\w_])_([^\s_](?:[^_\n]*[^\s_])?)_(?![\w_])/g, (_, inner) => style.italic(inner));
|
|
178965
|
-
return result.replace(/\u0000(\d+)\u0000/g, (_, index) => style.code(codeSpans[Number(index)]));
|
|
178966
|
-
}
|
|
178967
|
-
function collapseBlankRuns(lines) {
|
|
178968
|
-
const collapsed = [];
|
|
178969
|
-
let blanks = 0;
|
|
178970
|
-
for (const line of lines) {
|
|
178971
|
-
if (line === "") {
|
|
178972
|
-
blanks += 1;
|
|
178973
|
-
continue;
|
|
178974
|
-
}
|
|
178975
|
-
if (blanks > 0)
|
|
178976
|
-
collapsed.push("", ...blanks === 2 ? [""] : []);
|
|
178977
|
-
blanks = 0;
|
|
178978
|
-
collapsed.push(line);
|
|
178979
|
-
}
|
|
178980
|
-
if (blanks > 0)
|
|
178981
|
-
collapsed.push("", ...blanks === 2 ? [""] : []);
|
|
178982
|
-
return collapsed;
|
|
178983
|
-
}
|
|
178984
|
-
|
|
178985
178204
|
// src/harness-report.ts
|
|
178986
178205
|
import { createHash } from "node:crypto";
|
|
178987
178206
|
import {
|
|
178988
178207
|
existsSync,
|
|
178989
178208
|
lstatSync,
|
|
178990
178209
|
mkdirSync,
|
|
178991
|
-
readFileSync
|
|
178210
|
+
readFileSync,
|
|
178992
178211
|
writeFileSync
|
|
178993
178212
|
} from "node:fs";
|
|
178994
|
-
import { basename, dirname, join, relative, resolve
|
|
178213
|
+
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
178995
178214
|
import { confirm } from "@inquirer/prompts";
|
|
178996
178215
|
var HARNESS_REPORT_SCHEMA_VERSION = "harness_report.v0.1";
|
|
178997
178216
|
var HARNESS_REPORT_VALIDATION_SCHEMA_VERSION = "harness_report_validation.v0.1";
|
|
@@ -179509,12 +178728,12 @@ function loadHarnessReportForSync(rootDir, reportPath, options) {
|
|
|
179509
178728
|
`));
|
|
179510
178729
|
}
|
|
179511
178730
|
const approvalPath = join(rootDir, HARNESS_REPORT_APPROVAL_PATH);
|
|
179512
|
-
const approval = existsSync(approvalPath) ? JSON.parse(
|
|
178731
|
+
const approval = existsSync(approvalPath) ? JSON.parse(readFileSync(approvalPath, "utf8")) : null;
|
|
179513
178732
|
const approved = approval?.schemaVersion === HARNESS_REPORT_APPROVAL_SCHEMA_VERSION && approval.reportId === report.reportId && approval.reportHash === hashHarnessReport(report) && approval.approved === true;
|
|
179514
178733
|
return { report, validation, approval, approved };
|
|
179515
178734
|
}
|
|
179516
178735
|
function readHarnessReport(reportPath) {
|
|
179517
|
-
return normalizeHarnessReport(JSON.parse(
|
|
178736
|
+
return normalizeHarnessReport(JSON.parse(readFileSync(reportPath, "utf8")));
|
|
179518
178737
|
}
|
|
179519
178738
|
function normalizeHarnessReport(value) {
|
|
179520
178739
|
const report = cloneJson(value);
|
|
@@ -180105,7 +179324,7 @@ function limitReportEvidence(claims, citations) {
|
|
|
180105
179324
|
};
|
|
180106
179325
|
}
|
|
180107
179326
|
function resolveHarnessReportPath(rootDir, value) {
|
|
180108
|
-
return
|
|
179327
|
+
return resolve(rootDir, value && value !== "true" ? value : HARNESS_REPORT_PATH);
|
|
180109
179328
|
}
|
|
180110
179329
|
function writeHarnessReportArtifacts(options) {
|
|
180111
179330
|
const written = [];
|
|
@@ -180242,14 +179461,14 @@ function upsertCitation(citations, citationIndex, evidence, rootDir) {
|
|
|
180242
179461
|
function citationExcerpt(rootDir, path, line) {
|
|
180243
179462
|
if (isUnsafeCitationPath(path))
|
|
180244
179463
|
return {};
|
|
180245
|
-
const absPath =
|
|
179464
|
+
const absPath = resolve(rootDir, path);
|
|
180246
179465
|
if (!isInside(rootDir, absPath) || !existsSync(absPath))
|
|
180247
179466
|
return {};
|
|
180248
179467
|
try {
|
|
180249
179468
|
const stat = lstatSync(absPath);
|
|
180250
179469
|
if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 128 * 1024)
|
|
180251
179470
|
return {};
|
|
180252
|
-
const lines =
|
|
179471
|
+
const lines = readFileSync(absPath, "utf8").split(/\r?\n/);
|
|
180253
179472
|
const selected = line ? lines[line - 1] : lines.find((candidate) => candidate.trim().length > 0);
|
|
180254
179473
|
if (!selected)
|
|
180255
179474
|
return {};
|
|
@@ -180387,7 +179606,7 @@ function validateCitation(citation, rootDir, errors, warnings, options) {
|
|
|
180387
179606
|
errors.push(`Citation ${citation.id} points to an unsafe path.`);
|
|
180388
179607
|
return;
|
|
180389
179608
|
}
|
|
180390
|
-
const absPath =
|
|
179609
|
+
const absPath = resolve(rootDir, citation.path);
|
|
180391
179610
|
if (!isInside(rootDir, absPath)) {
|
|
180392
179611
|
errors.push(`Citation ${citation.id} points outside the harness root.`);
|
|
180393
179612
|
return;
|
|
@@ -180406,7 +179625,7 @@ function validateCitation(citation, rootDir, errors, warnings, options) {
|
|
|
180406
179625
|
}
|
|
180407
179626
|
if (!stat.isFile())
|
|
180408
179627
|
errors.push(`Citation ${citation.id} does not point to a file.`);
|
|
180409
|
-
const lines =
|
|
179628
|
+
const lines = readFileSync(absPath, "utf8").split(/\r?\n/);
|
|
180410
179629
|
if (citation.line !== undefined) {
|
|
180411
179630
|
const lineCount = lines.length;
|
|
180412
179631
|
if (citation.line < 1 || citation.line > lineCount) {
|
|
@@ -180457,7 +179676,7 @@ function isSecretishPath2(path) {
|
|
|
180457
179676
|
return name === ".env" || name.startsWith(".env.") || name.includes("secret") || name.includes("private-key") || name.endsWith(".pem");
|
|
180458
179677
|
}
|
|
180459
179678
|
function isInside(rootDir, absPath) {
|
|
180460
|
-
const rel = relative(
|
|
179679
|
+
const rel = relative(resolve(rootDir), resolve(absPath));
|
|
180461
179680
|
return rel === "" || !rel.startsWith("..") && !rel.startsWith("/");
|
|
180462
179681
|
}
|
|
180463
179682
|
function writeJson(path, value) {
|
|
@@ -180517,7 +179736,7 @@ function readRemoteRunState(rootDir) {
|
|
|
180517
179736
|
if (!existsSync2(path))
|
|
180518
179737
|
return;
|
|
180519
179738
|
try {
|
|
180520
|
-
const parsed = JSON.parse(
|
|
179739
|
+
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
180521
179740
|
if (!parsed || typeof parsed.run_id !== "string" || parsed.run_id.length === 0)
|
|
180522
179741
|
return;
|
|
180523
179742
|
return {
|
|
@@ -180813,7 +180032,7 @@ function serverFailedReportValidation(final) {
|
|
|
180813
180032
|
return typeof validation === "object" && validation !== null && !Array.isArray(validation) && validation.status === "fail";
|
|
180814
180033
|
}
|
|
180815
180034
|
function sanitizeProgressText(text) {
|
|
180816
|
-
return
|
|
180035
|
+
return stripAnsi(text).replace(/[\u0000-\u001f\u007f]+/g, " ").replace(/\s+/g, " ").trim();
|
|
180817
180036
|
}
|
|
180818
180037
|
function normalizeRemoteProgress(value) {
|
|
180819
180038
|
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
@@ -180878,22 +180097,22 @@ async function remoteAnalyzeFetch(url, apiKey, init, timeoutMs) {
|
|
|
180878
180097
|
|
|
180879
180098
|
// src/harness-register/register.ts
|
|
180880
180099
|
import * as fs from "node:fs";
|
|
180881
|
-
import { mkdtempSync, readFileSync as
|
|
180100
|
+
import { mkdtempSync, readFileSync as readFileSync7, rmSync as rmSync3 } from "node:fs";
|
|
180882
180101
|
import { Readable as Readable2 } from "node:stream";
|
|
180883
180102
|
import { tmpdir } from "node:os";
|
|
180884
|
-
import { basename as basename4, join as join8, resolve as
|
|
180103
|
+
import { basename as basename4, join as join8, resolve as resolve4 } from "node:path";
|
|
180885
180104
|
|
|
180886
180105
|
// src/harness-register/collect-adapter.ts
|
|
180887
180106
|
import { createHash as createHash4 } from "node:crypto";
|
|
180888
180107
|
import { execFileSync } from "node:child_process";
|
|
180889
|
-
import { copyFileSync, createReadStream, existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as
|
|
180108
|
+
import { copyFileSync, createReadStream, existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync6, realpathSync as realpathSync4, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
180890
180109
|
import { dirname as dirname5, join as join7 } from "node:path";
|
|
180891
180110
|
|
|
180892
180111
|
// ../../packages/harness-bundle/src/contract.ts
|
|
180893
180112
|
var HARNESS_BUNDLE_SCHEMA = "moda_harness_bundle.v1";
|
|
180894
180113
|
var DEPENDENCY_MAP_SCHEMA = "moda_dependency_map.v1";
|
|
180895
180114
|
// ../../packages/harness-bundle/src/detect/files.ts
|
|
180896
|
-
import { existsSync as existsSync3, lstatSync as lstatSync2, readdirSync, readFileSync as
|
|
180115
|
+
import { existsSync as existsSync3, lstatSync as lstatSync2, readdirSync, readFileSync as readFileSync3, realpathSync } from "node:fs";
|
|
180897
180116
|
import { join as join3, sep } from "node:path";
|
|
180898
180117
|
|
|
180899
180118
|
// ../../packages/harness-bundle/src/detect/text.ts
|
|
@@ -181244,7 +180463,7 @@ function readManifest(dir) {
|
|
|
181244
180463
|
if (!existsSync3(path))
|
|
181245
180464
|
return;
|
|
181246
180465
|
try {
|
|
181247
|
-
const parsed = JSON.parse(
|
|
180466
|
+
const parsed = JSON.parse(readFileSync3(path, "utf8"));
|
|
181248
180467
|
if (isRecord2(parsed) && parsed.schema === HARNESS_BUNDLE_SCHEMA && Array.isArray(parsed.files)) {
|
|
181249
180468
|
return parsed;
|
|
181250
180469
|
}
|
|
@@ -181263,7 +180482,7 @@ function readText(abs, maxBytes) {
|
|
|
181263
180482
|
const st = lstatSync2(abs);
|
|
181264
180483
|
if (!st.isFile() || st.size > maxBytes)
|
|
181265
180484
|
return;
|
|
181266
|
-
const buf =
|
|
180485
|
+
const buf = readFileSync3(abs);
|
|
181267
180486
|
if (buf.subarray(0, 8000).includes(0))
|
|
181268
180487
|
return;
|
|
181269
180488
|
return buf.toString("utf8");
|
|
@@ -186085,8 +185304,8 @@ function detectDependencies(input) {
|
|
|
186085
185304
|
}
|
|
186086
185305
|
// ../../packages/harness-bundle/src/collect/collect.ts
|
|
186087
185306
|
import { createHash as createHash2 } from "node:crypto";
|
|
186088
|
-
import { closeSync, existsSync as existsSync4, lstatSync as lstatSync3, openSync, readdirSync as readdirSync2, readFileSync as
|
|
186089
|
-
import { basename as basename3, dirname as dirname3, isAbsolute, join as join5, relative as relative2, resolve as
|
|
185307
|
+
import { closeSync, existsSync as existsSync4, lstatSync as lstatSync3, openSync, readdirSync as readdirSync2, readFileSync as readFileSync4, readlinkSync, readSync, realpathSync as realpathSync2 } from "node:fs";
|
|
185308
|
+
import { basename as basename3, dirname as dirname3, isAbsolute, join as join5, relative as relative2, resolve as resolve2, sep as sep2 } from "node:path";
|
|
186090
185309
|
|
|
186091
185310
|
// ../../packages/harness-bundle/src/collect/rules.ts
|
|
186092
185311
|
var VCS_DIRS = new Set([".git", ".hg", ".svn", ".bzr", "_darcs", ".jj", ".sl"]);
|
|
@@ -188519,7 +187738,7 @@ class Collector {
|
|
|
188519
187738
|
listedArtifacts = new Map;
|
|
188520
187739
|
constructor(repoRoot, opts) {
|
|
188521
187740
|
this.opts = opts;
|
|
188522
|
-
this.start = realpathSync2(
|
|
187741
|
+
this.start = realpathSync2(resolve2(repoRoot));
|
|
188523
187742
|
this.root = this.start;
|
|
188524
187743
|
this.budget = { ...DEFAULT_BUDGET, ...stripUndefined(opts.budget ?? {}) };
|
|
188525
187744
|
}
|
|
@@ -188531,13 +187750,13 @@ class Collector {
|
|
|
188531
187750
|
this.gitMode = true;
|
|
188532
187751
|
}
|
|
188533
187752
|
}
|
|
188534
|
-
const harnessAbs = realpathSync2(
|
|
187753
|
+
const harnessAbs = realpathSync2(resolve2(this.start, this.opts.harnessRoot ?? "."));
|
|
188535
187754
|
const harnessRel = toPosix(relative2(this.root, harnessAbs));
|
|
188536
187755
|
if (isOutside(harnessRel)) {
|
|
188537
187756
|
throw new Error(`Harness root ${harnessAbs} is outside the bundle root ${this.root}`);
|
|
188538
187757
|
}
|
|
188539
187758
|
for (const skip of this.opts.skipPaths ?? []) {
|
|
188540
|
-
const rel2 = toPosix(relative2(this.root,
|
|
187759
|
+
const rel2 = toPosix(relative2(this.root, resolve2(skip)));
|
|
188541
187760
|
if (rel2 !== "" && !isOutside(rel2))
|
|
188542
187761
|
this.skipRel.add(rel2);
|
|
188543
187762
|
}
|
|
@@ -188715,7 +187934,7 @@ class Collector {
|
|
|
188715
187934
|
try {
|
|
188716
187935
|
const manifestPath = join5(this.root, outDir, MANIFEST_FILE);
|
|
188717
187936
|
if (lstatSync3(manifestPath).size <= MAX_PREVIOUS_MANIFEST_BYTES) {
|
|
188718
|
-
const previous = JSON.parse(
|
|
187937
|
+
const previous = JSON.parse(readFileSync4(manifestPath, "utf8"));
|
|
188719
187938
|
for (const a of previous.deployArtifacts ?? [])
|
|
188720
187939
|
if (typeof a.path === "string")
|
|
188721
187940
|
listed.add(a.path);
|
|
@@ -188878,7 +188097,7 @@ class Collector {
|
|
|
188878
188097
|
}
|
|
188879
188098
|
let buf;
|
|
188880
188099
|
try {
|
|
188881
|
-
buf =
|
|
188100
|
+
buf = readFileSync4(abs);
|
|
188882
188101
|
} catch {
|
|
188883
188102
|
this.excludeFile(path, "unreadable", "read_failed", st.size);
|
|
188884
188103
|
return;
|
|
@@ -188917,7 +188136,7 @@ class Collector {
|
|
|
188917
188136
|
this.excludeFile(path, "unreadable", "readlink_failed");
|
|
188918
188137
|
return;
|
|
188919
188138
|
}
|
|
188920
|
-
const lexical =
|
|
188139
|
+
const lexical = resolve2(dirname3(abs), target);
|
|
188921
188140
|
let real = lexical;
|
|
188922
188141
|
try {
|
|
188923
188142
|
real = realpathSync2(abs);
|
|
@@ -189049,7 +188268,7 @@ class Collector {
|
|
|
189049
188268
|
return skip(`${st.size} bytes exceeds ${limit}`);
|
|
189050
188269
|
let buf;
|
|
189051
188270
|
try {
|
|
189052
|
-
buf =
|
|
188271
|
+
buf = readFileSync4(abs);
|
|
189053
188272
|
} catch {
|
|
189054
188273
|
return skip("unreadable");
|
|
189055
188274
|
}
|
|
@@ -189254,8 +188473,8 @@ function stripUndefined(value) {
|
|
|
189254
188473
|
}
|
|
189255
188474
|
// ../../packages/harness-bundle/src/collect/write.ts
|
|
189256
188475
|
import { createHash as createHash3, randomUUID } from "node:crypto";
|
|
189257
|
-
import { createWriteStream, existsSync as existsSync5, lstatSync as lstatSync4, mkdirSync as mkdirSync3, readdirSync as readdirSync3, readFileSync as
|
|
189258
|
-
import { dirname as dirname4, isAbsolute as isAbsolute2, join as join6, relative as relative3, resolve as
|
|
188476
|
+
import { createWriteStream, existsSync as existsSync5, lstatSync as lstatSync4, mkdirSync as mkdirSync3, readdirSync as readdirSync3, readFileSync as readFileSync5, readlinkSync as readlinkSync2, realpathSync as realpathSync3, renameSync, rmSync, statSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
188477
|
+
import { dirname as dirname4, isAbsolute as isAbsolute2, join as join6, relative as relative3, resolve as resolve3, sep as sep3 } from "node:path";
|
|
189259
188478
|
import { Readable, Transform } from "node:stream";
|
|
189260
188479
|
import { pipeline } from "node:stream/promises";
|
|
189261
188480
|
import { createGzip } from "node:zlib";
|
|
@@ -189431,7 +188650,7 @@ function* tarChunks(files) {
|
|
|
189431
188650
|
throw new Error(`${file.path} changed after collection; re-run the collector`);
|
|
189432
188651
|
entry = { path: file.path, type: "symlink", mode: 511, linkTarget: file.symlinkTarget };
|
|
189433
188652
|
} else {
|
|
189434
|
-
const body =
|
|
188653
|
+
const body = readFileSync5(file.absolutePath);
|
|
189435
188654
|
const executableNow = (statSync(file.absolutePath).mode & 73) !== 0;
|
|
189436
188655
|
if (sha256(body) !== file.sha256 || executableNow !== file.executable) {
|
|
189437
188656
|
throw new Error(`${file.path} changed after collection; re-run the collector`);
|
|
@@ -189502,7 +188721,7 @@ function redactEnvExamples(result, dir) {
|
|
|
189502
188721
|
if (!file.categories.includes("env_example") || file.symlinkTarget !== undefined)
|
|
189503
188722
|
continue;
|
|
189504
188723
|
redacted = true;
|
|
189505
|
-
const body = Buffer.from(envNamesOnly(
|
|
188724
|
+
const body = Buffer.from(envNamesOnly(readFileSync6(file.absolutePath, "utf8")));
|
|
189506
188725
|
const target = join7(dir, file.path);
|
|
189507
188726
|
mkdirSync4(dirname5(target), { recursive: true });
|
|
189508
188727
|
writeFileSync4(target, body, { mode: file.executable ? 493 : 420 });
|
|
@@ -189518,7 +188737,7 @@ function redactEnvExamples(result, dir) {
|
|
|
189518
188737
|
for (const file of result.files) {
|
|
189519
188738
|
if (file.encoding !== "text" || file.symlinkTarget !== undefined || file.bytes > MAX_ENV_RESCAN_BYTES)
|
|
189520
188739
|
continue;
|
|
189521
|
-
env.scanFile(file.path,
|
|
188740
|
+
env.scanFile(file.path, readFileSync6(file.absolutePath, "utf8"), file.categories);
|
|
189522
188741
|
}
|
|
189523
188742
|
result.manifest.env = env.finalize(new Set(result.files.map((file) => file.path)));
|
|
189524
188743
|
}
|
|
@@ -189563,8 +188782,8 @@ function insideCheckout(dir) {
|
|
|
189563
188782
|
}
|
|
189564
188783
|
async function digestFile(path) {
|
|
189565
188784
|
const hash = createHash4("sha256");
|
|
189566
|
-
await new Promise((
|
|
189567
|
-
createReadStream(path).on("data", (chunk) => hash.update(chunk)).on("error", reject).on("end", () =>
|
|
188785
|
+
await new Promise((resolve4, reject) => {
|
|
188786
|
+
createReadStream(path).on("data", (chunk) => hash.update(chunk)).on("error", reject).on("end", () => resolve4());
|
|
189568
188787
|
});
|
|
189569
188788
|
return { path, sha256: hash.digest("hex"), bytes: statSync2(path).size };
|
|
189570
188789
|
}
|
|
@@ -189588,8 +188807,8 @@ var EXCLUSION_REASONS = {
|
|
|
189588
188807
|
};
|
|
189589
188808
|
async function runHarnessRegister(context, argv = process.argv) {
|
|
189590
188809
|
const options = parseRegisterOptions(context, argv);
|
|
189591
|
-
const
|
|
189592
|
-
if (!context.dryRun && !resolveApiKey(
|
|
188810
|
+
const profileOptions = { profile: context.profile, env: context.env };
|
|
188811
|
+
if (!context.dryRun && !resolveApiKey(profileOptions)) {
|
|
189593
188812
|
throw new CliInputError("No Moda API key found for harness register.", "Run `moda harness register --dry-run` to review the bundle without one, or set MODA_API_KEY / run `moda auth login --api-key=<key>`.");
|
|
189594
188813
|
}
|
|
189595
188814
|
const outDir = mkdtempSync(join8(tmpdir(), "moda-harness-register-"));
|
|
@@ -189603,7 +188822,7 @@ async function runHarnessRegister(context, argv = process.argv) {
|
|
|
189603
188822
|
}
|
|
189604
188823
|
}
|
|
189605
188824
|
async function registerCollected(context, options, collected) {
|
|
189606
|
-
const
|
|
188825
|
+
const profileOptions = { profile: context.profile, env: context.env };
|
|
189607
188826
|
const report = buildRegisterReport(collected);
|
|
189608
188827
|
if (context.dryRun) {
|
|
189609
188828
|
emit(context, { ...report, dryRun: true }, renderRegisterReport(report, null));
|
|
@@ -189625,7 +188844,7 @@ async function registerCollected(context, options, collected) {
|
|
|
189625
188844
|
...gitFields(collected.manifest),
|
|
189626
188845
|
...options.imageRef ? { imageRef: options.imageRef } : {}
|
|
189627
188846
|
})
|
|
189628
|
-
},
|
|
188847
|
+
}, profileOptions));
|
|
189629
188848
|
const files = {
|
|
189630
188849
|
bundle: collected.bundle.path,
|
|
189631
188850
|
manifest: collected.manifestFile.path,
|
|
@@ -189635,29 +188854,29 @@ async function registerCollected(context, options, collected) {
|
|
|
189635
188854
|
const path = files[target.name];
|
|
189636
188855
|
if (!path)
|
|
189637
188856
|
throw new Error(`Moda asked for ${target.name}, which was not collected.`);
|
|
189638
|
-
await putObject(target, path, resolveModaBaseUrl(
|
|
188857
|
+
await putObject(target, path, resolveModaBaseUrl(profileOptions));
|
|
189639
188858
|
}
|
|
189640
|
-
const completed = await callControlAPI(`/harness-registrations/${encodeURIComponent(created.registration.id)}/complete`, { method: "POST" },
|
|
189641
|
-
await withFullChecklist(completed,
|
|
189642
|
-
const dashboardUrl = `${resolveModaBaseUrl(
|
|
188859
|
+
const completed = await callControlAPI(`/harness-registrations/${encodeURIComponent(created.registration.id)}/complete`, { method: "POST" }, profileOptions, { timeoutMs: 300000 });
|
|
188860
|
+
await withFullChecklist(completed, profileOptions);
|
|
188861
|
+
const dashboardUrl = `${resolveModaBaseUrl(profileOptions)}${completed.dashboardPath}`;
|
|
189643
188862
|
emit(context, { ...report, dryRun: false, registration: { ...completed, dashboardUrl } }, renderRegisterReport(report, { ...completed, dashboardUrl }), completed.status === "failed" ? "error" : undefined);
|
|
189644
188863
|
return { exitCode: completed.status === "failed" ? 1 : 0 };
|
|
189645
188864
|
}
|
|
189646
188865
|
async function runHarnessRegistration(context) {
|
|
189647
188866
|
const action = context.positionals[1] ?? "list";
|
|
189648
|
-
const
|
|
189649
|
-
if (!resolveApiKey(
|
|
188867
|
+
const profileOptions = { profile: context.profile, env: context.env };
|
|
188868
|
+
if (!resolveApiKey(profileOptions)) {
|
|
189650
188869
|
throw new CliInputError(`No Moda API key found for harness registration ${action}.`, "Set MODA_API_KEY, run `moda auth login --api-key=<key>`, or select a profile with an API key.");
|
|
189651
188870
|
}
|
|
189652
188871
|
if (context.flags["tenant-id"])
|
|
189653
188872
|
requireTenant(context);
|
|
189654
|
-
const baseUrl = resolveModaBaseUrl(
|
|
188873
|
+
const baseUrl = resolveModaBaseUrl(profileOptions);
|
|
189655
188874
|
if (action === "status") {
|
|
189656
188875
|
const id = context.positionals[2];
|
|
189657
188876
|
if (!id)
|
|
189658
188877
|
throw new CliInputError("Missing registration id.", "Usage: moda harness registration status <id> (ids from `moda harness registration list`)");
|
|
189659
|
-
const registration = await callControlAPI(`/harness-registrations/${encodeURIComponent(id)}`, {},
|
|
189660
|
-
await withFullChecklist(registration,
|
|
188878
|
+
const registration = await callControlAPI(`/harness-registrations/${encodeURIComponent(id)}`, {}, profileOptions);
|
|
188879
|
+
await withFullChecklist(registration, profileOptions);
|
|
189661
188880
|
const dashboardUrl = `${baseUrl}${registration.dashboardPath}`;
|
|
189662
188881
|
emit(context, { ...registration, dashboardUrl }, renderRegistrationStatus({ ...registration, dashboardUrl }));
|
|
189663
188882
|
return { exitCode: 0 };
|
|
@@ -189674,26 +188893,26 @@ async function runHarnessRegistration(context) {
|
|
|
189674
188893
|
if (context.flags["include-retired"] === "true")
|
|
189675
188894
|
query.set("includeRetired", "true");
|
|
189676
188895
|
const suffix = query.toString() ? `?${query}` : "";
|
|
189677
|
-
const response = await whenEnabled(() => callControlAPI(`/harness-registrations${suffix}`, {},
|
|
188896
|
+
const response = await whenEnabled(() => callControlAPI(`/harness-registrations${suffix}`, {}, profileOptions));
|
|
189678
188897
|
emit(context, response, renderRegistrationList(response.registrations, baseUrl));
|
|
189679
188898
|
return { exitCode: 0 };
|
|
189680
188899
|
}
|
|
189681
188900
|
throw new CliInputError(`Unknown harness registration command '${action}'.`, "Usage: moda harness registration list|status <id>");
|
|
189682
188901
|
}
|
|
189683
|
-
async function withFullChecklist(registration,
|
|
188902
|
+
async function withFullChecklist(registration, profileOptions) {
|
|
189684
188903
|
try {
|
|
189685
|
-
await loadFullChecklist(registration,
|
|
188904
|
+
await loadFullChecklist(registration, profileOptions);
|
|
189686
188905
|
} catch {
|
|
189687
188906
|
registration.checklistIncomplete = true;
|
|
189688
188907
|
}
|
|
189689
188908
|
}
|
|
189690
|
-
async function loadFullChecklist(registration,
|
|
188909
|
+
async function loadFullChecklist(registration, profileOptions) {
|
|
189691
188910
|
const total = registration.checklistCounts?.total ?? 0;
|
|
189692
188911
|
if (!registration.checklist || registration.checklist.items.length >= total)
|
|
189693
188912
|
return;
|
|
189694
188913
|
const items = [];
|
|
189695
188914
|
for (let page = 0;items.length < total && page < 100; page++) {
|
|
189696
|
-
const response = await callControlAPI(`/harness-registrations/${encodeURIComponent(registration.id)}/checklist?offset=${items.length}&limit=500`, {},
|
|
188915
|
+
const response = await callControlAPI(`/harness-registrations/${encodeURIComponent(registration.id)}/checklist?offset=${items.length}&limit=500`, {}, profileOptions);
|
|
189697
188916
|
if (response.items.length === 0)
|
|
189698
188917
|
break;
|
|
189699
188918
|
items.push(...response.items);
|
|
@@ -189753,7 +188972,7 @@ function parseRegisterOptions(context, argv) {
|
|
|
189753
188972
|
if (!ENV_NAME.test(name))
|
|
189754
188973
|
throw new CliInputError(`'${name}' is not an env var name.`, "Pass the variable name, never its value, e.g. --model-base-url-env=OPENAI_BASE_URL.");
|
|
189755
188974
|
}
|
|
189756
|
-
const harnessRoot =
|
|
188975
|
+
const harnessRoot = resolve4(context.cwd, flags.root ?? ".");
|
|
189757
188976
|
const harnessName = positionals[1] ?? defaultHarnessName(harnessRoot);
|
|
189758
188977
|
if (!HARNESS_NAME.test(harnessName)) {
|
|
189759
188978
|
throw new CliInputError(`Harness name '${harnessName}' is not valid.`, 'Use 1-128 letters, digits, ".", "_" or "-", e.g. `moda harness register support-agent`.');
|
|
@@ -189764,7 +188983,7 @@ function parseRegisterOptions(context, argv) {
|
|
|
189764
188983
|
}
|
|
189765
188984
|
function defaultHarnessName(root) {
|
|
189766
188985
|
try {
|
|
189767
|
-
const name = JSON.parse(
|
|
188986
|
+
const name = JSON.parse(readFileSync7(join8(root, "package.json"), "utf8")).name;
|
|
189768
188987
|
if (typeof name === "string" && name)
|
|
189769
188988
|
return sanitizeName(name.replace(/^@[^/]+\//, ""));
|
|
189770
188989
|
} catch {}
|
|
@@ -190020,8 +189239,8 @@ function formatBytes(bytes) {
|
|
|
190020
189239
|
}
|
|
190021
189240
|
|
|
190022
189241
|
// src/harness-artifact-bodies.ts
|
|
190023
|
-
import { existsSync as existsSync7, lstatSync as lstatSync5, readFileSync as
|
|
190024
|
-
import { basename as basename5, dirname as dirname6, isAbsolute as isAbsolute3, relative as relative4, resolve as
|
|
189242
|
+
import { existsSync as existsSync7, lstatSync as lstatSync5, readFileSync as readFileSync8, realpathSync as realpathSync5 } from "node:fs";
|
|
189243
|
+
import { basename as basename5, dirname as dirname6, isAbsolute as isAbsolute3, relative as relative4, resolve as resolve5 } from "node:path";
|
|
190025
189244
|
var MAX_SCANNED_FILE_BYTES2 = 512 * 1024;
|
|
190026
189245
|
var SNAPSHOT_BUDGET_SKIP_REASONS = new Set([
|
|
190027
189246
|
"file too large for harness scan",
|
|
@@ -190084,13 +189303,13 @@ function readBoundedRepoText(absPath, rootDir) {
|
|
|
190084
189303
|
return;
|
|
190085
189304
|
}
|
|
190086
189305
|
try {
|
|
190087
|
-
return
|
|
189306
|
+
return readFileSync8(absPath, "utf8");
|
|
190088
189307
|
} catch {
|
|
190089
189308
|
return;
|
|
190090
189309
|
}
|
|
190091
189310
|
}
|
|
190092
189311
|
function readRepoRelativeText(rootDir, relPath) {
|
|
190093
|
-
return readBoundedRepoText(
|
|
189312
|
+
return readBoundedRepoText(resolve5(rootDir, relPath), rootDir);
|
|
190094
189313
|
}
|
|
190095
189314
|
function isDedicatedToolFilePath(path) {
|
|
190096
189315
|
return /(^|\/)tools?\//i.test(path) && /\.(ts|tsx|js|mjs|py)$/i.test(path);
|
|
@@ -190117,8 +189336,8 @@ function extractToolBodyFromText(text, toolName) {
|
|
|
190117
189336
|
const normalizedName = toolName.replace(/\s+/g, "").toLowerCase();
|
|
190118
189337
|
for (let index = 0;index < lines.length; index += 1) {
|
|
190119
189338
|
const line = lines[index];
|
|
190120
|
-
const
|
|
190121
|
-
const mentionsTool =
|
|
189339
|
+
const compact = line.replace(/\s+/g, "").toLowerCase();
|
|
189340
|
+
const mentionsTool = compact.includes(normalizedName) || compact.includes(`def${normalizedName}`);
|
|
190122
189341
|
if (!mentionsTool)
|
|
190123
189342
|
continue;
|
|
190124
189343
|
if (line.includes("function_tool") || line.includes("tool(") || line.includes("createTool") || line.includes("functionTool") || line.includes("dynamicTool") || line.includes("new Tool") || line.includes("def ")) {
|
|
@@ -190131,14 +189350,14 @@ function annotatedSourceCandidates(sourcePath, annotation) {
|
|
|
190131
189350
|
const explicitSourcePath = normalizePath2(sourcePath) !== normalizePath2(annotation.evidence.path);
|
|
190132
189351
|
if (!explicitSourcePath) {
|
|
190133
189352
|
return [
|
|
190134
|
-
|
|
190135
|
-
|
|
189353
|
+
resolve5(annotation.rootDir, sourcePath),
|
|
189354
|
+
resolve5(dirname6(annotation.sourceAbsPath), sourcePath),
|
|
190136
189355
|
annotation.sourceAbsPath
|
|
190137
189356
|
];
|
|
190138
189357
|
}
|
|
190139
|
-
const rootAbs =
|
|
190140
|
-
const candidates = walkAncestorDirs(dirname6(annotation.sourceAbsPath), rootAbs).map((dir) =>
|
|
190141
|
-
candidates.push(
|
|
189358
|
+
const rootAbs = resolve5(annotation.rootDir);
|
|
189359
|
+
const candidates = walkAncestorDirs(dirname6(annotation.sourceAbsPath), rootAbs).map((dir) => resolve5(dir, sourcePath));
|
|
189360
|
+
candidates.push(resolve5(annotation.rootDir, sourcePath));
|
|
190142
189361
|
return candidates;
|
|
190143
189362
|
}
|
|
190144
189363
|
function readAnnotatedSourceText(sourcePath, annotation) {
|
|
@@ -190219,9 +189438,9 @@ function readSourcePathRelativeToEvidence(artifact, rootDir) {
|
|
|
190219
189438
|
const evidencePath = firstEvidencePath(artifact);
|
|
190220
189439
|
if (!evidencePath)
|
|
190221
189440
|
return;
|
|
190222
|
-
const rootAbs =
|
|
190223
|
-
for (const dir of walkAncestorDirs(dirname6(
|
|
190224
|
-
const text = readBoundedRepoText(
|
|
189441
|
+
const rootAbs = resolve5(rootDir);
|
|
189442
|
+
for (const dir of walkAncestorDirs(dirname6(resolve5(rootDir, evidencePath)), rootAbs)) {
|
|
189443
|
+
const text = readBoundedRepoText(resolve5(dir, artifact.sourcePath), rootDir);
|
|
190225
189444
|
if (text !== undefined)
|
|
190226
189445
|
return text;
|
|
190227
189446
|
}
|
|
@@ -190251,7 +189470,7 @@ function enrichScanCaptureMetadata(graph) {
|
|
|
190251
189470
|
|
|
190252
189471
|
// src/harness-candidates.ts
|
|
190253
189472
|
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync5 } from "node:fs";
|
|
190254
|
-
import { basename as basename6, dirname as dirname7, extname, resolve as
|
|
189473
|
+
import { basename as basename6, dirname as dirname7, extname, resolve as resolve6 } from "node:path";
|
|
190255
189474
|
var MAX_CANDIDATES_PER_FILE_PER_SIGNAL = 20;
|
|
190256
189475
|
var MIN_PROMPT_LITERAL_CHARS = 160;
|
|
190257
189476
|
var CONFIDENCE_WEIGHT = {
|
|
@@ -190777,7 +189996,7 @@ function detectHarnessCandidatesInFiles(files) {
|
|
|
190777
189996
|
function detectHarnessCandidates(rootDir) {
|
|
190778
189997
|
const startedAt = Date.now();
|
|
190779
189998
|
const skipped = [];
|
|
190780
|
-
const root =
|
|
189999
|
+
const root = resolve6(rootDir);
|
|
190781
190000
|
const inventory = inventoryFiles(root, skipped, {
|
|
190782
190001
|
includeFile: (path) => PROMPT_DOC_EXTENSIONS.has(extname(path).toLowerCase()) || [".json", ".yaml", ".yml"].includes(extname(path).toLowerCase()) || extname(path).toLowerCase() === ".rs" && RUST_PROMPT_PATH_HINT.test(path)
|
|
190783
190002
|
});
|
|
@@ -190803,7 +190022,7 @@ function detectHarnessCandidates(rootDir) {
|
|
|
190803
190022
|
return redactDeep(report);
|
|
190804
190023
|
}
|
|
190805
190024
|
function writeHarnessCandidatesReport(report, outPath) {
|
|
190806
|
-
const target =
|
|
190025
|
+
const target = resolve6(outPath);
|
|
190807
190026
|
mkdirSync5(dirname7(target), { recursive: true });
|
|
190808
190027
|
writeFileSync5(target, `${JSON.stringify(report, null, 2)}
|
|
190809
190028
|
`, "utf8");
|
|
@@ -190817,8 +190036,8 @@ import { extname as extname8 } from "node:path";
|
|
|
190817
190036
|
// src/prompt-sources.ts
|
|
190818
190037
|
var import_typescript2 = __toESM(require_typescript(), 1);
|
|
190819
190038
|
import { createHash as createHash5 } from "node:crypto";
|
|
190820
|
-
import { lstatSync as lstatSync7, readFileSync as
|
|
190821
|
-
import { extname as extname3, isAbsolute as isAbsolute4, relative as relative5, resolve as
|
|
190039
|
+
import { lstatSync as lstatSync7, readFileSync as readFileSync11, realpathSync as realpathSync8 } from "node:fs";
|
|
190040
|
+
import { extname as extname3, isAbsolute as isAbsolute4, relative as relative5, resolve as resolve9 } from "node:path";
|
|
190822
190041
|
|
|
190823
190042
|
// src/prompt-frameworks.ts
|
|
190824
190043
|
var PYTHON_AGENT_MODULES = [
|
|
@@ -190839,15 +190058,15 @@ var TYPESCRIPT_AGENT_MODULES = [
|
|
|
190839
190058
|
|
|
190840
190059
|
// src/prompt-source-code.ts
|
|
190841
190060
|
var import_typescript = __toESM(require_typescript(), 1);
|
|
190842
|
-
import { existsSync as existsSync8, lstatSync as lstatSync6, readFileSync as
|
|
190843
|
-
import { dirname as dirname8, extname as extname2, join as join9, resolve as
|
|
190061
|
+
import { existsSync as existsSync8, lstatSync as lstatSync6, readFileSync as readFileSync9, realpathSync as realpathSync6 } from "node:fs";
|
|
190062
|
+
import { dirname as dirname8, extname as extname2, join as join9, resolve as resolve7 } from "node:path";
|
|
190844
190063
|
var EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
190845
190064
|
var MAX_BYTES = 2 * 1024 * 1024;
|
|
190846
190065
|
var MAX_DEPTH = 32;
|
|
190847
190066
|
var MAX_FILES = 256;
|
|
190848
190067
|
var MAX_GRAPH_BYTES = 16 * 1024 * 1024;
|
|
190849
190068
|
function extractCodeSource(rootDir, sourcePath, symbol, forceDependencyGraph = false) {
|
|
190850
|
-
const state = { root:
|
|
190069
|
+
const state = { root: resolve7(rootDir), files: [], unresolved: [], visiting: new Set, importsVisited: new Set, parsed: new Map, assignments: new Map, bytesRead: 0 };
|
|
190851
190070
|
const file = safeFile(state.root, state.root, sourcePath);
|
|
190852
190071
|
const parsed = parseFile(file, state);
|
|
190853
190072
|
const target = symbol ? findSymbol(parsed, symbol) : findInstructionCandidate(parsed);
|
|
@@ -190880,7 +190099,7 @@ function parseFile(filePath, state) {
|
|
|
190880
190099
|
const cached = state.parsed.get(path);
|
|
190881
190100
|
if (cached)
|
|
190882
190101
|
return cached;
|
|
190883
|
-
const text =
|
|
190102
|
+
const text = readFileSync9(path, "utf8");
|
|
190884
190103
|
state.bytesRead += Buffer.byteLength(text);
|
|
190885
190104
|
state.files.push(path);
|
|
190886
190105
|
const scriptKind = extname2(path) === ".json" ? import_typescript.default.ScriptKind.JSON : /\.tsx?$/.test(extname2(path)) ? import_typescript.default.ScriptKind.TSX : import_typescript.default.ScriptKind.JSX;
|
|
@@ -190895,7 +190114,7 @@ function parseFile(filePath, state) {
|
|
|
190895
190114
|
function safeFile(root, base, requested) {
|
|
190896
190115
|
if (requested.includes("\x00"))
|
|
190897
190116
|
throw new Error(`Prompt source path contains NUL: ${requested}`);
|
|
190898
|
-
const candidate =
|
|
190117
|
+
const candidate = resolve7(base, requested);
|
|
190899
190118
|
let cursor = candidate;
|
|
190900
190119
|
while (cursor !== root) {
|
|
190901
190120
|
let stat2;
|
|
@@ -190911,7 +190130,7 @@ function safeFile(root, base, requested) {
|
|
|
190911
190130
|
break;
|
|
190912
190131
|
cursor = next;
|
|
190913
190132
|
}
|
|
190914
|
-
const rootReal =
|
|
190133
|
+
const rootReal = resolve7(root);
|
|
190915
190134
|
let real;
|
|
190916
190135
|
try {
|
|
190917
190136
|
real = requireRealpath(candidate);
|
|
@@ -191248,7 +190467,7 @@ function isBindingMutated(file, name) {
|
|
|
191248
190467
|
function moduleSpecifier(from, specifier) {
|
|
191249
190468
|
if (!specifier.startsWith("."))
|
|
191250
190469
|
return;
|
|
191251
|
-
const base =
|
|
190470
|
+
const base = resolve7(dirname8(from), specifier);
|
|
191252
190471
|
const stripped = /\.(?:js|jsx|mjs|cjs)$/.test(base) ? base.slice(0, base.lastIndexOf(".")) : base;
|
|
191253
190472
|
for (const candidate of [base, stripped, ...EXTENSIONS.map((ext) => `${base}${ext}`), ...EXTENSIONS.map((ext) => `${stripped}${ext}`), ...EXTENSIONS.map((ext) => join9(base, `index${ext}`)), ...EXTENSIONS.map((ext) => join9(stripped, `index${ext}`))])
|
|
191254
190473
|
if (existsSync8(candidate) && lstatSync6(candidate).isFile())
|
|
@@ -191268,7 +190487,7 @@ function nodeRange(file, node) {
|
|
|
191268
190487
|
};
|
|
191269
190488
|
}
|
|
191270
190489
|
function inspectCodeSelectors(rootDir, sourcePath, symbol) {
|
|
191271
|
-
const state = { root:
|
|
190490
|
+
const state = { root: resolve7(rootDir), files: [], unresolved: [], visiting: new Set, importsVisited: new Set, parsed: new Map, assignments: new Map, bytesRead: 0 };
|
|
191272
190491
|
const parsed = parseFile(safeFile(state.root, state.root, sourcePath), state);
|
|
191273
190492
|
if (symbol) {
|
|
191274
190493
|
const node = findSymbol(parsed, symbol);
|
|
@@ -191318,8 +190537,8 @@ function referenceNames(node) {
|
|
|
191318
190537
|
|
|
191319
190538
|
// src/prompt-source-python.ts
|
|
191320
190539
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
191321
|
-
import { readFileSync as
|
|
191322
|
-
import { resolve as
|
|
190540
|
+
import { readFileSync as readFileSync10, realpathSync as realpathSync7 } from "node:fs";
|
|
190541
|
+
import { resolve as resolve8 } from "node:path";
|
|
191323
190542
|
var PYTHON_AGENT_MODULES_LITERAL = JSON.stringify(PYTHON_AGENT_MODULES);
|
|
191324
190543
|
var SELECTOR_HELPER = String.raw`import ast,json,os,sys
|
|
191325
190544
|
request=json.loads(sys.stdin.read()); root=os.path.realpath(request['root']); path=os.path.abspath(request['path']); wanted=request.get('symbol')
|
|
@@ -191380,7 +190599,7 @@ else:
|
|
|
191380
190599
|
print(json.dumps({'candidates':found},ensure_ascii=False))`;
|
|
191381
190600
|
function inspectPythonSelectors(rootDir, sourcePath, symbol) {
|
|
191382
190601
|
const root = realpathSync7(rootDir);
|
|
191383
|
-
const absolute =
|
|
190602
|
+
const absolute = resolve8(root, sourcePath);
|
|
191384
190603
|
const result = spawnSync2("python3", ["-I", "-c", SELECTOR_HELPER], {
|
|
191385
190604
|
input: JSON.stringify({ root, path: absolute, ...symbol ? { symbol } : {} }),
|
|
191386
190605
|
encoding: "utf8",
|
|
@@ -191525,7 +190744,7 @@ except SystemExit: pass
|
|
|
191525
190744
|
except Exception as error: print(json.dumps({'candidates':[],'error':str(error)}))`;
|
|
191526
190745
|
function discoverPythonPromptSources(rootDir, sourcePath) {
|
|
191527
190746
|
const result = spawnSync2("python3", ["-I", "-c", DISCOVERY_HELPER], {
|
|
191528
|
-
input: JSON.stringify({ root: rootDir, path:
|
|
190747
|
+
input: JSON.stringify({ root: rootDir, path: resolve8(rootDir, sourcePath) }),
|
|
191529
190748
|
encoding: "utf8",
|
|
191530
190749
|
maxBuffer: 4 * 1024 * 1024,
|
|
191531
190750
|
timeout: 1e4
|
|
@@ -191785,7 +191004,7 @@ except Exception as e:
|
|
|
191785
191004
|
function extractPythonSource(rootDir, sourcePath, symbol, _forceDependencyGraph = false) {
|
|
191786
191005
|
let raw = "";
|
|
191787
191006
|
try {
|
|
191788
|
-
raw =
|
|
191007
|
+
raw = readFileSync10(sourcePath, "utf8");
|
|
191789
191008
|
} catch {}
|
|
191790
191009
|
const result = spawnSync2("python3", ["-I", "-c", HELPER], {
|
|
191791
191010
|
input: JSON.stringify({ root: rootDir, path: sourcePath, symbol, force: _forceDependencyGraph }),
|
|
@@ -191879,7 +191098,7 @@ function resolvePromptSource(rootDir, source) {
|
|
|
191879
191098
|
} else if (source.selector?.symbol) {
|
|
191880
191099
|
throw new Error(`${sourcePath}: symbol selectors require a JavaScript, TypeScript, or Python source file`);
|
|
191881
191100
|
} else if (ext === ".json" || ext === ".yaml" || ext === ".yml" || hasPointer || source.kind === "messages") {
|
|
191882
|
-
const parsed = parseStructured(
|
|
191101
|
+
const parsed = parseStructured(readFileSync11(sourceAbs, "utf8"), sourcePath, ext);
|
|
191883
191102
|
const selected = hasPointer ? jsonPointer(parsed, source.selector.pointer, sourcePath) : parsed;
|
|
191884
191103
|
const selectedField = source.selector?.pointer?.split("/").at(-1)?.replaceAll("~1", "/").replaceAll("~0", "~");
|
|
191885
191104
|
const inferredKind = !source.kind && selectedField && /^(?:template|system_template|instance_template)$/.test(selectedField) ? "template" : source.kind;
|
|
@@ -191889,7 +191108,7 @@ function resolvePromptSource(rootDir, source) {
|
|
|
191889
191108
|
messages = structured.messages;
|
|
191890
191109
|
kind = structured.kind;
|
|
191891
191110
|
} else {
|
|
191892
|
-
const raw =
|
|
191111
|
+
const raw = readFileSync11(sourceAbs, "utf8");
|
|
191893
191112
|
if (ext === ".md" && /\.prompt\.md$/i.test(sourcePath)) {
|
|
191894
191113
|
const legacy = parseLegacyMarkdown(raw);
|
|
191895
191114
|
content = legacy.content;
|
|
@@ -191912,7 +191131,7 @@ function resolvePromptSource(rootDir, source) {
|
|
|
191912
191131
|
const depAbs = safePath(root, dependency.path);
|
|
191913
191132
|
files.add(depAbs);
|
|
191914
191133
|
if (typeof dependency.selector?.pointer === "string") {
|
|
191915
|
-
const parsed = parseStructured(
|
|
191134
|
+
const parsed = parseStructured(readFileSync11(depAbs, "utf8"), dependency.path, extname3(depAbs).toLowerCase());
|
|
191916
191135
|
jsonPointer(parsed, dependency.selector.pointer, dependency.path);
|
|
191917
191136
|
} else if (dependency.selector?.symbol && CODE_EXTENSIONS2.has(extname3(depAbs).toLowerCase())) {
|
|
191918
191137
|
const dep = extname3(depAbs).toLowerCase() === ".py" ? extractPythonSource(root, depAbs, dependency.selector.symbol) : extractCodeSource(root, depAbs, dependency.selector.symbol);
|
|
@@ -191935,7 +191154,7 @@ function resolvePromptSource(rootDir, source) {
|
|
|
191935
191154
|
assertSafeMaterializedContent(content, sourcePath);
|
|
191936
191155
|
else
|
|
191937
191156
|
assertSafeMaterializedContent(materialized, sourcePath);
|
|
191938
|
-
const dependencies = [...files].sort().map((path) => ({ path: relative5(root, path).replaceAll("\\", "/"), contentHash: sha2562(
|
|
191157
|
+
const dependencies = [...files].sort().map((path) => ({ path: relative5(root, path).replaceAll("\\", "/"), contentHash: sha2562(readFileSync11(path)) }));
|
|
191939
191158
|
const sourceHash = sha2562(JSON.stringify({ kind, content, systemPrompt: systemPrompt ?? null, messages: messages ?? null }));
|
|
191940
191159
|
const sourceDefinition = {
|
|
191941
191160
|
schemaVersion: 1,
|
|
@@ -192005,7 +191224,7 @@ function discoverStructuredPromptSources(rootDir, sourcePath) {
|
|
|
192005
191224
|
const ext = extname3(file).toLowerCase();
|
|
192006
191225
|
if (![".json", ".yaml", ".yml"].includes(ext))
|
|
192007
191226
|
return [];
|
|
192008
|
-
const value = parseStructured(
|
|
191227
|
+
const value = parseStructured(readFileSync11(file, "utf8"), sourcePath, ext);
|
|
192009
191228
|
const sources = [];
|
|
192010
191229
|
const base = sourcePath.replace(/\.[^.]+$/, "").replace(/[^A-Za-z0-9_.-]+/g, ".");
|
|
192011
191230
|
const dedicatedPath = /(^|\/)prompts?(?:\/|\.[^/]+$)|\.prompt\.[^.]+$/i.test(sourcePath);
|
|
@@ -192081,14 +191300,14 @@ function discoverCodePromptCandidates(rootDir, sourcePath) {
|
|
|
192081
191300
|
addName(candidate.symbol, candidate.knownBuilder === true);
|
|
192082
191301
|
modelInputs.add(candidate.symbol);
|
|
192083
191302
|
}
|
|
192084
|
-
for (const match of
|
|
191303
|
+
for (const match of readFileSync11(file, "utf8").matchAll(/^(?:(?:async\s+)?def\s+([A-Za-z_]\w*)|([A-Za-z_]\w*)\s*=\s*([^\n#]+))/gm)) {
|
|
192085
191304
|
const name = match[1] ?? match[2];
|
|
192086
191305
|
const rhs = match[3] ?? "";
|
|
192087
191306
|
if (name && isPromptName2(name) && (match[1] || /['"`\[({+]/.test(rhs) || /^[A-Za-z_]\w*\s*$/.test(rhs)))
|
|
192088
191307
|
addName(name, Boolean(match[1]));
|
|
192089
191308
|
}
|
|
192090
191309
|
} else {
|
|
192091
|
-
const sf = import_typescript2.default.createSourceFile(file,
|
|
191310
|
+
const sf = import_typescript2.default.createSourceFile(file, readFileSync11(file, "utf8"), import_typescript2.default.ScriptTarget.Latest, true, import_typescript2.default.ScriptKind.TSX);
|
|
192092
191311
|
const agentConstructors = new Set;
|
|
192093
191312
|
for (const statement of sf.statements) {
|
|
192094
191313
|
if (!import_typescript2.default.isImportDeclaration(statement) || !import_typescript2.default.isStringLiteral(statement.moduleSpecifier) || !TYPESCRIPT_AGENT_MODULES.includes(statement.moduleSpecifier.text))
|
|
@@ -192270,13 +191489,13 @@ function jsonPointer(value, pointer, path) {
|
|
|
192270
191489
|
return current;
|
|
192271
191490
|
}
|
|
192272
191491
|
function safeRoot(dir) {
|
|
192273
|
-
const root = realpathSync8(
|
|
191492
|
+
const root = realpathSync8(resolve9(dir));
|
|
192274
191493
|
if (!lstatSync7(root).isDirectory())
|
|
192275
191494
|
throw new Error(`Prompt source root is not a directory: ${dir}`);
|
|
192276
191495
|
return root;
|
|
192277
191496
|
}
|
|
192278
191497
|
function safePath(root, requested) {
|
|
192279
|
-
const candidate =
|
|
191498
|
+
const candidate = resolve9(root, requested);
|
|
192280
191499
|
rejectSymlinkPath(root, candidate, requested);
|
|
192281
191500
|
const real = realpathSync8(candidate);
|
|
192282
191501
|
if (!(real === root || real.startsWith(`${root}/`)))
|
|
@@ -192322,12 +191541,12 @@ function sha2562(input) {
|
|
|
192322
191541
|
}
|
|
192323
191542
|
|
|
192324
191543
|
// src/prompt-source-verification/index.ts
|
|
192325
|
-
import { readFileSync as
|
|
191544
|
+
import { readFileSync as readFileSync15 } from "node:fs";
|
|
192326
191545
|
import { z } from "zod";
|
|
192327
191546
|
|
|
192328
191547
|
// src/prompt-source-validation.ts
|
|
192329
191548
|
import { existsSync as existsSync9, lstatSync as lstatSync8 } from "node:fs";
|
|
192330
|
-
import { extname as extname4, relative as relative6, resolve as
|
|
191549
|
+
import { extname as extname4, relative as relative6, resolve as resolve10 } from "node:path";
|
|
192331
191550
|
function checkPromptMapping(rootDir, unknownMapping) {
|
|
192332
191551
|
const repairs = [];
|
|
192333
191552
|
const unresolved = [];
|
|
@@ -192343,10 +191562,10 @@ function checkPromptMapping(rootDir, unknownMapping) {
|
|
|
192343
191562
|
if (JSON.stringify(normalized) !== JSON.stringify(sourceValue))
|
|
192344
191563
|
repairs.push("Omitted empty selector/dependency containers");
|
|
192345
191564
|
const source = validatePromptSource(normalized);
|
|
192346
|
-
const absolute =
|
|
191565
|
+
const absolute = resolve10(rootDir, source.path);
|
|
192347
191566
|
if (!existsSync9(absolute) || !lstatSync8(absolute).isFile())
|
|
192348
191567
|
throw new Error(`${source.path}: source path is unavailable`);
|
|
192349
|
-
const rel2 = relative6(
|
|
191568
|
+
const rel2 = relative6(resolve10(rootDir), absolute).replaceAll("\\", "/");
|
|
192350
191569
|
if (rel2 !== source.path)
|
|
192351
191570
|
repairs.push(`normalized path to ${rel2}`);
|
|
192352
191571
|
let selected = { ...source, path: rel2 };
|
|
@@ -192411,23 +191630,23 @@ function isPromptDefinitionPath(path) {
|
|
|
192411
191630
|
}
|
|
192412
191631
|
|
|
192413
191632
|
// src/prompt-source-verification/evidence.ts
|
|
192414
|
-
import { readFileSync as
|
|
191633
|
+
import { readFileSync as readFileSync14 } from "node:fs";
|
|
192415
191634
|
import { extname as extname7 } from "node:path";
|
|
192416
191635
|
|
|
192417
191636
|
// src/prompt-source-verification/paths.ts
|
|
192418
191637
|
import { lstatSync as lstatSync9, realpathSync as realpathSync9 } from "node:fs";
|
|
192419
|
-
import { isAbsolute as isAbsolute5, relative as relative7, resolve as
|
|
191638
|
+
import { isAbsolute as isAbsolute5, relative as relative7, resolve as resolve11, sep as sep4 } from "node:path";
|
|
192420
191639
|
function safePromptEvidencePath(rootDir, path) {
|
|
192421
191640
|
const root = realpathSync9(rootDir);
|
|
192422
191641
|
if (!path || isAbsolute5(path))
|
|
192423
191642
|
throw new Error("Evidence path must be repository-relative");
|
|
192424
|
-
const absolute =
|
|
191643
|
+
const absolute = resolve11(root, path);
|
|
192425
191644
|
const rel2 = relative7(root, absolute);
|
|
192426
191645
|
if (!rel2 || rel2 === ".." || rel2.startsWith(`..${sep4}`) || isAbsolute5(rel2))
|
|
192427
191646
|
throw new Error("Evidence escapes repository");
|
|
192428
191647
|
let current = root;
|
|
192429
191648
|
for (const part of rel2.split(sep4)) {
|
|
192430
|
-
current =
|
|
191649
|
+
current = resolve11(current, part);
|
|
192431
191650
|
if (lstatSync9(current).isSymbolicLink())
|
|
192432
191651
|
throw new Error("Evidence path is symlinked");
|
|
192433
191652
|
}
|
|
@@ -192441,14 +191660,14 @@ function safePromptEvidencePath(rootDir, path) {
|
|
|
192441
191660
|
var import_typescript3 = __toESM(require_typescript(), 1);
|
|
192442
191661
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
192443
191662
|
import { extname as extname5 } from "node:path";
|
|
192444
|
-
import { readFileSync as
|
|
191663
|
+
import { readFileSync as readFileSync12 } from "node:fs";
|
|
192445
191664
|
function proveSink(root, sink) {
|
|
192446
191665
|
const file = safePromptEvidencePath(root, sink.path);
|
|
192447
191666
|
const cache = new Map;
|
|
192448
191667
|
if (!cache.has(file)) {
|
|
192449
191668
|
if (extname5(file) === ".py") {
|
|
192450
191669
|
try {
|
|
192451
|
-
const rows = JSON.parse(execFileSync2("python3", ["-I", "-c", PYTHON_PROOF], { input:
|
|
191670
|
+
const rows = JSON.parse(execFileSync2("python3", ["-I", "-c", PYTHON_PROOF], { input: readFileSync12(file, "utf8"), encoding: "utf8", timeout: 1e4, maxBuffer: 2 * 1024 * 1024 }));
|
|
192452
191671
|
cache.set(file, new Map(Object.entries(rows).map(([line, proof]) => [Number(line), proof])));
|
|
192453
191672
|
} catch {
|
|
192454
191673
|
cache.set(file, new Map);
|
|
@@ -192615,7 +191834,7 @@ print(json.dumps(rows))
|
|
|
192615
191834
|
`;
|
|
192616
191835
|
|
|
192617
191836
|
// src/prompt-source-location.ts
|
|
192618
|
-
import { readFileSync as
|
|
191837
|
+
import { readFileSync as readFileSync13 } from "node:fs";
|
|
192619
191838
|
import { extname as extname6 } from "node:path";
|
|
192620
191839
|
function structuredExcerpt(text, source) {
|
|
192621
191840
|
if (source.selector?.pointer === undefined)
|
|
@@ -192669,7 +191888,7 @@ function promptDefinitionExcerpt(rootDir, source) {
|
|
|
192669
191888
|
return;
|
|
192670
191889
|
return { ...extraction.range, text: extraction.sourceText, ...extraction.declarationKind ? { declarationKind: extraction.declarationKind } : {} };
|
|
192671
191890
|
}
|
|
192672
|
-
const text =
|
|
191891
|
+
const text = readFileSync13(file, "utf8");
|
|
192673
191892
|
return structuredExcerpt(text, source);
|
|
192674
191893
|
}
|
|
192675
191894
|
function promptDefinitionRange(rootDir, source) {
|
|
@@ -192696,7 +191915,7 @@ function reviewEvidence(rootDir, source, evidence) {
|
|
|
192696
191915
|
for (const item of evidence) {
|
|
192697
191916
|
let text;
|
|
192698
191917
|
try {
|
|
192699
|
-
text =
|
|
191918
|
+
text = readFileSync14(safePromptEvidencePath(rootDir, item.path), "utf8");
|
|
192700
191919
|
} catch (error) {
|
|
192701
191920
|
if (item.kind === "model_endpoint")
|
|
192702
191921
|
return { valid: false, endpointVerified: false, reason: error instanceof Error ? error.message : String(error) };
|
|
@@ -192811,7 +192030,7 @@ async function independentlyVerifyPromptSource(rootDir, source, verifier) {
|
|
|
192811
192030
|
let priorJudgment;
|
|
192812
192031
|
try {
|
|
192813
192032
|
const before = JSON.stringify(checked.resolved.sourceDefinition);
|
|
192814
|
-
const sourceBytes =
|
|
192033
|
+
const sourceBytes = readFileSync15(safePromptEvidencePath(rootDir, source.path), "utf8");
|
|
192815
192034
|
const instruction = promptVerificationInstruction(checked.source, checked.sourceHash, promptDefinitionExcerpt(rootDir, checked.source));
|
|
192816
192035
|
for (let attempt = 0;attempt < 2; attempt++) {
|
|
192817
192036
|
const repair = attempt ? `
|
|
@@ -192842,7 +192061,7 @@ ${output}` : "";
|
|
|
192842
192061
|
}
|
|
192843
192062
|
if (reviewed.truncated || reviewed.sourceHash !== checked.sourceHash)
|
|
192844
192063
|
return pending("Verifier output is truncated or cites a different source hash", reviewed.evidence, reviewed.role, normalizeUsage(undefined, false));
|
|
192845
|
-
if (before !== snapshot() ||
|
|
192064
|
+
if (before !== snapshot() || readFileSync15(safePromptEvidencePath(rootDir, source.path), "utf8") !== sourceBytes)
|
|
192846
192065
|
return pending("Source changed during verification", reviewed.evidence, reviewed.role, normalizeUsage(undefined, false));
|
|
192847
192066
|
if (reviewed.role === "non_prompt")
|
|
192848
192067
|
return { status: "rejected", reason: reviewed.reason, evidence: reviewed.evidence, sourceHash: checked.sourceHash, role: reviewed.role, usage: normalizeUsage(undefined, false) };
|
|
@@ -193202,8 +192421,8 @@ function applyPromptDiscovery(graph, discovery) {
|
|
|
193202
192421
|
}
|
|
193203
192422
|
|
|
193204
192423
|
// src/harness-candidate-promotion.ts
|
|
193205
|
-
import { readFileSync as
|
|
193206
|
-
import { resolve as
|
|
192424
|
+
import { readFileSync as readFileSync16 } from "node:fs";
|
|
192425
|
+
import { resolve as resolve12 } from "node:path";
|
|
193207
192426
|
var PROMOTED_CONFIDENCE = {
|
|
193208
192427
|
high: 0.85,
|
|
193209
192428
|
medium: 0.6
|
|
@@ -193233,7 +192452,7 @@ function readFileLines(rootDir, path, cache) {
|
|
|
193233
192452
|
return cached;
|
|
193234
192453
|
let lines;
|
|
193235
192454
|
try {
|
|
193236
|
-
lines =
|
|
192455
|
+
lines = readFileSync16(resolve12(rootDir, path), "utf8").split(/\r?\n/);
|
|
193237
192456
|
} catch {
|
|
193238
192457
|
lines = null;
|
|
193239
192458
|
}
|
|
@@ -194516,7 +193735,7 @@ async function runHarnessCommand(context) {
|
|
|
194516
193735
|
return runHarnessRegister(context);
|
|
194517
193736
|
if (subcommand === "registration")
|
|
194518
193737
|
return runHarnessRegistration(context);
|
|
194519
|
-
const rootDir =
|
|
193738
|
+
const rootDir = resolve13(context.cwd, context.flags.path ?? ".");
|
|
194520
193739
|
const selectedAgentId = selectedRuntimeAgentId(context.flags);
|
|
194521
193740
|
const tenant = resolveHarnessTenant(context.flags, context);
|
|
194522
193741
|
const scanPlan = buildCommandScanPlan(context, rootDir);
|
|
@@ -194712,11 +193931,11 @@ async function runHarnessCommand(context) {
|
|
|
194712
193931
|
if (!idOrKey) {
|
|
194713
193932
|
throw new CliInputError("Missing harness id or key to delete.", "Usage: moda harness delete <harness-id-or-key> [--yes]");
|
|
194714
193933
|
}
|
|
194715
|
-
const
|
|
194716
|
-
if (!resolveApiKey(
|
|
193934
|
+
const profileOptions = { profile: context.profile, env: context.env };
|
|
193935
|
+
if (!resolveApiKey(profileOptions) && !context.dryRun) {
|
|
194717
193936
|
throw new CliInputError("No Moda API key found for harness delete.", "Run `moda init` first, set MODA_API_KEY, or select a profile with an API key.");
|
|
194718
193937
|
}
|
|
194719
|
-
const identity3 = describeSyncIdentity(
|
|
193938
|
+
const identity3 = describeSyncIdentity(profileOptions);
|
|
194720
193939
|
if (identity3) {
|
|
194721
193940
|
const label = identity3.tenantSource === "api-key" ? describeSyncTenantLabel(identity3) : describeSyncTenantLabel({
|
|
194722
193941
|
tenantId: tenant?.tenantId ?? identity3.tenantId,
|
|
@@ -194734,7 +193953,7 @@ async function runHarnessCommand(context) {
|
|
|
194734
193953
|
return { exitCode: 0 };
|
|
194735
193954
|
}
|
|
194736
193955
|
await confirmHarnessDelete(context, idOrKey);
|
|
194737
|
-
const response = await callControlAPI(`/harnesses/${encodeURIComponent(idOrKey)}`, { method: "DELETE" },
|
|
193956
|
+
const response = await callControlAPI(`/harnesses/${encodeURIComponent(idOrKey)}`, { method: "DELETE" }, profileOptions);
|
|
194738
193957
|
writeHumanProgress(context, `Deleted harness ${response.harnessKey ?? idOrKey} from tenant ${response.tenantId ?? "unknown"} ` + `(${response.deleted?.versions ?? 0} versions, ${response.deleted?.agents ?? 0} agents, ` + `${response.deleted?.artifacts ?? 0} artifacts, ${response.deleted?.relationships ?? 0} relationships).`);
|
|
194739
193958
|
context.output.writeData({ ...response, dryRun: false });
|
|
194740
193959
|
return { exitCode: 0 };
|
|
@@ -194777,7 +193996,7 @@ async function runHarnessCommand(context) {
|
|
|
194777
193996
|
throw new CliInputError("Focused remote prompt analysis is not supported yet.", "Use local --analyst=claude|codex|cursor|local-scan, or drop --concern for a full remote report.");
|
|
194778
193997
|
}
|
|
194779
193998
|
if (context.flags["github-actions"] === "true") {
|
|
194780
|
-
const { runGithubActionsAnalyze } = await import("./harness-github-actions-
|
|
193999
|
+
const { runGithubActionsAnalyze } = await import("./harness-github-actions-mtksqp3c.js");
|
|
194781
194000
|
const result = await runGithubActionsAnalyze(rootDir, {
|
|
194782
194001
|
writeReport: (report2) => {
|
|
194783
194002
|
const normalized = normalizeHarnessReport(report2);
|
|
@@ -194919,7 +194138,7 @@ async function runHarnessCommand(context) {
|
|
|
194919
194138
|
throw new CliInputError("Missing output path for --out.", "Usage: moda harness candidates --out=<file>");
|
|
194920
194139
|
}
|
|
194921
194140
|
if (outFlag && !context.dryRun) {
|
|
194922
|
-
written.push(writeHarnessCandidatesReport(report,
|
|
194141
|
+
written.push(writeHarnessCandidatesReport(report, resolve13(context.cwd, outFlag)));
|
|
194923
194142
|
}
|
|
194924
194143
|
writeHumanProgress(context, `Harness candidates: ${report.stats.candidateCount} candidates across ${report.stats.filesWithCandidates} files (${report.stats.filesScanned} scanned, ${report.stats.filesPerSecond.toLocaleString()} files/sec).`);
|
|
194925
194144
|
context.output.writeData({ scanPlan, ...report, written, dryRun: context.dryRun });
|
|
@@ -195018,8 +194237,8 @@ async function runHarnessCommand(context) {
|
|
|
195018
194237
|
if (context.flags[flag] === "true")
|
|
195019
194238
|
throw new CliInputError(`--${flag} needs a value.`);
|
|
195020
194239
|
}
|
|
195021
|
-
const
|
|
195022
|
-
if (!resolveApiKey(
|
|
194240
|
+
const profileOptions = { profile: context.profile, env: context.env };
|
|
194241
|
+
if (!resolveApiKey(profileOptions)) {
|
|
195023
194242
|
throw new CliInputError(`No Moda API key found for harness ${subcommand}.`, "Set MODA_API_KEY, run `moda auth login --api-key`, or select a profile with an API key.");
|
|
195024
194243
|
}
|
|
195025
194244
|
const query = new URLSearchParams;
|
|
@@ -195039,7 +194258,7 @@ async function runHarnessCommand(context) {
|
|
|
195039
194258
|
query.set("to", context.flags.to);
|
|
195040
194259
|
const suffix = query.toString() ? `?${query.toString()}` : "";
|
|
195041
194260
|
const path = subcommand === "list" ? `/harnesses${suffix}` : `/harnesses/${encodeURIComponent(idOrKey)}${subcommand === "show" ? "" : `/${subcommand}`}${suffix}`;
|
|
195042
|
-
context.output.writeData(await callControlAPI(path, {},
|
|
194261
|
+
context.output.writeData(await callControlAPI(path, {}, profileOptions));
|
|
195043
194262
|
return { exitCode: 0 };
|
|
195044
194263
|
}
|
|
195045
194264
|
default:
|
|
@@ -195111,7 +194330,7 @@ async function runPromptConcernAnalysis(context, rootDir, scanPlan, tenant) {
|
|
|
195111
194330
|
const manifest = join10(rootDir, ".moda/prompts.yml");
|
|
195112
194331
|
let existing = [];
|
|
195113
194332
|
if (existsSync10(manifest)) {
|
|
195114
|
-
const document = $parseDocument(
|
|
194333
|
+
const document = $parseDocument(readFileSync17(manifest, "utf8"));
|
|
195115
194334
|
if (document.errors.length)
|
|
195116
194335
|
throw new CliInputError("Invalid prompt manifest.", document.errors[0].message);
|
|
195117
194336
|
existing = document.toJS({ maxAliasCount: 20 })?.sources ?? [];
|
|
@@ -195340,7 +194559,7 @@ function buildExternalAnalystEnv(env) {
|
|
|
195340
194559
|
return next;
|
|
195341
194560
|
}
|
|
195342
194561
|
function readExternalAnalystReport(rootDir, result, adapter, concern) {
|
|
195343
|
-
const reportPath =
|
|
194562
|
+
const reportPath = resolve13(rootDir, HARNESS_REPORT_PATH);
|
|
195344
194563
|
if (existsSync10(reportPath))
|
|
195345
194564
|
return repairExternalAnalystReport(readHarnessReport(reportPath), rootDir, { concern });
|
|
195346
194565
|
const output = [
|
|
@@ -195355,7 +194574,7 @@ function readExternalAnalystReport(rootDir, result, adapter, concern) {
|
|
|
195355
194574
|
return parsed;
|
|
195356
194575
|
let debugHint = "";
|
|
195357
194576
|
try {
|
|
195358
|
-
const debugPath =
|
|
194577
|
+
const debugPath = resolve13(rootDir, MODA_DIR, "analyst-debug.log");
|
|
195359
194578
|
mkdirSync6(dirname9(debugPath), { recursive: true });
|
|
195360
194579
|
writeFileSync6(debugPath, [
|
|
195361
194580
|
`# analyst=${adapter} status=${result.status} signal=${result.signal} timedOut=${result.timedOut} maxBufferExceeded=${result.maxBufferExceeded}`,
|
|
@@ -195577,12 +194796,12 @@ function repairCitationLines(report, rootDir) {
|
|
|
195577
194796
|
if (citation.type !== "file" && citation.type !== "generated_doc" || !citation.path || !citation.excerpt)
|
|
195578
194797
|
continue;
|
|
195579
194798
|
const excerpt2 = citation.excerpt;
|
|
195580
|
-
const candidatePath =
|
|
194799
|
+
const candidatePath = resolve13(rootDir, citation.path);
|
|
195581
194800
|
if (!existsSync10(candidatePath))
|
|
195582
194801
|
continue;
|
|
195583
194802
|
let text;
|
|
195584
194803
|
try {
|
|
195585
|
-
text =
|
|
194804
|
+
text = readFileSync17(candidatePath, "utf8");
|
|
195586
194805
|
} catch {
|
|
195587
194806
|
continue;
|
|
195588
194807
|
}
|
|
@@ -196182,8 +195401,8 @@ function resolveExternalHarnessAnalystInvocation(options) {
|
|
|
196182
195401
|
}
|
|
196183
195402
|
function createPromptAnalystIsolation(adapter, rootDir) {
|
|
196184
195403
|
const moduleDir = dirname9(fileURLToPath(import.meta.url));
|
|
196185
|
-
const bundled =
|
|
196186
|
-
const source =
|
|
195404
|
+
const bundled = resolve13(moduleDir, "prompt-source-mcp.js");
|
|
195405
|
+
const source = resolve13(moduleDir, "prompt-source-mcp.ts");
|
|
196187
195406
|
const bundledServer = existsSync10(bundled);
|
|
196188
195407
|
const serverPath = bundledServer ? bundled : source;
|
|
196189
195408
|
const command = bundledServer ? process.execPath : resolveBunRuntime();
|
|
@@ -196693,11 +195912,11 @@ function splitCommandLine(commandLine) {
|
|
|
196693
195912
|
return commandLine.trim().split(/\s+/).filter(Boolean);
|
|
196694
195913
|
}
|
|
196695
195914
|
function truncateText(value, maxLength) {
|
|
196696
|
-
const
|
|
196697
|
-
return
|
|
195915
|
+
const compact = value.replace(/\s+/g, " ").trim();
|
|
195916
|
+
return compact.length > maxLength ? `${compact.slice(0, maxLength - 1)}...` : compact;
|
|
196698
195917
|
}
|
|
196699
195918
|
function scanHarness(options = {}) {
|
|
196700
|
-
const rootDir =
|
|
195919
|
+
const rootDir = resolve13(options.rootDir ?? process.cwd());
|
|
196701
195920
|
const skipped = [];
|
|
196702
195921
|
const files = inventoryFiles(rootDir, skipped);
|
|
196703
195922
|
const annotations = files.flatMap((file) => parseAnnotations(file));
|
|
@@ -196799,7 +196018,7 @@ function collectSnapshotInputs(rootDir, maxFiles, maxTextBytes) {
|
|
|
196799
196018
|
let text = "";
|
|
196800
196019
|
if (isTextFile(path)) {
|
|
196801
196020
|
try {
|
|
196802
|
-
text =
|
|
196021
|
+
text = readFileSync17(current, "utf8");
|
|
196803
196022
|
inventoryTextBytes += Buffer.byteLength(text, "utf8");
|
|
196804
196023
|
} catch {
|
|
196805
196024
|
return;
|
|
@@ -196812,7 +196031,7 @@ function collectSnapshotInputs(rootDir, maxFiles, maxTextBytes) {
|
|
|
196812
196031
|
return inputs;
|
|
196813
196032
|
}
|
|
196814
196033
|
function buildSourceSnapshot(rootDir) {
|
|
196815
|
-
const root2 =
|
|
196034
|
+
const root2 = resolve13(rootDir);
|
|
196816
196035
|
const maxFiles = numericEnv("MODA_HARNESS_MAX_FILES", DEFAULT_MAX_INVENTORY_FILES);
|
|
196817
196036
|
const maxTextBytes = numericEnv("MODA_HARNESS_MAX_TEXT_BYTES", DEFAULT_MAX_INVENTORY_TEXT_BYTES);
|
|
196818
196037
|
const inputs = collectSnapshotInputs(root2, maxFiles, maxTextBytes);
|
|
@@ -197022,8 +196241,8 @@ function plannedDryRunRemote(plan) {
|
|
|
197022
196241
|
}
|
|
197023
196242
|
async function syncHarnessWithRemote(context, body) {
|
|
197024
196243
|
assertHarnessGraphSyncSize(body.graph);
|
|
197025
|
-
const
|
|
197026
|
-
const hasApiKey = Boolean(resolveApiKey(
|
|
196244
|
+
const profileOptions = { profile: context.profile, env: context.env };
|
|
196245
|
+
const hasApiKey = Boolean(resolveApiKey(profileOptions));
|
|
197027
196246
|
if (context.dryRun && !hasApiKey)
|
|
197028
196247
|
return;
|
|
197029
196248
|
return await callControlAPI("/harnesses/sync", {
|
|
@@ -197032,14 +196251,14 @@ async function syncHarnessWithRemote(context, body) {
|
|
|
197032
196251
|
...body,
|
|
197033
196252
|
dryRun: context.dryRun
|
|
197034
196253
|
})
|
|
197035
|
-
},
|
|
196254
|
+
}, profileOptions);
|
|
197036
196255
|
}
|
|
197037
196256
|
function readHarnessSyncState(rootDir) {
|
|
197038
196257
|
const path = join10(rootDir, SYNC_STATE_PATH);
|
|
197039
196258
|
if (!existsSync10(path))
|
|
197040
196259
|
return;
|
|
197041
196260
|
try {
|
|
197042
|
-
const parsed = JSON.parse(
|
|
196261
|
+
const parsed = JSON.parse(readFileSync17(path, "utf8"));
|
|
197043
196262
|
if (!isRecord4(parsed) || parsed.schemaVersion !== "sync_state.v0.1") {
|
|
197044
196263
|
return;
|
|
197045
196264
|
}
|
|
@@ -197156,7 +196375,7 @@ function findFresherHarnessReports(rootDir) {
|
|
|
197156
196375
|
return fresher.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
197157
196376
|
}
|
|
197158
196377
|
function warnFresherSubdirHarnessReports(context, rootDir, explicitReport) {
|
|
197159
|
-
const explicitReportPath = explicitReport && explicitReport !== "true" ? normalizePath3(relative8(rootDir,
|
|
196378
|
+
const explicitReportPath = explicitReport && explicitReport !== "true" ? normalizePath3(relative8(rootDir, resolve13(rootDir, explicitReport))) : undefined;
|
|
197160
196379
|
if (explicitReportPath && explicitReportPath !== normalizePath3(HARNESS_REPORT_PATH))
|
|
197161
196380
|
return;
|
|
197162
196381
|
let fresher;
|
|
@@ -197173,7 +196392,7 @@ function warnFresherSubdirHarnessReports(context, rootDir, explicitReport) {
|
|
|
197173
196392
|
writeHarnessNotice(context, `A fresher harness report exists at ${newest.path} (this directory has ${rootState}). If you meant that report, re-run with --path=${subdir}.`);
|
|
197174
196393
|
}
|
|
197175
196394
|
function readHarnessGraph(manifestPath) {
|
|
197176
|
-
return JSON.parse(
|
|
196395
|
+
return JSON.parse(readFileSync17(manifestPath, "utf8"));
|
|
197177
196396
|
}
|
|
197178
196397
|
function writeHarnessArtifacts(graph, rootDir, options = {}) {
|
|
197179
196398
|
const modaDir = join10(rootDir, MODA_DIR);
|
|
@@ -197358,7 +196577,7 @@ function explainAgent(graph, agent) {
|
|
|
197358
196577
|
}
|
|
197359
196578
|
function inventoryFiles(rootDir, skipped, options = {}) {
|
|
197360
196579
|
const files = [];
|
|
197361
|
-
const rootReal =
|
|
196580
|
+
const rootReal = resolve13(rootDir);
|
|
197362
196581
|
const maxFiles = numericEnv("MODA_HARNESS_MAX_FILES", DEFAULT_MAX_INVENTORY_FILES);
|
|
197363
196582
|
const maxTextBytes = numericEnv("MODA_HARNESS_MAX_TEXT_BYTES", DEFAULT_MAX_INVENTORY_TEXT_BYTES);
|
|
197364
196583
|
let textBytes = 0;
|
|
@@ -197412,7 +196631,7 @@ function inventoryFiles(rootDir, skipped, options = {}) {
|
|
|
197412
196631
|
recordSkipped(skipped, { path: rel2, reason: "scan text budget exceeded" });
|
|
197413
196632
|
} else {
|
|
197414
196633
|
try {
|
|
197415
|
-
item.text =
|
|
196634
|
+
item.text = readFileSync17(current, "utf8");
|
|
197416
196635
|
textBytes += Buffer.byteLength(item.text, "utf8");
|
|
197417
196636
|
} catch {
|
|
197418
196637
|
recordSkipped(skipped, { path: rel2, reason: "text read failed" });
|
|
@@ -197719,7 +196938,7 @@ function maybeAddPromptArtifact(graph, file) {
|
|
|
197719
196938
|
if (!isPrompt)
|
|
197720
196939
|
return;
|
|
197721
196940
|
const id = stableId2("prompt", file.path);
|
|
197722
|
-
const text = file.text ??
|
|
196941
|
+
const text = file.text ?? readFileSync17(file.absPath, "utf8");
|
|
197723
196942
|
upsertArtifact(graph, {
|
|
197724
196943
|
id,
|
|
197725
196944
|
type: "prompt",
|
|
@@ -198300,7 +197519,7 @@ function detectProviderPackagesInManifests(rootDir) {
|
|
|
198300
197519
|
const packageJsonPath = join10(rootDir, "package.json");
|
|
198301
197520
|
if (existsSync10(packageJsonPath)) {
|
|
198302
197521
|
try {
|
|
198303
|
-
const deps = packageDependencyNames(
|
|
197522
|
+
const deps = packageDependencyNames(readFileSync17(packageJsonPath, "utf8"));
|
|
198304
197523
|
for (const provider of PROVIDER_CATALOG) {
|
|
198305
197524
|
for (const name of provider.packageNames) {
|
|
198306
197525
|
if (deps.has(name))
|
|
@@ -198312,7 +197531,7 @@ function detectProviderPackagesInManifests(rootDir) {
|
|
|
198312
197531
|
const pyprojectPath = join10(rootDir, "pyproject.toml");
|
|
198313
197532
|
if (existsSync10(pyprojectPath)) {
|
|
198314
197533
|
try {
|
|
198315
|
-
const deps = pyprojectDependencyNames(
|
|
197534
|
+
const deps = pyprojectDependencyNames(readFileSync17(pyprojectPath, "utf8"));
|
|
198316
197535
|
for (const provider of PROVIDER_CATALOG) {
|
|
198317
197536
|
for (const name of provider.packageNames) {
|
|
198318
197537
|
if (deps.has(name.toLowerCase()))
|
|
@@ -198695,7 +197914,7 @@ function upsertDeployment(graph, next) {
|
|
|
198695
197914
|
}
|
|
198696
197915
|
function contentHashForAnnotatedSource(sourcePath, annotation) {
|
|
198697
197916
|
const bodyAnnotation = annotation;
|
|
198698
|
-
const rootCandidate =
|
|
197917
|
+
const rootCandidate = resolve13(annotation.rootDir, sourcePath);
|
|
198699
197918
|
const candidates = [
|
|
198700
197919
|
rootCandidate,
|
|
198701
197920
|
...annotatedSourceCandidates(sourcePath, bodyAnnotation).filter((c) => c !== rootCandidate)
|
|
@@ -198729,7 +197948,7 @@ function readSmallTextFileForHash(absPath, rootDir) {
|
|
|
198729
197948
|
if (!isTextFile(rel2))
|
|
198730
197949
|
return;
|
|
198731
197950
|
try {
|
|
198732
|
-
return
|
|
197951
|
+
return readFileSync17(absPath, "utf8");
|
|
198733
197952
|
} catch {
|
|
198734
197953
|
return;
|
|
198735
197954
|
}
|
|
@@ -198822,4 +198041,4 @@ function hashText(text) {
|
|
|
198822
198041
|
return createHash7("sha256").update(text).digest("hex");
|
|
198823
198042
|
}
|
|
198824
198043
|
|
|
198825
|
-
export {
|
|
198044
|
+
export { $isSeq, $parseDocument, $stringify, require_typescript, inspectCodeSelectors, inspectPythonSelectors, resolvePromptSource, backfillPromptSource, HARNESS_REPORT_PATH, HARNESS_REPORT_APPROVAL_PATH, HARNESS_ANALYZE_CONCERNS, validateHarnessReport, readHarnessReport, normalizeHarnessReport, hashHarnessReport, hashStableJson, startRemoteAnalyze, pollRemoteAnalyzeUntilDone, isRecoverableRemoteRun, checkPromptMapping, safePromptEvidencePath, discoverHarnessPromptSources, canonicalText, renderDoctorHuman, renderStatusHuman, renderInitBanner, renderInitStep, renderInitNote, renderInitSetupPlan, renderInitComplete, runHarnessCommand, writeHarnessAnalyzeResult, emitWrittenArtifacts, analyzeHarnessPrompts, repairExternalAnalystReport, deriveRelationshipsFromGraph, mergeDeterministicArtifacts, describeCodingAgentEvent, analystEventProgress, isRetryableExternalAnalystFailure, sleep, summarizeInvalidAnalystReport, isDeterministicLocalAnalyst, resolveHarnessAnalyzeConcern, detectAvailableCodingAgents, codingAgentDisplayName, runCodingAgent, resolveAnalystModel, renderExternalHarnessAnalystPrompt, CONCERN_CANDIDATE_KINDS, SEED_CANDIDATE_KIND_LABELS, renderAnalystCandidateLines, renderAnalystSeedLines, truncateText, scanHarness, summarizeHarness, buildSourceSnapshot, writeHumanProgress, readHarnessSyncState, describeSyncIdentity, describeSyncTenantLabel, findFresherHarnessReports, writeHarnessArtifacts, assertHarnessGraphSyncQuality, graphForSync, inventoryFiles, numericEnv, numericEnvAllowZero, computeDeterministicFloor, stableId2 as stableId, titleFromId2 as titleFromId, promptNameFromPath };
|