terminalhire 0.42.21 → 0.42.23
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/bin/jpi-claim.js +696 -181
- package/dist/bin/jpi-dispatch.js +819 -296
- package/dist/bin/jpi-mcp.js +703 -188
- package/dist/bin/jpi-run.js +600 -77
- package/dist/bin/proxy/egressProxy.js +25 -0
- package/package.json +1 -1
package/dist/bin/jpi-dispatch.js
CHANGED
|
@@ -3554,11 +3554,11 @@ function parseGitHubRef(url) {
|
|
|
3554
3554
|
kind: m[3] === "pull" ? "pull" : "issue"
|
|
3555
3555
|
};
|
|
3556
3556
|
}
|
|
3557
|
-
async function ghGraphQL(
|
|
3557
|
+
async function ghGraphQL(query2, variables, token, signal, governor) {
|
|
3558
3558
|
const init = {
|
|
3559
3559
|
method: "POST",
|
|
3560
3560
|
headers: { ...ghHeaders(token), "Content-Type": "application/json" },
|
|
3561
|
-
body: JSON.stringify({ query, variables }),
|
|
3561
|
+
body: JSON.stringify({ query: query2, variables }),
|
|
3562
3562
|
signal
|
|
3563
3563
|
};
|
|
3564
3564
|
if (governor) {
|
|
@@ -12927,9 +12927,9 @@ async function runLogin() {
|
|
|
12927
12927
|
let ghProfile;
|
|
12928
12928
|
if (process.env["TERMINALHIRE_GITHUB_MOCK"] === "1" || process.env["JPI_GITHUB_MOCK"] === "1") {
|
|
12929
12929
|
const { fileURLToPath: fileURLToPath15 } = await import("url");
|
|
12930
|
-
const { join:
|
|
12930
|
+
const { join: join63 } = await import("path");
|
|
12931
12931
|
const __dirname10 = fileURLToPath15(new URL(".", import.meta.url));
|
|
12932
|
-
const fixturePath =
|
|
12932
|
+
const fixturePath = join63(__dirname10, "../../fixtures/github-sample.json");
|
|
12933
12933
|
const { readFileSync: readFileSync43 } = await import("fs");
|
|
12934
12934
|
ghProfile = JSON.parse(readFileSync43(fixturePath, "utf8"));
|
|
12935
12935
|
} else {
|
|
@@ -18881,8 +18881,8 @@ var init_stringify = __esm({
|
|
|
18881
18881
|
});
|
|
18882
18882
|
|
|
18883
18883
|
// ../../node_modules/@anthropic-ai/sdk/internal/utils/query.mjs
|
|
18884
|
-
function stringifyQuery(
|
|
18885
|
-
return stringify(
|
|
18884
|
+
function stringifyQuery(query2) {
|
|
18885
|
+
return stringify(query2, { arrayFormat: "brackets" });
|
|
18886
18886
|
}
|
|
18887
18887
|
var init_query = __esm({
|
|
18888
18888
|
"../../node_modules/@anthropic-ai/sdk/internal/utils/query.mjs"() {
|
|
@@ -20966,9 +20966,9 @@ var init_deployment_runs = __esm({
|
|
|
20966
20966
|
* ```
|
|
20967
20967
|
*/
|
|
20968
20968
|
list(params = {}, options) {
|
|
20969
|
-
const { betas, ...
|
|
20969
|
+
const { betas, ...query2 } = params ?? {};
|
|
20970
20970
|
return this._client.getAPIList("/v1/deployment_runs?beta=true", PageCursor, {
|
|
20971
|
-
query,
|
|
20971
|
+
query: query2,
|
|
20972
20972
|
...options,
|
|
20973
20973
|
headers: buildHeaders([
|
|
20974
20974
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -21080,9 +21080,9 @@ var init_deployments = __esm({
|
|
|
21080
21080
|
* ```
|
|
21081
21081
|
*/
|
|
21082
21082
|
list(params = {}, options) {
|
|
21083
|
-
const { betas, ...
|
|
21083
|
+
const { betas, ...query2 } = params ?? {};
|
|
21084
21084
|
return this._client.getAPIList("/v1/deployments?beta=true", PageCursor, {
|
|
21085
|
-
query,
|
|
21085
|
+
query: query2,
|
|
21086
21086
|
...options,
|
|
21087
21087
|
headers: buildHeaders([
|
|
21088
21088
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -21242,9 +21242,9 @@ var init_dreams = __esm({
|
|
|
21242
21242
|
* ```
|
|
21243
21243
|
*/
|
|
21244
21244
|
list(params = {}, options) {
|
|
21245
|
-
const { betas, ...
|
|
21245
|
+
const { betas, ...query2 } = params ?? {};
|
|
21246
21246
|
return this._client.getAPIList("/v1/dreams?beta=true", PageCursor, {
|
|
21247
|
-
query,
|
|
21247
|
+
query: query2,
|
|
21248
21248
|
...options,
|
|
21249
21249
|
headers: buildHeaders([
|
|
21250
21250
|
{ "anthropic-beta": [...betas ?? [], "dreaming-2026-04-21"].toString() },
|
|
@@ -21375,9 +21375,9 @@ var init_files = __esm({
|
|
|
21375
21375
|
* ```
|
|
21376
21376
|
*/
|
|
21377
21377
|
list(params = {}, options) {
|
|
21378
|
-
const { betas, ...
|
|
21378
|
+
const { betas, ...query2 } = params ?? {};
|
|
21379
21379
|
return this._client.getAPIList("/v1/files?beta=true", Page, {
|
|
21380
|
-
query,
|
|
21380
|
+
query: query2,
|
|
21381
21381
|
...options,
|
|
21382
21382
|
headers: buildHeaders([
|
|
21383
21383
|
{ "anthropic-beta": [...betas ?? [], "files-api-2025-04-14"].toString() },
|
|
@@ -21525,9 +21525,9 @@ var init_models = __esm({
|
|
|
21525
21525
|
* ```
|
|
21526
21526
|
*/
|
|
21527
21527
|
list(params = {}, options) {
|
|
21528
|
-
const { betas, ...
|
|
21528
|
+
const { betas, ...query2 } = params ?? {};
|
|
21529
21529
|
return this._client.getAPIList("/v1/models?beta=true", Page, {
|
|
21530
|
-
query,
|
|
21530
|
+
query: query2,
|
|
21531
21531
|
...options,
|
|
21532
21532
|
headers: buildHeaders([
|
|
21533
21533
|
{ ...betas?.toString() != null ? { "anthropic-beta": betas?.toString() } : void 0 },
|
|
@@ -21624,9 +21624,9 @@ var init_user_profiles = __esm({
|
|
|
21624
21624
|
* ```
|
|
21625
21625
|
*/
|
|
21626
21626
|
list(params = {}, options) {
|
|
21627
|
-
const { betas, ...
|
|
21627
|
+
const { betas, ...query2 } = params ?? {};
|
|
21628
21628
|
return this._client.getAPIList("/v1/user_profiles?beta=true", PageCursor, {
|
|
21629
|
-
query,
|
|
21629
|
+
query: query2,
|
|
21630
21630
|
...options,
|
|
21631
21631
|
headers: buildHeaders([
|
|
21632
21632
|
{ "anthropic-beta": [...betas ?? [], "user-profiles-2026-03-24"].toString() },
|
|
@@ -22485,9 +22485,9 @@ var init_versions = __esm({
|
|
|
22485
22485
|
* ```
|
|
22486
22486
|
*/
|
|
22487
22487
|
list(agentID, params = {}, options) {
|
|
22488
|
-
const { betas, ...
|
|
22488
|
+
const { betas, ...query2 } = params ?? {};
|
|
22489
22489
|
return this._client.getAPIList(path`/v1/agents/${agentID}/versions?beta=true`, PageCursor, {
|
|
22490
|
-
query,
|
|
22490
|
+
query: query2,
|
|
22491
22491
|
...options,
|
|
22492
22492
|
headers: buildHeaders([
|
|
22493
22493
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -22550,9 +22550,9 @@ var init_agents = __esm({
|
|
|
22550
22550
|
* ```
|
|
22551
22551
|
*/
|
|
22552
22552
|
retrieve(agentID, params = {}, options) {
|
|
22553
|
-
const { betas, ...
|
|
22553
|
+
const { betas, ...query2 } = params ?? {};
|
|
22554
22554
|
return this._client.get(path`/v1/agents/${agentID}?beta=true`, {
|
|
22555
|
-
query,
|
|
22555
|
+
query: query2,
|
|
22556
22556
|
...options,
|
|
22557
22557
|
headers: buildHeaders([
|
|
22558
22558
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -22595,9 +22595,9 @@ var init_agents = __esm({
|
|
|
22595
22595
|
* ```
|
|
22596
22596
|
*/
|
|
22597
22597
|
list(params = {}, options) {
|
|
22598
|
-
const { betas, ...
|
|
22598
|
+
const { betas, ...query2 } = params ?? {};
|
|
22599
22599
|
return this._client.getAPIList("/v1/agents?beta=true", PageCursor, {
|
|
22600
|
-
query,
|
|
22600
|
+
query: query2,
|
|
22601
22601
|
...options,
|
|
22602
22602
|
headers: buildHeaders([
|
|
22603
22603
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -24687,9 +24687,9 @@ var init_work = __esm({
|
|
|
24687
24687
|
* ```
|
|
24688
24688
|
*/
|
|
24689
24689
|
list(environmentID, params = {}, options) {
|
|
24690
|
-
const { betas, ...
|
|
24690
|
+
const { betas, ...query2 } = params ?? {};
|
|
24691
24691
|
return this._client.getAPIList(path`/v1/environments/${environmentID}/work?beta=true`, PageCursor, {
|
|
24692
|
-
query,
|
|
24692
|
+
query: query2,
|
|
24693
24693
|
...options,
|
|
24694
24694
|
headers: buildHeaders([
|
|
24695
24695
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -24768,9 +24768,9 @@ var init_work = __esm({
|
|
|
24768
24768
|
* ```
|
|
24769
24769
|
*/
|
|
24770
24770
|
poll(environmentID, params = {}, options) {
|
|
24771
|
-
const { betas, "Anthropic-Worker-ID": anthropicWorkerID, ...
|
|
24771
|
+
const { betas, "Anthropic-Worker-ID": anthropicWorkerID, ...query2 } = params ?? {};
|
|
24772
24772
|
return this._client.get(path`/v1/environments/${environmentID}/work/poll?beta=true`, {
|
|
24773
|
-
query,
|
|
24773
|
+
query: query2,
|
|
24774
24774
|
...options,
|
|
24775
24775
|
headers: buildHeaders([
|
|
24776
24776
|
{
|
|
@@ -24967,9 +24967,9 @@ var init_environments = __esm({
|
|
|
24967
24967
|
* ```
|
|
24968
24968
|
*/
|
|
24969
24969
|
list(params = {}, options) {
|
|
24970
|
-
const { betas, ...
|
|
24970
|
+
const { betas, ...query2 } = params ?? {};
|
|
24971
24971
|
return this._client.getAPIList("/v1/environments?beta=true", PageCursor, {
|
|
24972
|
-
query,
|
|
24972
|
+
query: query2,
|
|
24973
24973
|
...options,
|
|
24974
24974
|
headers: buildHeaders([
|
|
24975
24975
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -25072,9 +25072,9 @@ var init_memories = __esm({
|
|
|
25072
25072
|
* ```
|
|
25073
25073
|
*/
|
|
25074
25074
|
retrieve(memoryID, params, options) {
|
|
25075
|
-
const { memory_store_id, betas, ...
|
|
25075
|
+
const { memory_store_id, betas, ...query2 } = params;
|
|
25076
25076
|
return this._client.get(path`/v1/memory_stores/${memory_store_id}/memories/${memoryID}?beta=true`, {
|
|
25077
|
-
query,
|
|
25077
|
+
query: query2,
|
|
25078
25078
|
...options,
|
|
25079
25079
|
headers: buildHeaders([
|
|
25080
25080
|
{ "anthropic-beta": [...betas ?? [], "agent-memory-2026-07-22"].toString() },
|
|
@@ -25120,9 +25120,9 @@ var init_memories = __esm({
|
|
|
25120
25120
|
* ```
|
|
25121
25121
|
*/
|
|
25122
25122
|
list(memoryStoreID, params = {}, options) {
|
|
25123
|
-
const { betas, ...
|
|
25123
|
+
const { betas, ...query2 } = params ?? {};
|
|
25124
25124
|
return this._client.getAPIList(path`/v1/memory_stores/${memoryStoreID}/memories?beta=true`, PageCursor, {
|
|
25125
|
-
query,
|
|
25125
|
+
query: query2,
|
|
25126
25126
|
...options,
|
|
25127
25127
|
headers: buildHeaders([
|
|
25128
25128
|
{ "anthropic-beta": [...betas ?? [], "agent-memory-2026-07-22"].toString() },
|
|
@@ -25180,9 +25180,9 @@ var init_memory_versions = __esm({
|
|
|
25180
25180
|
* ```
|
|
25181
25181
|
*/
|
|
25182
25182
|
retrieve(memoryVersionID, params, options) {
|
|
25183
|
-
const { memory_store_id, betas, ...
|
|
25183
|
+
const { memory_store_id, betas, ...query2 } = params;
|
|
25184
25184
|
return this._client.get(path`/v1/memory_stores/${memory_store_id}/memory_versions/${memoryVersionID}?beta=true`, {
|
|
25185
|
-
query,
|
|
25185
|
+
query: query2,
|
|
25186
25186
|
...options,
|
|
25187
25187
|
headers: buildHeaders([
|
|
25188
25188
|
{ "anthropic-beta": [...betas ?? [], "agent-memory-2026-07-22"].toString() },
|
|
@@ -25204,9 +25204,9 @@ var init_memory_versions = __esm({
|
|
|
25204
25204
|
* ```
|
|
25205
25205
|
*/
|
|
25206
25206
|
list(memoryStoreID, params = {}, options) {
|
|
25207
|
-
const { betas, ...
|
|
25207
|
+
const { betas, ...query2 } = params ?? {};
|
|
25208
25208
|
return this._client.getAPIList(path`/v1/memory_stores/${memoryStoreID}/memory_versions?beta=true`, PageCursor, {
|
|
25209
|
-
query,
|
|
25209
|
+
query: query2,
|
|
25210
25210
|
...options,
|
|
25211
25211
|
headers: buildHeaders([
|
|
25212
25212
|
{ "anthropic-beta": [...betas ?? [], "agent-memory-2026-07-22"].toString() },
|
|
@@ -25332,9 +25332,9 @@ var init_memory_stores = __esm({
|
|
|
25332
25332
|
* ```
|
|
25333
25333
|
*/
|
|
25334
25334
|
list(params = {}, options) {
|
|
25335
|
-
const { betas, ...
|
|
25335
|
+
const { betas, ...query2 } = params ?? {};
|
|
25336
25336
|
return this._client.getAPIList("/v1/memory_stores?beta=true", PageCursor, {
|
|
25337
|
-
query,
|
|
25337
|
+
query: query2,
|
|
25338
25338
|
...options,
|
|
25339
25339
|
headers: buildHeaders([
|
|
25340
25340
|
{ "anthropic-beta": [...betas ?? [], "agent-memory-2026-07-22"].toString() },
|
|
@@ -25532,9 +25532,9 @@ var init_batches = __esm({
|
|
|
25532
25532
|
* ```
|
|
25533
25533
|
*/
|
|
25534
25534
|
list(params = {}, options) {
|
|
25535
|
-
const { betas, ...
|
|
25535
|
+
const { betas, ...query2 } = params ?? {};
|
|
25536
25536
|
return this._client.getAPIList("/v1/messages/batches?beta=true", Page, {
|
|
25537
|
-
query,
|
|
25537
|
+
query: query2,
|
|
25538
25538
|
...options,
|
|
25539
25539
|
headers: buildHeaders([
|
|
25540
25540
|
{ "anthropic-beta": [...betas ?? [], "message-batches-2024-09-24"].toString() },
|
|
@@ -27207,9 +27207,9 @@ var init_events = __esm({
|
|
|
27207
27207
|
* ```
|
|
27208
27208
|
*/
|
|
27209
27209
|
list(sessionID, params = {}, options) {
|
|
27210
|
-
const { betas, ...
|
|
27210
|
+
const { betas, ...query2 } = params ?? {};
|
|
27211
27211
|
return this._client.getAPIList(path`/v1/sessions/${sessionID}/events?beta=true`, PageCursor, {
|
|
27212
|
-
query,
|
|
27212
|
+
query: query2,
|
|
27213
27213
|
...options,
|
|
27214
27214
|
headers: buildHeaders([
|
|
27215
27215
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -27264,9 +27264,9 @@ var init_events = __esm({
|
|
|
27264
27264
|
* ```
|
|
27265
27265
|
*/
|
|
27266
27266
|
stream(sessionID, params = {}, options) {
|
|
27267
|
-
const { betas, ...
|
|
27267
|
+
const { betas, ...query2 } = params ?? {};
|
|
27268
27268
|
return this._client.get(path`/v1/sessions/${sessionID}/events/stream?beta=true`, {
|
|
27269
|
-
query,
|
|
27269
|
+
query: query2,
|
|
27270
27270
|
...options,
|
|
27271
27271
|
headers: buildHeaders([
|
|
27272
27272
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -27374,9 +27374,9 @@ var init_resources = __esm({
|
|
|
27374
27374
|
* ```
|
|
27375
27375
|
*/
|
|
27376
27376
|
list(sessionID, params = {}, options) {
|
|
27377
|
-
const { betas, ...
|
|
27377
|
+
const { betas, ...query2 } = params ?? {};
|
|
27378
27378
|
return this._client.getAPIList(path`/v1/sessions/${sessionID}/resources?beta=true`, PageCursor, {
|
|
27379
|
-
query,
|
|
27379
|
+
query: query2,
|
|
27380
27380
|
...options,
|
|
27381
27381
|
headers: buildHeaders([
|
|
27382
27382
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -27461,9 +27461,9 @@ var init_events2 = __esm({
|
|
|
27461
27461
|
* ```
|
|
27462
27462
|
*/
|
|
27463
27463
|
list(threadID, params, options) {
|
|
27464
|
-
const { session_id, betas, ...
|
|
27464
|
+
const { session_id, betas, ...query2 } = params;
|
|
27465
27465
|
return this._client.getAPIList(path`/v1/sessions/${session_id}/threads/${threadID}/events?beta=true`, PageCursor, {
|
|
27466
|
-
query,
|
|
27466
|
+
query: query2,
|
|
27467
27467
|
...options,
|
|
27468
27468
|
headers: buildHeaders([
|
|
27469
27469
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -27550,9 +27550,9 @@ var init_threads = __esm({
|
|
|
27550
27550
|
* ```
|
|
27551
27551
|
*/
|
|
27552
27552
|
list(sessionID, params = {}, options) {
|
|
27553
|
-
const { betas, ...
|
|
27553
|
+
const { betas, ...query2 } = params ?? {};
|
|
27554
27554
|
return this._client.getAPIList(path`/v1/sessions/${sessionID}/threads?beta=true`, PageCursor, {
|
|
27555
|
-
query,
|
|
27555
|
+
query: query2,
|
|
27556
27556
|
...options,
|
|
27557
27557
|
headers: buildHeaders([
|
|
27558
27558
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -27687,9 +27687,9 @@ var init_sessions = __esm({
|
|
|
27687
27687
|
* ```
|
|
27688
27688
|
*/
|
|
27689
27689
|
list(params = {}, options) {
|
|
27690
|
-
const { betas, ...
|
|
27690
|
+
const { betas, ...query2 } = params ?? {};
|
|
27691
27691
|
return this._client.getAPIList("/v1/sessions?beta=true", BidirectionalPageCursor, {
|
|
27692
|
-
query,
|
|
27692
|
+
query: query2,
|
|
27693
27693
|
...options,
|
|
27694
27694
|
headers: buildHeaders([
|
|
27695
27695
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -27814,9 +27814,9 @@ var init_versions2 = __esm({
|
|
|
27814
27814
|
* ```
|
|
27815
27815
|
*/
|
|
27816
27816
|
list(skillID, params = {}, options) {
|
|
27817
|
-
const { betas, ...
|
|
27817
|
+
const { betas, ...query2 } = params ?? {};
|
|
27818
27818
|
return this._client.getAPIList(path`/v1/skills/${skillID}/versions?beta=true`, PageCursor, {
|
|
27819
|
-
query,
|
|
27819
|
+
query: query2,
|
|
27820
27820
|
...options,
|
|
27821
27821
|
headers: buildHeaders([
|
|
27822
27822
|
{ "anthropic-beta": [...betas ?? [], "skills-2025-10-02"].toString() },
|
|
@@ -27945,9 +27945,9 @@ var init_skills2 = __esm({
|
|
|
27945
27945
|
* ```
|
|
27946
27946
|
*/
|
|
27947
27947
|
list(params = {}, options) {
|
|
27948
|
-
const { betas, ...
|
|
27948
|
+
const { betas, ...query2 } = params ?? {};
|
|
27949
27949
|
return this._client.getAPIList("/v1/skills?beta=true", PageCursor, {
|
|
27950
|
-
query,
|
|
27950
|
+
query: query2,
|
|
27951
27951
|
...options,
|
|
27952
27952
|
headers: buildHeaders([
|
|
27953
27953
|
{ "anthropic-beta": [...betas ?? [], "skills-2025-10-02"].toString() },
|
|
@@ -28065,9 +28065,9 @@ var init_certificates = __esm({
|
|
|
28065
28065
|
* ```
|
|
28066
28066
|
*/
|
|
28067
28067
|
list(tunnelID, params = {}, options) {
|
|
28068
|
-
const { betas, ...
|
|
28068
|
+
const { betas, ...query2 } = params ?? {};
|
|
28069
28069
|
return this._client.getAPIList(path`/v1/tunnels/${tunnelID}/certificates?beta=true`, PageCursor, {
|
|
28070
|
-
query,
|
|
28070
|
+
query: query2,
|
|
28071
28071
|
...options,
|
|
28072
28072
|
headers: buildHeaders([
|
|
28073
28073
|
{ "anthropic-beta": [...betas ?? [], "mcp-tunnels-2026-06-22"].toString() },
|
|
@@ -28194,9 +28194,9 @@ var init_tunnels = __esm({
|
|
|
28194
28194
|
* ```
|
|
28195
28195
|
*/
|
|
28196
28196
|
list(params = {}, options) {
|
|
28197
|
-
const { betas, ...
|
|
28197
|
+
const { betas, ...query2 } = params ?? {};
|
|
28198
28198
|
return this._client.getAPIList("/v1/tunnels?beta=true", PageCursor, {
|
|
28199
|
-
query,
|
|
28199
|
+
query: query2,
|
|
28200
28200
|
...options,
|
|
28201
28201
|
headers: buildHeaders([
|
|
28202
28202
|
{ "anthropic-beta": [...betas ?? [], "mcp-tunnels-2026-06-22"].toString() },
|
|
@@ -28390,9 +28390,9 @@ var init_credentials2 = __esm({
|
|
|
28390
28390
|
* ```
|
|
28391
28391
|
*/
|
|
28392
28392
|
list(vaultID, params = {}, options) {
|
|
28393
|
-
const { betas, ...
|
|
28393
|
+
const { betas, ...query2 } = params ?? {};
|
|
28394
28394
|
return this._client.getAPIList(path`/v1/vaults/${vaultID}/credentials?beta=true`, PageCursor, {
|
|
28395
|
-
query,
|
|
28395
|
+
query: query2,
|
|
28396
28396
|
...options,
|
|
28397
28397
|
headers: buildHeaders([
|
|
28398
28398
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -28563,9 +28563,9 @@ var init_vaults = __esm({
|
|
|
28563
28563
|
* ```
|
|
28564
28564
|
*/
|
|
28565
28565
|
list(params = {}, options) {
|
|
28566
|
-
const { betas, ...
|
|
28566
|
+
const { betas, ...query2 } = params ?? {};
|
|
28567
28567
|
return this._client.getAPIList("/v1/vaults?beta=true", PageCursor, {
|
|
28568
|
-
query,
|
|
28568
|
+
query: query2,
|
|
28569
28569
|
...options,
|
|
28570
28570
|
headers: buildHeaders([
|
|
28571
28571
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -29451,8 +29451,8 @@ var init_batches2 = __esm({
|
|
|
29451
29451
|
* }
|
|
29452
29452
|
* ```
|
|
29453
29453
|
*/
|
|
29454
|
-
list(
|
|
29455
|
-
return this._client.getAPIList("/v1/messages/batches", Page, { query, ...options });
|
|
29454
|
+
list(query2 = {}, options) {
|
|
29455
|
+
return this._client.getAPIList("/v1/messages/batches", Page, { query: query2, ...options });
|
|
29456
29456
|
}
|
|
29457
29457
|
/**
|
|
29458
29458
|
* Delete a Message Batch.
|
|
@@ -29708,9 +29708,9 @@ var init_models2 = __esm({
|
|
|
29708
29708
|
* use in the API. More recently released models are listed first.
|
|
29709
29709
|
*/
|
|
29710
29710
|
list(params = {}, options) {
|
|
29711
|
-
const { betas, ...
|
|
29711
|
+
const { betas, ...query2 } = params ?? {};
|
|
29712
29712
|
return this._client.getAPIList("/v1/models", Page, {
|
|
29713
|
-
query,
|
|
29713
|
+
query: query2,
|
|
29714
29714
|
...options,
|
|
29715
29715
|
headers: buildHeaders([
|
|
29716
29716
|
{ ...betas?.toString() != null ? { "anthropic-beta": betas?.toString() } : void 0 },
|
|
@@ -30059,8 +30059,8 @@ var init_client = __esm({
|
|
|
30059
30059
|
}
|
|
30060
30060
|
return buildHeaders([{ Authorization: `Bearer ${this.authToken}` }]);
|
|
30061
30061
|
}
|
|
30062
|
-
stringifyQuery(
|
|
30063
|
-
return stringifyQuery(
|
|
30062
|
+
stringifyQuery(query2) {
|
|
30063
|
+
return stringifyQuery(query2);
|
|
30064
30064
|
}
|
|
30065
30065
|
getUserAgent() {
|
|
30066
30066
|
return `${this.constructor.name}/JS ${VERSION}`;
|
|
@@ -30071,16 +30071,16 @@ var init_client = __esm({
|
|
|
30071
30071
|
makeStatusError(status, error2, message, headers) {
|
|
30072
30072
|
return APIError.generate(status, error2, message, headers);
|
|
30073
30073
|
}
|
|
30074
|
-
buildURL(path6,
|
|
30074
|
+
buildURL(path6, query2, defaultBaseURL) {
|
|
30075
30075
|
const baseURL = !__classPrivateFieldGet(this, _BaseAnthropic_instances, "m", _BaseAnthropic_baseURLOverridden).call(this) && defaultBaseURL || this.baseURL;
|
|
30076
30076
|
const url = isAbsoluteURL(path6) ? new URL(path6) : new URL(baseURL + (baseURL.endsWith("/") && path6.startsWith("/") ? path6.slice(1) : path6));
|
|
30077
30077
|
const defaultQuery = this.defaultQuery();
|
|
30078
30078
|
const pathQuery = Object.fromEntries(url.searchParams);
|
|
30079
30079
|
if (!isEmptyObj(defaultQuery) || !isEmptyObj(pathQuery)) {
|
|
30080
|
-
|
|
30080
|
+
query2 = { ...pathQuery, ...defaultQuery, ...query2 };
|
|
30081
30081
|
}
|
|
30082
|
-
if (typeof
|
|
30083
|
-
url.search = this.stringifyQuery(
|
|
30082
|
+
if (typeof query2 === "object" && query2 && !Array.isArray(query2)) {
|
|
30083
|
+
url.search = this.stringifyQuery(query2);
|
|
30084
30084
|
}
|
|
30085
30085
|
return url.toString();
|
|
30086
30086
|
}
|
|
@@ -30393,14 +30393,14 @@ var init_client = __esm({
|
|
|
30393
30393
|
}
|
|
30394
30394
|
async buildRequest(inputOptions, { retryCount = 0 } = {}) {
|
|
30395
30395
|
const options = { ...inputOptions };
|
|
30396
|
-
const { method, path: path6, query, defaultBaseURL } = options;
|
|
30396
|
+
const { method, path: path6, query: query2, defaultBaseURL } = options;
|
|
30397
30397
|
if (this._authState.resolution) {
|
|
30398
30398
|
await this._authState.resolution;
|
|
30399
30399
|
}
|
|
30400
30400
|
if (!this._baseURLIsExplicit && this._authState.baseURL && this.baseURL !== this._authState.baseURL) {
|
|
30401
30401
|
this.baseURL = this._authState.baseURL;
|
|
30402
30402
|
}
|
|
30403
|
-
const url = this.buildURL(path6,
|
|
30403
|
+
const url = this.buildURL(path6, query2, defaultBaseURL);
|
|
30404
30404
|
if ("timeout" in options)
|
|
30405
30405
|
validatePositiveInteger("timeout", options.timeout);
|
|
30406
30406
|
options.timeout = options.timeout ?? this.timeout;
|
|
@@ -30518,8 +30518,8 @@ function stripFallbackBlocks(body) {
|
|
|
30518
30518
|
function betaRefusalFallbackMiddleware(fallbacks, options = {}) {
|
|
30519
30519
|
let warnedMissingState = false;
|
|
30520
30520
|
return async (request, next, ctx) => {
|
|
30521
|
-
const [path6,
|
|
30522
|
-
if (fallbacks.length === 0 || ctx.options?.method !== "post" || path6 !== "/v1/messages" || new URLSearchParams(
|
|
30521
|
+
const [path6, query2] = (ctx.options?.path ?? "").split("?");
|
|
30522
|
+
if (fallbacks.length === 0 || ctx.options?.method !== "post" || path6 !== "/v1/messages" || new URLSearchParams(query2).get("beta") !== "true" || typeof ctx.options.body !== "object" || ctx.options.body == null) {
|
|
30523
30523
|
return next(request);
|
|
30524
30524
|
}
|
|
30525
30525
|
if (ctx.options.body.fallbacks != null) {
|
|
@@ -31787,7 +31787,7 @@ ${facts.stderr}`))
|
|
|
31787
31787
|
return null;
|
|
31788
31788
|
}
|
|
31789
31789
|
function isCommandUnavailable(facts, countsRead) {
|
|
31790
|
-
if (facts.exitCode === 127 || facts.exitCode === 126)
|
|
31790
|
+
if (facts.exitCode === 127 || facts.exitCode === 126 || facts.exitCode === 125)
|
|
31791
31791
|
return true;
|
|
31792
31792
|
if (countsRead)
|
|
31793
31793
|
return false;
|
|
@@ -31795,6 +31795,22 @@ function isCommandUnavailable(facts, countsRead) {
|
|
|
31795
31795
|
return false;
|
|
31796
31796
|
return facts.stdout.trim().length === 0 && EXEC_FAILURE.test(facts.stderr);
|
|
31797
31797
|
}
|
|
31798
|
+
function isOfflineBuildGap(facts, counts) {
|
|
31799
|
+
if (facts.runtime !== "jvm")
|
|
31800
|
+
return null;
|
|
31801
|
+
if (counts !== null && counts.tests_failed > 0)
|
|
31802
|
+
return null;
|
|
31803
|
+
if (facts.exitCode === 0 || facts.exitCode === null)
|
|
31804
|
+
return null;
|
|
31805
|
+
const out = `${facts.stdout}
|
|
31806
|
+
${facts.stderr}`;
|
|
31807
|
+
for (const pattern of OFFLINE_BUILD_GAP) {
|
|
31808
|
+
const hit = pattern.exec(out);
|
|
31809
|
+
if (hit)
|
|
31810
|
+
return hit[0];
|
|
31811
|
+
}
|
|
31812
|
+
return null;
|
|
31813
|
+
}
|
|
31798
31814
|
function classifyVerification(facts) {
|
|
31799
31815
|
if (facts.timedOut) {
|
|
31800
31816
|
return {
|
|
@@ -31819,6 +31835,14 @@ function classifyVerification(facts) {
|
|
|
31819
31835
|
reason: `the test command could not be invoked (exit ${String(facts.exitCode)}). This is an environment failure on our side \u2014 a missing interpreter, a binary outside PATH, or a dependency installed somewhere the command cannot see it. The repo has not been judged.`
|
|
31820
31836
|
};
|
|
31821
31837
|
}
|
|
31838
|
+
const gap = isOfflineBuildGap(facts, counts);
|
|
31839
|
+
if (gap !== null) {
|
|
31840
|
+
return {
|
|
31841
|
+
outcome: "test-command-unavailable",
|
|
31842
|
+
counts,
|
|
31843
|
+
reason: `the build stopped on something our install step did not fetch (${gap}). The test step has no network, so this is a gap in our environment, not a failure in the repo. The repo has not been judged.`
|
|
31844
|
+
};
|
|
31845
|
+
}
|
|
31822
31846
|
if (counts !== null) {
|
|
31823
31847
|
if (counts.tests_failed > 0) {
|
|
31824
31848
|
return {
|
|
@@ -31873,10 +31897,19 @@ function isGreen(outcome) {
|
|
|
31873
31897
|
function isOurFault(outcome) {
|
|
31874
31898
|
return outcome === "test-command-unavailable" || outcome === "counts-unparsed";
|
|
31875
31899
|
}
|
|
31876
|
-
var int, withSuiteFailures, READERS, SUPPORTED_RUNNERS, COVERAGE_TABLE, EXEC_FAILURE, SUITE_REPORTED_FAILURE;
|
|
31900
|
+
var VERIFICATION_OUTCOMES, int, withSuiteFailures, READERS, SUPPORTED_RUNNERS, COVERAGE_TABLE, EXEC_FAILURE, SUITE_REPORTED_FAILURE, OFFLINE_BUILD_GAP;
|
|
31877
31901
|
var init_classify2 = __esm({
|
|
31878
31902
|
"../../packages/envrun/dist/classify.js"() {
|
|
31879
31903
|
"use strict";
|
|
31904
|
+
VERIFICATION_OUTCOMES = [
|
|
31905
|
+
"completed",
|
|
31906
|
+
"tests-failed",
|
|
31907
|
+
"no-tests-observed",
|
|
31908
|
+
"counts-unparsed",
|
|
31909
|
+
"test-command-unavailable",
|
|
31910
|
+
"environment-exhausted",
|
|
31911
|
+
"budget-exceeded"
|
|
31912
|
+
];
|
|
31880
31913
|
int = (m, i = 1) => m ? Number(m[i]) : 0;
|
|
31881
31914
|
withSuiteFailures = (counts, suiteLine) => {
|
|
31882
31915
|
if (counts.tests_failed > 0 || !suiteLine)
|
|
@@ -31976,6 +32009,51 @@ var init_classify2 = __esm({
|
|
|
31976
32009
|
return { tests_passed: int(passed), tests_failed: int(failed) + int(errors) };
|
|
31977
32010
|
}
|
|
31978
32011
|
},
|
|
32012
|
+
{
|
|
32013
|
+
// Maven surefire's per-module summary (TERM-1122), measured against surefire
|
|
32014
|
+
// 3.2.5 through `th run`:
|
|
32015
|
+
//
|
|
32016
|
+
// [INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
|
|
32017
|
+
//
|
|
32018
|
+
// The per-CLASS lines carry the same counts followed by `, Time elapsed: …`, so
|
|
32019
|
+
// the end anchor after `Skipped` is what keeps them out; counting both would
|
|
32020
|
+
// double every test. One summary prints per module, so they are SUMMED. An
|
|
32021
|
+
// error is a test that could not run to an assertion, counted as failed so a
|
|
32022
|
+
// green verdict is impossible while one is outstanding, as pytest's are.
|
|
32023
|
+
runner: "maven surefire",
|
|
32024
|
+
read: (out) => {
|
|
32025
|
+
const lines = [
|
|
32026
|
+
...out.matchAll(/^(?:\[(?:INFO|WARNING|ERROR)\] )?Tests run: (\d+), Failures: (\d+), Errors: (\d+), Skipped: (\d+)(?:, Flakes: \d+)?\s*$/gm)
|
|
32027
|
+
];
|
|
32028
|
+
if (lines.length === 0)
|
|
32029
|
+
return null;
|
|
32030
|
+
let passed = 0;
|
|
32031
|
+
let failed = 0;
|
|
32032
|
+
for (const m of lines) {
|
|
32033
|
+
const [run32, failures, errors, skipped] = [m[1], m[2], m[3], m[4]].map(Number);
|
|
32034
|
+
failed += failures + errors;
|
|
32035
|
+
passed += Math.max(0, run32 - failures - errors - skipped);
|
|
32036
|
+
}
|
|
32037
|
+
return { tests_passed: passed, tests_failed: failed };
|
|
32038
|
+
}
|
|
32039
|
+
},
|
|
32040
|
+
{
|
|
32041
|
+
// Gradle prints no test counts when every test passes, so envrun installs an
|
|
32042
|
+
// init script that prints one line per Test task (`gradleTestSummary.ts`,
|
|
32043
|
+
// TERM-1122). The marker is ours; its format is fixed there.
|
|
32044
|
+
runner: "gradle",
|
|
32045
|
+
read: (out) => {
|
|
32046
|
+
const lines = [
|
|
32047
|
+
...out.matchAll(/^terminalhire-gradle-tests: task=\S+ total=(\d+) passed=(\d+) failed=(\d+) skipped=(\d+)\s*$/gm)
|
|
32048
|
+
];
|
|
32049
|
+
if (lines.length === 0)
|
|
32050
|
+
return null;
|
|
32051
|
+
return {
|
|
32052
|
+
tests_passed: lines.reduce((sum, m) => sum + Number(m[2]), 0),
|
|
32053
|
+
tests_failed: lines.reduce((sum, m) => sum + Number(m[3]), 0)
|
|
32054
|
+
};
|
|
32055
|
+
}
|
|
32056
|
+
},
|
|
31979
32057
|
{
|
|
31980
32058
|
// mocha: ` 440 passing (1s)` and ` 2 failing`
|
|
31981
32059
|
runner: "mocha",
|
|
@@ -32010,6 +32088,79 @@ var init_classify2 = __esm({
|
|
|
32010
32088
|
const p = int(passed);
|
|
32011
32089
|
return { tests_passed: p, tests_failed: Math.max(0, t - p) };
|
|
32012
32090
|
}
|
|
32091
|
+
},
|
|
32092
|
+
{
|
|
32093
|
+
/**
|
|
32094
|
+
* BARE TAP — assertion lines with no plan and no summary comment (TERM-1138).
|
|
32095
|
+
*
|
|
32096
|
+
* LAST ON PURPOSE. It is the loosest reader here, so anything that a more specific
|
|
32097
|
+
* one can read must reach that one first: `node --test` and node-tap both emit `ok`
|
|
32098
|
+
* lines AND a closing summary, and their readers are ordered above for that reason.
|
|
32099
|
+
* Moving this up would have it answer for both.
|
|
32100
|
+
*
|
|
32101
|
+
* A hand-rolled harness prints neither summary — it emits its assertions and stops.
|
|
32102
|
+
* That is what morebetterltd/wheelhouse does: thirty `ok N - …` lines, exit 0, and
|
|
32103
|
+
* before this every one of those runs reported `counts-unparsed`, which the claim
|
|
32104
|
+
* page renders as "RESULT UNREADABLE — THE SUITE EXITED 0" over a suite that passed.
|
|
32105
|
+
*
|
|
32106
|
+
* ON THE MISSING PLAN LINE. TAP requires `1..N` so a reader can tell a finished
|
|
32107
|
+
* stream from a truncated one, and there is none here, so this cannot prove the
|
|
32108
|
+
* suite reached its end. That is a real limit and it is NOT a reason to refuse,
|
|
32109
|
+
* because it holds this format to a standard no reader in this file meets — the
|
|
32110
|
+
* jest reader greps a line out of stdout that a repository could `echo` without
|
|
32111
|
+
* running anything. These are format adapters, not a trust boundary; the boundary
|
|
32112
|
+
* is that the command is the repository's own or is refused a signature.
|
|
32113
|
+
*
|
|
32114
|
+
* CONTIGUOUS FROM 1, which buys self-consistency rather than security:
|
|
32115
|
+
*
|
|
32116
|
+
* - starting at 1 rejects a TRUNCATION. `testOutputTail` keeps the last lines, so
|
|
32117
|
+
* a stream beginning `ok 47` is the middle of a longer run and counting it would
|
|
32118
|
+
* report three tests for a suite that ran fifty.
|
|
32119
|
+
* - no gaps rejects prose that happens to carry the word, and a stream interleaved
|
|
32120
|
+
* with another's.
|
|
32121
|
+
* - anchored with no leading space rejects TAP SUBTESTS, which indent. Counting
|
|
32122
|
+
* those would double them against their parent.
|
|
32123
|
+
*/
|
|
32124
|
+
runner: "bare TAP",
|
|
32125
|
+
read: (out) => {
|
|
32126
|
+
let n = 0;
|
|
32127
|
+
let failed = 0;
|
|
32128
|
+
let passed = 0;
|
|
32129
|
+
let plan = null;
|
|
32130
|
+
for (const line of out.split("\n")) {
|
|
32131
|
+
if (/^Bail out!/.test(line))
|
|
32132
|
+
return null;
|
|
32133
|
+
const p = /^(\d+)\.\.(\d+)\s*$/.exec(line);
|
|
32134
|
+
if (p) {
|
|
32135
|
+
const declared = Number(p[2]) - Number(p[1]) + 1;
|
|
32136
|
+
if (plan !== null && plan !== declared)
|
|
32137
|
+
return null;
|
|
32138
|
+
plan = declared;
|
|
32139
|
+
continue;
|
|
32140
|
+
}
|
|
32141
|
+
const m = /^(not )?ok (\d+)(?:\s|$)/.exec(line);
|
|
32142
|
+
if (!m)
|
|
32143
|
+
continue;
|
|
32144
|
+
if (Number(m[2]) !== n + 1)
|
|
32145
|
+
return null;
|
|
32146
|
+
n += 1;
|
|
32147
|
+
const directive = /#\s*(skip|todo)\b/i.exec(line);
|
|
32148
|
+
const kind = directive?.[1]?.toLowerCase();
|
|
32149
|
+
if (kind === "skip")
|
|
32150
|
+
continue;
|
|
32151
|
+
if (m[1] !== void 0) {
|
|
32152
|
+
if (kind !== "todo")
|
|
32153
|
+
failed += 1;
|
|
32154
|
+
continue;
|
|
32155
|
+
}
|
|
32156
|
+
passed += 1;
|
|
32157
|
+
}
|
|
32158
|
+
if (n === 0)
|
|
32159
|
+
return null;
|
|
32160
|
+
if (plan !== null && plan !== n)
|
|
32161
|
+
return null;
|
|
32162
|
+
return { tests_passed: passed, tests_failed: failed };
|
|
32163
|
+
}
|
|
32013
32164
|
}
|
|
32014
32165
|
];
|
|
32015
32166
|
SUPPORTED_RUNNERS = READERS.map((r) => r.runner);
|
|
@@ -32031,6 +32182,21 @@ var init_classify2 = __esm({
|
|
|
32031
32182
|
"\\d+\\s+examples?,\\s+(?!0\\b)\\d+\\s+failures?"
|
|
32032
32183
|
// rspec's summary line
|
|
32033
32184
|
].join("|"), "m");
|
|
32185
|
+
OFFLINE_BUILD_GAP = [
|
|
32186
|
+
// Maven, `-o`: `Cannot access central (…) in offline mode and the artifact … has
|
|
32187
|
+
// not been downloaded from it before.`
|
|
32188
|
+
/in offline mode and the artifact \S+ has not been downloaded from it before/,
|
|
32189
|
+
// Maven without `-o`, as a CI-derived `mvn test` runs: it tries the network.
|
|
32190
|
+
/Could not transfer artifact \S+ from\/to /,
|
|
32191
|
+
/Plugin \S+ or one of its dependencies could not be resolved/,
|
|
32192
|
+
// Gradle, `--offline`.
|
|
32193
|
+
/No cached version (?:listing )?(?:of|for) \S+ available for offline mode/,
|
|
32194
|
+
// Gradle without `--offline`, and the wrapper fetching its own distribution.
|
|
32195
|
+
/Could not GET 'https?:\/\//,
|
|
32196
|
+
/^Downloading https:\/\/services\.gradle\.org\/distributions\//m,
|
|
32197
|
+
/No matching toolchains found for requested specification/,
|
|
32198
|
+
/Cannot find a Java installation on your machine matching/
|
|
32199
|
+
];
|
|
32034
32200
|
}
|
|
32035
32201
|
});
|
|
32036
32202
|
|
|
@@ -32096,6 +32262,12 @@ function scrubEnv(source, opts) {
|
|
|
32096
32262
|
env["GOCACHE"] = join34(jailHome, ".cache", "go-build");
|
|
32097
32263
|
env["GOFLAGS"] = "-modcacherw";
|
|
32098
32264
|
env["CARGO_HOME"] = join34(jailHome, ".cargo");
|
|
32265
|
+
env["MAVEN_OPTS"] = `-Dmaven.repo.local=${join34(jailHome, ".m2", "repository")}`;
|
|
32266
|
+
env["GRADLE_USER_HOME"] = join34(jailHome, ".gradle");
|
|
32267
|
+
const bundle = join34(jailHome, ".bundle");
|
|
32268
|
+
env["GEM_HOME"] = bundle;
|
|
32269
|
+
env["BUNDLE_PATH"] = bundle;
|
|
32270
|
+
env["BUNDLE_APP_CONFIG"] = bundle;
|
|
32099
32271
|
const proxy = opts.proxyUrl ?? DEAD_PROXY;
|
|
32100
32272
|
env["HTTP_PROXY"] = proxy;
|
|
32101
32273
|
env["HTTPS_PROXY"] = proxy;
|
|
@@ -32396,6 +32568,31 @@ var init_egressProxy = __esm({
|
|
|
32396
32568
|
"static.crates.io",
|
|
32397
32569
|
"index.crates.io",
|
|
32398
32570
|
"crates.io",
|
|
32571
|
+
// TERM-1139. `ruby` has had an image since the mapping existed and `bundle install`
|
|
32572
|
+
// as its derived command, and this host was missing — so every ruby repo could start
|
|
32573
|
+
// and could never install. Install is the ONLY step with a network grant at all, so a
|
|
32574
|
+
// denial here is terminal, not a slow path.
|
|
32575
|
+
//
|
|
32576
|
+
// One entry, not two: `hostAllowed` is dot-anchored SUFFIX matching, so this covers
|
|
32577
|
+
// `index.rubygems.org` as well. Listing that separately would advertise the grant as
|
|
32578
|
+
// narrower than it is, which the `github.com` note below rejects for the same reason.
|
|
32579
|
+
"rubygems.org",
|
|
32580
|
+
// TERM-1139, added with the `dotnet` image mapping. `dotnet restore` fetches from
|
|
32581
|
+
// NuGet; the coupling test refuses a mapped runtime whose registry is unreachable, and
|
|
32582
|
+
// it caught this one the moment the image landed.
|
|
32583
|
+
"api.nuget.org",
|
|
32584
|
+
// TERM-1122, added with the `jvm` image mapping, each from a MEASURED denial
|
|
32585
|
+
// through `th run` (the proxy's 403 in the build's own output), not a guess:
|
|
32586
|
+
// - Maven Central, where both `mvn` and Gradle's `mavenCentral()` resolve.
|
|
32587
|
+
// - `services.gradle.org`, where a Gradle wrapper fetches its distribution.
|
|
32588
|
+
// - `release-assets.githubusercontent.com`, where that fetch LANDS. Measured
|
|
32589
|
+
// chain: services.gradle.org 307 -> github.com 302 -> this host 200. The
|
|
32590
|
+
// `github.com` note below keeps `githubusercontent.com` denied until a real
|
|
32591
|
+
// install needs it; this is that install. Only this one host: raw blobs and
|
|
32592
|
+
// `objects.githubusercontent.com` stay denied.
|
|
32593
|
+
"repo.maven.apache.org",
|
|
32594
|
+
"services.gradle.org",
|
|
32595
|
+
"release-assets.githubusercontent.com",
|
|
32399
32596
|
// Git dependencies. Approved by Eric 2026-07-22 after a live run measured the
|
|
32400
32597
|
// chokepoint working under load (20 events, 16 allowed / 4 denied by host).
|
|
32401
32598
|
//
|
|
@@ -32687,6 +32884,9 @@ function containerArgs(spec, env, opts) {
|
|
|
32687
32884
|
args5.push(`--env=${k}=${url}`);
|
|
32688
32885
|
}
|
|
32689
32886
|
args5.push("--env=NO_PROXY=", "--env=no_proxy=");
|
|
32887
|
+
const host = opts.net.proxyHost;
|
|
32888
|
+
const port = String(opts.net.proxyPort);
|
|
32889
|
+
args5.push(`--env=JAVA_TOOL_OPTIONS=-Dhttp.proxyHost=${host} -Dhttp.proxyPort=${port} -Dhttps.proxyHost=${host} -Dhttps.proxyPort=${port} -Daether.connector.http.useSystemProperties=true`);
|
|
32690
32890
|
}
|
|
32691
32891
|
args5.push("--");
|
|
32692
32892
|
args5.push(validateImage(opts.image ?? DEFAULT_CONTAINER_IMAGE));
|
|
@@ -33019,7 +33219,10 @@ var init_container = __esm({
|
|
|
33019
33219
|
"http_proxy",
|
|
33020
33220
|
"https_proxy",
|
|
33021
33221
|
"NO_PROXY",
|
|
33022
|
-
"no_proxy"
|
|
33222
|
+
"no_proxy",
|
|
33223
|
+
// Carries the JVM's copy of the proxy (below), so an inherited value is dropped
|
|
33224
|
+
// for the same reason as the rest.
|
|
33225
|
+
"JAVA_TOOL_OPTIONS"
|
|
33023
33226
|
]);
|
|
33024
33227
|
WINDOWS_DRIVE_ROOT = /^[A-Za-z]:[\\/]/;
|
|
33025
33228
|
IMAGE_HOST = "(?:[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)+(?::[0-9]+)?|localhost(?::[0-9]+)?)";
|
|
@@ -33069,11 +33272,17 @@ var init_dist = __esm({
|
|
|
33069
33272
|
function censusTotal(c) {
|
|
33070
33273
|
return c.containers.length + c.volumes.length + c.networks.length;
|
|
33071
33274
|
}
|
|
33072
|
-
function
|
|
33275
|
+
function query(docker3, args5) {
|
|
33073
33276
|
const res = docker3.sync([...args5], { timeoutMs: 15e3 });
|
|
33074
|
-
if (res.error || res.status !== 0)
|
|
33075
|
-
|
|
33076
|
-
|
|
33277
|
+
if (res.error || res.status !== 0) {
|
|
33278
|
+
const why = res.error?.message ?? (res.stderr.trim() || `exit ${String(res.status)}`);
|
|
33279
|
+
return { ids: [], failure: `docker ${args5.slice(0, 2).join(" ")}: ${why}` };
|
|
33280
|
+
}
|
|
33281
|
+
const ids2 = res.stdout.split("\n").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
33282
|
+
return { ids: ids2, failure: null };
|
|
33283
|
+
}
|
|
33284
|
+
function ids(docker3, args5) {
|
|
33285
|
+
return query(docker3, args5).ids;
|
|
33077
33286
|
}
|
|
33078
33287
|
function census(docker3, label) {
|
|
33079
33288
|
const filter = `label=${label}`;
|
|
@@ -33083,25 +33292,67 @@ function census(docker3, label) {
|
|
|
33083
33292
|
networks: ids(docker3, ["network", "ls", "-q", "--filter", filter])
|
|
33084
33293
|
};
|
|
33085
33294
|
}
|
|
33295
|
+
function censusReport(docker3, label) {
|
|
33296
|
+
const filter = `label=${label}`;
|
|
33297
|
+
const failures = [];
|
|
33298
|
+
const ask5 = (args5) => {
|
|
33299
|
+
const q = query(docker3, args5);
|
|
33300
|
+
if (q.failure !== null)
|
|
33301
|
+
failures.push(q.failure);
|
|
33302
|
+
return q.ids;
|
|
33303
|
+
};
|
|
33304
|
+
const taken = {
|
|
33305
|
+
containers: ask5(["ps", "-aq", "--filter", filter]),
|
|
33306
|
+
volumes: ask5(["volume", "ls", "-q", "--filter", filter]),
|
|
33307
|
+
networks: ask5(["network", "ls", "-q", "--filter", filter])
|
|
33308
|
+
};
|
|
33309
|
+
return failures.length === 0 ? { observed: true, census: taken, unobservedReason: null } : { observed: false, census: taken, unobservedReason: failures.join("; ") };
|
|
33310
|
+
}
|
|
33086
33311
|
function localCensus(label) {
|
|
33087
33312
|
return census(localDockerClient(), label);
|
|
33088
33313
|
}
|
|
33089
|
-
function judgeLeaks(peak, after) {
|
|
33314
|
+
function judgeLeaks(peak, after, observation) {
|
|
33090
33315
|
const labelObserved = peak.containers.length > 0;
|
|
33316
|
+
if (!observation.observed) {
|
|
33317
|
+
return {
|
|
33318
|
+
labelObserved,
|
|
33319
|
+
reaped: false,
|
|
33320
|
+
observed: false,
|
|
33321
|
+
clean: false,
|
|
33322
|
+
state: "unobserved",
|
|
33323
|
+
peak,
|
|
33324
|
+
after,
|
|
33325
|
+
note: `UNOBSERVED, not clean: we could not look at what survived teardown (${observation.unobservedReason ?? "no reason given"}), so nothing is known about leaks on this run, in either direction.`
|
|
33326
|
+
};
|
|
33327
|
+
}
|
|
33091
33328
|
const reaped = censusTotal(after) === 0;
|
|
33092
33329
|
let note;
|
|
33330
|
+
let state;
|
|
33093
33331
|
if (!labelObserved && reaped) {
|
|
33332
|
+
state = "inconclusive";
|
|
33094
33333
|
note = "INCONCLUSIVE, not clean: nothing labelled was ever seen alive, so an empty final census is equally consistent with the label never being applied. The control failed, so the denial proves nothing.";
|
|
33095
33334
|
} else if (!labelObserved) {
|
|
33335
|
+
state = "leak";
|
|
33096
33336
|
note = "no labelled container was observed alive AND objects remain \u2014 the label wiring is wrong.";
|
|
33097
33337
|
} else if (!reaped) {
|
|
33338
|
+
state = "leak";
|
|
33098
33339
|
note = `LEAK: ${String(censusTotal(after))} labelled object(s) survived teardown (containers=${String(after.containers.length)} volumes=${String(after.volumes.length)} networks=${String(after.networks.length)}).`;
|
|
33099
33340
|
} else {
|
|
33341
|
+
state = "clean";
|
|
33100
33342
|
note = `clean: peak ${String(peak.containers.length)} labelled container(s) observed alive, 0 labelled objects remain after teardown.`;
|
|
33101
33343
|
}
|
|
33102
|
-
return {
|
|
33344
|
+
return {
|
|
33345
|
+
labelObserved,
|
|
33346
|
+
reaped,
|
|
33347
|
+
observed: true,
|
|
33348
|
+
clean: labelObserved && reaped,
|
|
33349
|
+
state,
|
|
33350
|
+
peak,
|
|
33351
|
+
after,
|
|
33352
|
+
note
|
|
33353
|
+
};
|
|
33103
33354
|
}
|
|
33104
|
-
var RUN_LABEL_KEY, LabelWatch;
|
|
33355
|
+
var RUN_LABEL_KEY, LabelWatch, LEAK_STATES;
|
|
33105
33356
|
var init_labels = __esm({
|
|
33106
33357
|
"../../packages/envrun/dist/labels.js"() {
|
|
33107
33358
|
"use strict";
|
|
@@ -33156,6 +33407,7 @@ var init_labels = __esm({
|
|
|
33156
33407
|
return this.#samples;
|
|
33157
33408
|
}
|
|
33158
33409
|
};
|
|
33410
|
+
LEAK_STATES = ["clean", "leak", "inconclusive", "unobserved"];
|
|
33159
33411
|
}
|
|
33160
33412
|
});
|
|
33161
33413
|
|
|
@@ -33640,7 +33892,7 @@ function acquireLocalLease(runId) {
|
|
|
33640
33892
|
observed: false,
|
|
33641
33893
|
census: { containers: [], volumes: [], networks: [] },
|
|
33642
33894
|
unobservedReason: RELEASED_LEASE_CENSUS_REASON
|
|
33643
|
-
} :
|
|
33895
|
+
} : censusReport(docker3, label)),
|
|
33644
33896
|
publishPreview: (req) => startPreview({ ...req, docker: docker3 }),
|
|
33645
33897
|
release: () => {
|
|
33646
33898
|
if (released) {
|
|
@@ -33760,6 +34012,17 @@ caused by: ${frame}`;
|
|
|
33760
34012
|
}
|
|
33761
34013
|
return frames === 0 ? null : out;
|
|
33762
34014
|
}
|
|
34015
|
+
function imageVariantFor(spec) {
|
|
34016
|
+
if (spec.runtime !== "jvm")
|
|
34017
|
+
return void 0;
|
|
34018
|
+
const callsGradle = /(?:^|[\s;&|(])gradle(?=\s|$)/;
|
|
34019
|
+
return [spec.installCommand, spec.testCommand].some((c) => c != null && callsGradle.test(c)) ? "gradle" : void 0;
|
|
34020
|
+
}
|
|
34021
|
+
function shapeFor(runtime, variant) {
|
|
34022
|
+
if (runtime === "jvm" && variant === "gradle")
|
|
34023
|
+
return JVM_GRADLE_IMAGE;
|
|
34024
|
+
return RUNTIME_IMAGES[runtime];
|
|
34025
|
+
}
|
|
33763
34026
|
function atLeast(a, b) {
|
|
33764
34027
|
const left = a.split(".").map(Number);
|
|
33765
34028
|
const right = b.split(".").map(Number);
|
|
@@ -33772,19 +34035,19 @@ function atLeast(a, b) {
|
|
|
33772
34035
|
}
|
|
33773
34036
|
return true;
|
|
33774
34037
|
}
|
|
33775
|
-
function imageForRuntime(runtime, override, version2) {
|
|
34038
|
+
function imageForRuntime(runtime, override, version2, variant) {
|
|
33776
34039
|
if (override)
|
|
33777
34040
|
return override;
|
|
33778
|
-
const shape =
|
|
34041
|
+
const shape = shapeFor(runtime, variant);
|
|
33779
34042
|
if (!shape) {
|
|
33780
|
-
throw new RunRefusalError(`no container image is mapped for runtime ${JSON.stringify(runtime)}. Refusing to run it in the Node image: a
|
|
34043
|
+
throw new RunRefusalError(`no container image is mapped for runtime ${JSON.stringify(runtime)}. Refusing to run it in the Node image: a bare "command not found" exits 127, which classifyVerification already owns as ours \u2014 but a test script that RUNS and fails inside on the missing tool exits with its own status and prints to stdout, and that falls through to tests-failed \u2014 a false red blamed on the repo.`);
|
|
33781
34044
|
}
|
|
33782
34045
|
if (version2 === void 0 || version2 === null)
|
|
33783
34046
|
return unversionedImage(shape);
|
|
33784
34047
|
if (!TAG_VERSION.test(version2)) {
|
|
33785
34048
|
throw new RunRefusalError(`runtime version ${JSON.stringify(version2)} is not a bare version, so no image tag can be built from it. Refusing rather than booting the default: the repo asked for a version, and supplying a different one silently is what TERM-643 fixed.`);
|
|
33786
34049
|
}
|
|
33787
|
-
return `${shape.repository}:${version2}${shape.suffix}`;
|
|
34050
|
+
return `${shape.repository}:${shape.prefix ?? ""}${version2}${shape.suffix}`;
|
|
33788
34051
|
}
|
|
33789
34052
|
function setManifestProbe(probe) {
|
|
33790
34053
|
const previous = manifestProbe;
|
|
@@ -33797,10 +34060,10 @@ function imageDefinitelyAbsent(image) {
|
|
|
33797
34060
|
return false;
|
|
33798
34061
|
return /manifest unknown|no such manifest/i.test(res.output);
|
|
33799
34062
|
}
|
|
33800
|
-
function resolvePublishedImage(image, runtime, version2) {
|
|
34063
|
+
function resolvePublishedImage(image, runtime, version2, variant) {
|
|
33801
34064
|
if (!imageDefinitelyAbsent(image))
|
|
33802
34065
|
return image;
|
|
33803
|
-
const shape =
|
|
34066
|
+
const shape = shapeFor(runtime, variant);
|
|
33804
34067
|
if (shape && shape.declaredIsFloor && atLeast(shape.defaultVersion, version2)) {
|
|
33805
34068
|
return unversionedImage(shape);
|
|
33806
34069
|
}
|
|
@@ -33808,18 +34071,19 @@ function resolvePublishedImage(image, runtime, version2) {
|
|
|
33808
34071
|
}
|
|
33809
34072
|
function resolveImageForSpec(spec, override) {
|
|
33810
34073
|
const declared = spec.runtimeVersion;
|
|
33811
|
-
const
|
|
34074
|
+
const variant = imageVariantFor(spec);
|
|
34075
|
+
const image = imageForRuntime(spec.runtime, override, declared, variant);
|
|
33812
34076
|
const constructed = (() => {
|
|
33813
34077
|
if (declared === null)
|
|
33814
34078
|
return null;
|
|
33815
34079
|
try {
|
|
33816
|
-
return imageForRuntime(spec.runtime, void 0, declared);
|
|
34080
|
+
return imageForRuntime(spec.runtime, void 0, declared, variant);
|
|
33817
34081
|
} catch {
|
|
33818
34082
|
return null;
|
|
33819
34083
|
}
|
|
33820
34084
|
})();
|
|
33821
34085
|
if (constructed !== null && image === constructed && declared !== null) {
|
|
33822
|
-
return resolvePublishedImage(image, spec.runtime, declared);
|
|
34086
|
+
return resolvePublishedImage(image, spec.runtime, declared, variant);
|
|
33823
34087
|
}
|
|
33824
34088
|
return image;
|
|
33825
34089
|
}
|
|
@@ -33846,12 +34110,22 @@ function assertVenueOwnerDeclared(lease) {
|
|
|
33846
34110
|
return;
|
|
33847
34111
|
throw new RunRefusalError("this venue did not say which account owns the tree it staged, so the guest would run under this machine's uid and could not write its own clone. We refuse rather than report that permission error as the repo's tests failing.");
|
|
33848
34112
|
}
|
|
34113
|
+
function refuseUnbuildableSpec(spec) {
|
|
34114
|
+
if (spec.runtime !== "jvm" || spec.installCommand !== null || spec.testCommand !== null)
|
|
34115
|
+
return;
|
|
34116
|
+
const why = spec.unresolved.find((r) => r.kind === "no-test-command")?.detail;
|
|
34117
|
+
if (why === void 0) {
|
|
34118
|
+
throw new EnvRunError("internal: a jvm spec with no test command carries no no-test-command reason");
|
|
34119
|
+
}
|
|
34120
|
+
throw new RunRefusalError(`refusing to run this repository: ${why}.`);
|
|
34121
|
+
}
|
|
33849
34122
|
async function runEnvironmentSpec(req) {
|
|
33850
34123
|
const startedAt = Date.now();
|
|
33851
34124
|
const containment = req.lease.containment;
|
|
33852
34125
|
if (containment.kind !== "container") {
|
|
33853
34126
|
throw new EnvRunError(`phase 2 requires the container tier, got ${containment.kind}. Refusing: a container phase that silently ran under seatbelt would make every container claim vacuous.`);
|
|
33854
34127
|
}
|
|
34128
|
+
refuseUnbuildableSpec(req.spec);
|
|
33855
34129
|
assertVenueOwnerDeclared(req.lease);
|
|
33856
34130
|
const image = resolveImageForSpec(req.spec, req.image);
|
|
33857
34131
|
const { jail, tmp } = req;
|
|
@@ -33894,9 +34168,10 @@ async function runEnvironmentSpec(req) {
|
|
|
33894
34168
|
installOk: false
|
|
33895
34169
|
};
|
|
33896
34170
|
} else if (req.spec.testCommand === null) {
|
|
34171
|
+
const why = req.spec.unresolved.find((r) => r.kind === "no-test-command")?.detail;
|
|
33897
34172
|
result = {
|
|
33898
34173
|
outcome: "no-tests-observed",
|
|
33899
|
-
note: "the spec derived no test command, so nothing was executed: nothing failed and nothing ran. Certain, not inferred \u2014 no command was ever invoked.",
|
|
34174
|
+
note: "the spec derived no test command, so nothing was executed: nothing failed and nothing ran. Certain, not inferred \u2014 no command was ever invoked." + (why === void 0 ? "" : ` Why: ${why}.`),
|
|
33900
34175
|
installOk: true
|
|
33901
34176
|
};
|
|
33902
34177
|
} else {
|
|
@@ -33919,7 +34194,7 @@ async function runEnvironmentSpec(req) {
|
|
|
33919
34194
|
labels,
|
|
33920
34195
|
timeoutMs: req.testTimeoutMs ?? 9e5
|
|
33921
34196
|
});
|
|
33922
|
-
const verdict = classifyVerification(toExecution(test));
|
|
34197
|
+
const verdict = classifyVerification({ ...toExecution(test), runtime: req.spec.runtime });
|
|
33923
34198
|
result = { outcome: verdict.outcome, note: verdict.reason, installOk: true };
|
|
33924
34199
|
}
|
|
33925
34200
|
} finally {
|
|
@@ -33933,6 +34208,10 @@ async function runEnvironmentSpec(req) {
|
|
|
33933
34208
|
volumes: [],
|
|
33934
34209
|
networks: []
|
|
33935
34210
|
};
|
|
34211
|
+
const observation = afterReport ?? {
|
|
34212
|
+
observed: false,
|
|
34213
|
+
unobservedReason: "the run carried no label, so there was nothing to count by"
|
|
34214
|
+
};
|
|
33936
34215
|
return {
|
|
33937
34216
|
outcome: result.outcome,
|
|
33938
34217
|
tier: "container",
|
|
@@ -33941,7 +34220,7 @@ async function runEnvironmentSpec(req) {
|
|
|
33941
34220
|
test,
|
|
33942
34221
|
installOk: result.installOk,
|
|
33943
34222
|
counts: test ? readCounts(test.stdout, test.stderr) : null,
|
|
33944
|
-
leaks: judgeLeaks(peak, after),
|
|
34223
|
+
leaks: judgeLeaks(peak, after, observation),
|
|
33945
34224
|
note: result.note,
|
|
33946
34225
|
wallMs: Date.now() - startedAt
|
|
33947
34226
|
};
|
|
@@ -33991,7 +34270,7 @@ async function runStep(containment, r) {
|
|
|
33991
34270
|
wallMs: Date.now() - startedAt
|
|
33992
34271
|
};
|
|
33993
34272
|
}
|
|
33994
|
-
var EnvRunError, RunRefusalError, MAX_CAUSE_FRAMES, CHAIN_UNREADABLE, CHAIN_TOO_DEEP, RUNTIME_IMAGES, unversionedImage, TAG_VERSION, dockerManifestProbe, manifestProbe, MISSING_IMAGE_SHAPE;
|
|
34273
|
+
var EnvRunError, RunRefusalError, MAX_CAUSE_FRAMES, CHAIN_UNREADABLE, CHAIN_TOO_DEEP, RUNTIME_IMAGES, JVM_GRADLE_IMAGE, unversionedImage, TAG_VERSION, dockerManifestProbe, manifestProbe, MISSING_IMAGE_SHAPE;
|
|
33995
34274
|
var init_execute = __esm({
|
|
33996
34275
|
"../../packages/envrun/dist/execute.js"() {
|
|
33997
34276
|
"use strict";
|
|
@@ -34028,9 +34307,66 @@ var init_execute = __esm({
|
|
|
34028
34307
|
},
|
|
34029
34308
|
go: { repository: "golang", suffix: "-bookworm", defaultVersion: "1.23", declaredIsFloor: true },
|
|
34030
34309
|
ruby: { repository: "ruby", suffix: "-bookworm", defaultVersion: "3.3", declaredIsFloor: false },
|
|
34031
|
-
rust: { repository: "rust", suffix: "-bookworm", defaultVersion: "1", declaredIsFloor: true }
|
|
34032
|
-
|
|
34033
|
-
|
|
34310
|
+
rust: { repository: "rust", suffix: "-bookworm", defaultVersion: "1", declaredIsFloor: true },
|
|
34311
|
+
/**
|
|
34312
|
+
* TERM-1139. `dotnet` was unmapped alongside `jvm`, and the recorded reason was that
|
|
34313
|
+
* neither had "a single obvious base image (gradle vs maven, sdk vs runtime)". That
|
|
34314
|
+
* reason holds for jvm and it does NOT hold here, which is why only this half moved.
|
|
34315
|
+
*
|
|
34316
|
+
* "sdk vs runtime" answers itself: the derived commands are `dotnet restore` and
|
|
34317
|
+
* `dotnet test`, and neither exists on the runtime image. There is no second build
|
|
34318
|
+
* tool competing for the slot the way maven and gradle compete for jvm's — and since
|
|
34319
|
+
* no official image carries both of those, jvm genuinely cannot be served by one key.
|
|
34320
|
+
*
|
|
34321
|
+
* MEASURED, not chosen by tag: `mcr.microsoft.com/dotnet/sdk:8.0` carries `git` and
|
|
34322
|
+
* `dotnet` (881MB). `git` is the property the whole `image-tooling-live` test exists
|
|
34323
|
+
* for, and `eclipse-temurin:21-jdk` was rejected here for lacking it.
|
|
34324
|
+
*
|
|
34325
|
+
* The tag shape fits without touching the builder: the SDK publishes a tag per
|
|
34326
|
+
* version, so `repository:VERSION` is a real image at every version envspec can
|
|
34327
|
+
* derive, with no suffix. That is NOT true of the maven images, where the leading
|
|
34328
|
+
* tag component is maven's version and Java's sits in the suffix.
|
|
34329
|
+
*
|
|
34330
|
+
* `declaredIsFloor` is true on the same reasoning as go and rust: an SDK builds
|
|
34331
|
+
* older target frameworks, so booting 8.0 for a repo asking 6.0 is the supported
|
|
34332
|
+
* case rather than a substitution. A repo asking for something NEWER than our
|
|
34333
|
+
* default still refuses, which is where TERM-643 put that line.
|
|
34334
|
+
*/
|
|
34335
|
+
dotnet: {
|
|
34336
|
+
repository: "mcr.microsoft.com/dotnet/sdk",
|
|
34337
|
+
suffix: "",
|
|
34338
|
+
defaultVersion: "8.0",
|
|
34339
|
+
declaredIsFloor: true
|
|
34340
|
+
},
|
|
34341
|
+
/**
|
|
34342
|
+
* TERM-1122. Maven's image, and the one a Gradle WRAPPER repo gets too: the wrapper
|
|
34343
|
+
* downloads its own Gradle, so it needs a JDK and nothing else. MEASURED
|
|
34344
|
+
* 2026-09-18: `maven:3.9-eclipse-temurin-21` carries `git`, `mvn` and JDK 21 on
|
|
34345
|
+
* Ubuntu 24.04, which is why this is not `eclipse-temurin` (no `git`, rejected
|
|
34346
|
+
* under TERM-1139). The JDK sits AFTER maven's own version in the tag, hence
|
|
34347
|
+
* `prefix`, and the major is all envspec derives (`javaMajor`).
|
|
34348
|
+
*
|
|
34349
|
+
* `declaredIsFloor`: a JDK builds for older `--release` targets, so a repo asking
|
|
34350
|
+
* for 16, which has no image, runs on 21. A Gradle toolchain is stricter than a
|
|
34351
|
+
* floor and asks for its exact JDK; Gradle's refusal on the wrong one reads as
|
|
34352
|
+
* ours (`classify.ts`, `isOfflineBuildGap`), never as the repo's.
|
|
34353
|
+
*/
|
|
34354
|
+
jvm: {
|
|
34355
|
+
repository: "maven",
|
|
34356
|
+
prefix: "3.9-eclipse-temurin-",
|
|
34357
|
+
suffix: "",
|
|
34358
|
+
defaultVersion: "21",
|
|
34359
|
+
declaredIsFloor: true
|
|
34360
|
+
}
|
|
34361
|
+
};
|
|
34362
|
+
JVM_GRADLE_IMAGE = {
|
|
34363
|
+
repository: "gradle",
|
|
34364
|
+
prefix: "jdk",
|
|
34365
|
+
suffix: "",
|
|
34366
|
+
defaultVersion: "21",
|
|
34367
|
+
declaredIsFloor: true
|
|
34368
|
+
};
|
|
34369
|
+
unversionedImage = (shape) => `${shape.repository}:${shape.prefix ?? ""}${shape.defaultVersion}${shape.suffix}`;
|
|
34034
34370
|
TAG_VERSION = /^\d+(?:\.\d+){0,2}$/;
|
|
34035
34371
|
dockerManifestProbe = (image) => {
|
|
34036
34372
|
const res = spawnSync5("docker", ["manifest", "inspect", image], {
|
|
@@ -34722,14 +35058,31 @@ function answerDidItPass(r) {
|
|
|
34722
35058
|
const passed = r.status === "verified" && r.outcome !== null && isGreen(r.outcome);
|
|
34723
35059
|
return { passed, summary: renderVerdictLine(r), lookAt: r.preview?.url ?? null };
|
|
34724
35060
|
}
|
|
34725
|
-
|
|
35061
|
+
function exitCodeFor(r) {
|
|
35062
|
+
if (r.status === "refused")
|
|
35063
|
+
return 2;
|
|
35064
|
+
if (r.outcome === null)
|
|
35065
|
+
return 2;
|
|
35066
|
+
return OUTCOME_EXIT_CODES[r.outcome];
|
|
35067
|
+
}
|
|
35068
|
+
var RUN_TEST_COMMAND_SOURCES, RUN_IMAGE_SOURCES, RUN_RESULT_SCHEMA, RUN_RESULT_FIELDS, RENDER_NONE, FIELD_VIEWS, OUTCOME_EXIT_CODES;
|
|
34726
35069
|
var init_result = __esm({
|
|
34727
35070
|
"../../packages/envrun/dist/result.js"() {
|
|
34728
35071
|
"use strict";
|
|
34729
35072
|
init_dist2();
|
|
34730
35073
|
init_classify2();
|
|
34731
35074
|
init_venueDescriptor();
|
|
34732
|
-
RUN_TEST_COMMAND_SOURCES = [
|
|
35075
|
+
RUN_TEST_COMMAND_SOURCES = [
|
|
35076
|
+
...TEST_COMMAND_SOURCES,
|
|
35077
|
+
"developer-declared",
|
|
35078
|
+
"operator-declared"
|
|
35079
|
+
];
|
|
35080
|
+
RUN_IMAGE_SOURCES = [
|
|
35081
|
+
"detected",
|
|
35082
|
+
"none",
|
|
35083
|
+
"operator-declared",
|
|
35084
|
+
"developer-declared"
|
|
35085
|
+
];
|
|
34733
35086
|
RUN_RESULT_SCHEMA = "terminalhire.verification-run/1";
|
|
34734
35087
|
RUN_RESULT_FIELDS = [
|
|
34735
35088
|
"schema",
|
|
@@ -34754,7 +35107,9 @@ var init_result = __esm({
|
|
|
34754
35107
|
"preview",
|
|
34755
35108
|
"containerImage",
|
|
34756
35109
|
"containerImageDigest",
|
|
35110
|
+
"imageSource",
|
|
34757
35111
|
"leaksClean",
|
|
35112
|
+
"leakState",
|
|
34758
35113
|
"venue"
|
|
34759
35114
|
];
|
|
34760
35115
|
RENDER_NONE = null;
|
|
@@ -34786,12 +35141,42 @@ var init_result = __esm({
|
|
|
34786
35141
|
preview: (r) => r.preview === null ? null : `preview ${r.preview.url}`,
|
|
34787
35142
|
containerImage: (r) => r.containerImage === null ? null : `image ${r.containerImage}`,
|
|
34788
35143
|
containerImageDigest: (r) => r.containerImageDigest === null ? null : `image digest ${r.containerImageDigest}`,
|
|
34789
|
-
|
|
35144
|
+
// Shown only when a human chose the environment. `detected` is the ordinary case and
|
|
35145
|
+
// saying so on every run would train the reader to skip the line that matters.
|
|
35146
|
+
imageSource: (r) => r.imageSource === "detected" || r.imageSource === "none" ? null : `image source ${r.imageSource} (not signed)`,
|
|
35147
|
+
// Printed through `leakState` below, which knows WHY a false is false. Rendering both would
|
|
35148
|
+
// print the leak warning on a run where we merely could not look (TERM-1144).
|
|
35149
|
+
leaksClean: RENDER_NONE,
|
|
35150
|
+
// Silent when clean and when refused, as the boolean's line was. The two not-a-leak states
|
|
35151
|
+
// get their own sentence, because "we could not check" read as "we found a leak" is the
|
|
35152
|
+
// exact confusion this field exists to end.
|
|
35153
|
+
leakState: (r) => {
|
|
35154
|
+
switch (r.leakState) {
|
|
35155
|
+
case null:
|
|
35156
|
+
case "clean":
|
|
35157
|
+
return null;
|
|
35158
|
+
case "leak":
|
|
35159
|
+
return "WARNING labelled Docker objects survived teardown";
|
|
35160
|
+
case "inconclusive":
|
|
35161
|
+
return "leak check inconclusive \u2014 no labelled container was seen while the run was live, so finding nothing afterwards proves nothing";
|
|
35162
|
+
case "unobserved":
|
|
35163
|
+
return "leak check not taken \u2014 we could not check what was left after teardown";
|
|
35164
|
+
}
|
|
35165
|
+
},
|
|
34790
35166
|
// Absent on most runs, so it prints only when there is something to say. Silence
|
|
34791
35167
|
// here is the honest rendering of "no venue answered": a placeholder line would
|
|
34792
35168
|
// invite a reader to treat an unanswered probe as a described venue.
|
|
34793
35169
|
venue: (r) => r.venue === null ? null : renderVenueLine(r.venue)
|
|
34794
35170
|
};
|
|
35171
|
+
OUTCOME_EXIT_CODES = {
|
|
35172
|
+
completed: 0,
|
|
35173
|
+
"tests-failed": 1,
|
|
35174
|
+
"no-tests-observed": 1,
|
|
35175
|
+
"budget-exceeded": 1,
|
|
35176
|
+
"counts-unparsed": 2,
|
|
35177
|
+
"test-command-unavailable": 2,
|
|
35178
|
+
"environment-exhausted": 2
|
|
35179
|
+
};
|
|
34795
35180
|
}
|
|
34796
35181
|
});
|
|
34797
35182
|
|
|
@@ -34912,12 +35297,23 @@ function toAcceptancePredicate(pair, opts = {}) {
|
|
|
34912
35297
|
if (why !== null)
|
|
34913
35298
|
return refuse3("test-command-origin-unattested", `the ${side} run ${why}`);
|
|
34914
35299
|
}
|
|
34915
|
-
if (patched.testCommandSource === "developer-declared") {
|
|
34916
|
-
return refuse3("test-command-origin-unattested", "the developer supplied the test command (unreachable \u2014 the source rules above cover it)
|
|
35300
|
+
if (patched.testCommandSource === "developer-declared" || patched.testCommandSource === "operator-declared") {
|
|
35301
|
+
return refuse3("test-command-origin-unattested", `${patched.testCommandSource === "developer-declared" ? "the developer" : "an operator"} supplied the test command (unreachable \u2014 the source rules above cover it)`);
|
|
34917
35302
|
}
|
|
34918
35303
|
if (baseline.testCommandSource !== patched.testCommandSource) {
|
|
34919
35304
|
return refuse3("test-command-origin-unattested", `the pair disagrees on where the command came from: baseline ${baseline.testCommandSource}, patched ${patched.testCommandSource}. One signed value cannot describe both.`);
|
|
34920
35305
|
}
|
|
35306
|
+
for (const [side, source, image] of [
|
|
35307
|
+
["patched", patched.imageSource, patched.containerImage],
|
|
35308
|
+
["baseline", baseline.imageSource, baseline.containerImage]
|
|
35309
|
+
]) {
|
|
35310
|
+
const why = IMAGE_SOURCE_IS_SIGNABLE[source](image);
|
|
35311
|
+
if (why !== null)
|
|
35312
|
+
return refuse3("image-origin-unattested", `the ${side} run ${why}`);
|
|
35313
|
+
}
|
|
35314
|
+
if (baseline.imageSource !== patched.imageSource) {
|
|
35315
|
+
return refuse3("image-origin-unattested", `the pair disagrees on where the image came from: baseline ${baseline.imageSource}, patched ${patched.imageSource}. The environment is part of what the statement says was held constant.`);
|
|
35316
|
+
}
|
|
34921
35317
|
if (baseline.containerImage !== patched.containerImage) {
|
|
34922
35318
|
return refuse3("pair-disagrees-on-image", `baseline ran in ${String(baseline.containerImage)} and patched in ${String(patched.containerImage)}. The signed measurement names one image, so a pair from two environments would attribute to the patch whatever the image changed.`);
|
|
34923
35319
|
}
|
|
@@ -34974,7 +35370,7 @@ function signRunStatement(predicate, privateKey, keyid) {
|
|
|
34974
35370
|
const statement = createAcceptanceStatement(predicate);
|
|
34975
35371
|
return { statement, envelope: signStatement(statement, privateKey, keyid) };
|
|
34976
35372
|
}
|
|
34977
|
-
var OUTCOME_TO_BUDGET, BASELINE_IS_A_VERDICT, CONTRADICTS_COUNTS, SOURCE_IS_SIGNABLE, ATTEST_REFUSAL_REASONS, refuse3, LOCAL_MEASUREMENT_PREFIX, REFERENCE_DOMAIN_COMPONENT, REFERENCE_DOMAIN_NAME, REFERENCE_IPV6, REFERENCE_DOMAIN, REFERENCE_PATH_COMPONENT, REPO_DIGEST_RE;
|
|
35373
|
+
var OUTCOME_TO_BUDGET, BASELINE_IS_A_VERDICT, CONTRADICTS_COUNTS, SOURCE_IS_SIGNABLE, IMAGE_SOURCE_IS_SIGNABLE, ATTEST_REFUSAL_REASONS, refuse3, LOCAL_MEASUREMENT_PREFIX, REFERENCE_DOMAIN_COMPONENT, REFERENCE_DOMAIN_NAME, REFERENCE_IPV6, REFERENCE_DOMAIN, REFERENCE_PATH_COMPONENT, REPO_DIGEST_RE;
|
|
34978
35374
|
var init_attestation2 = __esm({
|
|
34979
35375
|
"../../packages/envrun/dist/attestation.js"() {
|
|
34980
35376
|
"use strict";
|
|
@@ -35030,11 +35426,25 @@ var init_attestation2 = __esm({
|
|
|
35030
35426
|
// The party under verification chose it, and no signed member can say so. Per ADR-005
|
|
35031
35427
|
// Decision 2, emit nothing rather than pick the closest word.
|
|
35032
35428
|
"developer-declared": () => "had its test command supplied by the developer whose work is under verification, and the signed vocabulary has no member for that. `founder-declared` would attribute the choice to the other party; `detected` would claim the repo chose it. Both are false.",
|
|
35429
|
+
// US, out of band, per posting — the twin of `IMAGE_SOURCE_IS_SIGNABLE['operator-declared']`
|
|
35430
|
+
// and refusing for the same reason. `founder-declared` is the nearest signed member and it
|
|
35431
|
+
// is still false: the poster did not choose this, we did, and signing our own choice under
|
|
35432
|
+
// the counterparty's name is the specific false attribution the `developer-declared` entry
|
|
35433
|
+
// above exists to refuse. Decision 2 — emit nothing rather than pick the closest word.
|
|
35434
|
+
"operator-declared": () => "had its test command chosen by an operator out of band, and the signed vocabulary has no member for that. Signing it would present a hand-picked command as one the repository chose for itself.",
|
|
35033
35435
|
// `none` means nobody chose a command, so a command beside it is a contradiction. Shadowed
|
|
35034
35436
|
// today — `thrun.ts` sets `none` only when the derived command is null, and `no-test-command`
|
|
35035
35437
|
// fires first — but that coupling runs through `runEnvironmentSpec` and lives in no type.
|
|
35036
35438
|
none: (command) => command === null ? null : `records its command source as \`none\` \u2014 nobody chose one \u2014 beside the command ${JSON.stringify(command)}`
|
|
35037
35439
|
};
|
|
35440
|
+
IMAGE_SOURCE_IS_SIGNABLE = {
|
|
35441
|
+
detected: () => null,
|
|
35442
|
+
"operator-declared": () => "had its container image chosen by an operator out of band, and the signed vocabulary has no member for that. Signing it would present a hand-picked environment as the one the runtime mapping selected.",
|
|
35443
|
+
"developer-declared": () => "had its container image supplied by the developer whose work is under verification. A chosen interpreter turns a red suite green as surely as a chosen test command.",
|
|
35444
|
+
// `none` means no image was booted, so an image name beside it is a contradiction — the
|
|
35445
|
+
// `SOURCE_IS_SIGNABLE.none` argument, applied to the other field.
|
|
35446
|
+
none: (image) => image === null ? null : `records its image source as \`none\` \u2014 nothing was booted \u2014 beside the image ${JSON.stringify(image)}`
|
|
35447
|
+
};
|
|
35038
35448
|
ATTEST_REFUSAL_REASONS = [
|
|
35039
35449
|
"our-environment-failed",
|
|
35040
35450
|
"run-was-refused",
|
|
@@ -35076,7 +35486,11 @@ var init_attestation2 = __esm({
|
|
|
35076
35486
|
// The signed triple must be reproducible from what it names — see the guard.
|
|
35077
35487
|
"patch-binding-incomplete",
|
|
35078
35488
|
"outcome-contradicts-counts",
|
|
35079
|
-
"test-command-origin-unattested"
|
|
35489
|
+
"test-command-origin-unattested",
|
|
35490
|
+
// The environment half of the pair above. `pair-disagrees-on-image` compares image NAMES;
|
|
35491
|
+
// this one asks who CHOSE the name, which no comparison of the two halves can reveal when
|
|
35492
|
+
// both were handed the same override.
|
|
35493
|
+
"image-origin-unattested"
|
|
35080
35494
|
];
|
|
35081
35495
|
refuse3 = (reason, detail) => ({
|
|
35082
35496
|
ok: false,
|
|
@@ -35580,13 +35994,20 @@ function gcpBootArgv(p) {
|
|
|
35580
35994
|
// steal". Attaching an account removes that, so the safety now rests on two things,
|
|
35581
35995
|
// and this change MUST land together with proof #2 — never ahead of it:
|
|
35582
35996
|
//
|
|
35583
|
-
// 1. `--no-scopes`
|
|
35584
|
-
// No scopes → the OAuth access-token endpoint serves nothing
|
|
35585
|
-
// TERM-706)
|
|
35586
|
-
//
|
|
35587
|
-
//
|
|
35588
|
-
//
|
|
35589
|
-
//
|
|
35997
|
+
// 1. `--no-scopes` and a NARROW grant set bound the BLAST RADIUS of a lifted
|
|
35998
|
+
// token. No scopes → the OAuth access-token endpoint serves nothing
|
|
35999
|
+
// (measured, TERM-706). This said "ZERO project roles" until 2026-09-18, and
|
|
36000
|
+
// that was never true of the account we ship: measured live, `venue-identity@`
|
|
36001
|
+
// holds `roles/confidentialcomputing.workloadUser` on the project and
|
|
36002
|
+
// `roles/artifactregistry.reader` on the `venue-images` repository alone —
|
|
36003
|
+
// the same two grants the Confidential Space note below already named, so this
|
|
36004
|
+
// file contradicted itself. Neither reaches a second repository, a bucket or
|
|
36005
|
+
// another VM, which is the property "zero roles" was reaching for. But the
|
|
36006
|
+
// token is NOT valueless: it is the attestation evidence itself, so a lifted
|
|
36007
|
+
// token still authorizes a false claim about WHERE a run happened (the
|
|
36008
|
+
// steal-a-true-token attack in the item-2 spike). `--no-scopes` stays because
|
|
36009
|
+
// it removes lateral GCP access; it does not make losing the identity token
|
|
36010
|
+
// cheap.
|
|
35590
36011
|
// 2. The untrusted code cannot reach the metadata server to lift the token at all.
|
|
35591
36012
|
// The test step runs `--network=none`; the install step runs on an `--internal`
|
|
35592
36013
|
// network whose only egress is a CONNECT-only, registry-allowlisted proxy that
|
|
@@ -37066,11 +37487,7 @@ function makeLease(p) {
|
|
|
37066
37487
|
}
|
|
37067
37488
|
try {
|
|
37068
37489
|
check("counting what the run left behind");
|
|
37069
|
-
return Promise.resolve(
|
|
37070
|
-
observed: true,
|
|
37071
|
-
census: census(p.docker, label),
|
|
37072
|
-
unobservedReason: null
|
|
37073
|
-
});
|
|
37490
|
+
return Promise.resolve(censusReport(p.docker, label));
|
|
37074
37491
|
} catch (err) {
|
|
37075
37492
|
return Promise.resolve({
|
|
37076
37493
|
observed: false,
|
|
@@ -37338,7 +37755,7 @@ function localDockerPlacement() {
|
|
|
37338
37755
|
kind: "local-docker",
|
|
37339
37756
|
refusal: null,
|
|
37340
37757
|
venue: () => localVenue(),
|
|
37341
|
-
imageFor: (runtime, override, version2) => imageForRuntime(runtime, override, version2)
|
|
37758
|
+
imageFor: (runtime, override, version2, variant) => imageForRuntime(runtime, override, version2, variant)
|
|
37342
37759
|
};
|
|
37343
37760
|
}
|
|
37344
37761
|
function hostedPoolPlacement() {
|
|
@@ -37346,7 +37763,7 @@ function hostedPoolPlacement() {
|
|
|
37346
37763
|
kind: "hosted-pool",
|
|
37347
37764
|
refusal: null,
|
|
37348
37765
|
venue: () => hostedVenue(),
|
|
37349
|
-
imageFor: (runtime, override, version2) => imageForRuntime(runtime, override, version2)
|
|
37766
|
+
imageFor: (runtime, override, version2, variant) => imageForRuntime(runtime, override, version2, variant)
|
|
37350
37767
|
};
|
|
37351
37768
|
}
|
|
37352
37769
|
function placementFor(kind) {
|
|
@@ -37911,6 +38328,9 @@ function detectRuntime(repo) {
|
|
|
37911
38328
|
if (repo.listNames("").some((name) => /\.(?:csproj|fsproj|sln)$/.test(name))) {
|
|
37912
38329
|
candidates.push("dotnet");
|
|
37913
38330
|
}
|
|
38331
|
+
if (candidates.length === 0 && repo.listFiles("").some((f) => f.endsWith(".java"))) {
|
|
38332
|
+
candidates.push("jvm");
|
|
38333
|
+
}
|
|
37914
38334
|
return { runtime: candidates[0] ?? "unknown", candidates };
|
|
37915
38335
|
}
|
|
37916
38336
|
function readJsonObject(repo, path6) {
|
|
@@ -38058,6 +38478,11 @@ function basePythonInstallCommand(repo) {
|
|
|
38058
38478
|
}
|
|
38059
38479
|
return null;
|
|
38060
38480
|
}
|
|
38481
|
+
function rehearse(command) {
|
|
38482
|
+
const copy = '"$R/.terminalhire-rehearsal"';
|
|
38483
|
+
const home = '"$R/.terminalhire-rehearsal-home"';
|
|
38484
|
+
return `{ R="$HOME"; rm -rf ${copy} ${home}; mkdir -p ${home} && cp -R . ${copy} && (cd ${copy} && HOME=${home} GRADLE_USER_HOME="$R/.gradle" JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -Duser.home=$R/.terminalhire-rehearsal-home" ${command}); rm -rf ${copy} ${home}; true; }`;
|
|
38485
|
+
}
|
|
38061
38486
|
function otherRuntimeCommands(repo, runtime) {
|
|
38062
38487
|
switch (runtime) {
|
|
38063
38488
|
case "go":
|
|
@@ -38085,10 +38510,21 @@ function otherRuntimeCommands(repo, runtime) {
|
|
|
38085
38510
|
case "dotnet":
|
|
38086
38511
|
return { install: "dotnet restore", test: "dotnet test" };
|
|
38087
38512
|
case "jvm": {
|
|
38088
|
-
if (repo.exists(
|
|
38089
|
-
return { install:
|
|
38513
|
+
if (!JVM_BUILD_FILES.some((file) => repo.exists(file)))
|
|
38514
|
+
return { install: null, test: null };
|
|
38515
|
+
if (repo.exists("pom.xml")) {
|
|
38516
|
+
return {
|
|
38517
|
+
install: `mvn -B dependency:go-offline && ${rehearse('mvn -B test -Dmaven.test.failure.ignore=true -Dmaven.repo.local="$R/.m2/repository"')}`,
|
|
38518
|
+
test: "mvn -B -o test"
|
|
38519
|
+
};
|
|
38520
|
+
}
|
|
38090
38521
|
const wrapper = repo.exists("gradlew") ? "./gradlew" : "gradle";
|
|
38091
|
-
return {
|
|
38522
|
+
return {
|
|
38523
|
+
install: `${wrapper} dependencies && ${rehearse(`${wrapper} test --continue`)}`,
|
|
38524
|
+
// `--no-build-cache`: the rehearsal above can fill Gradle's build cache, and a
|
|
38525
|
+
// test task restored FROM-CACHE runs nothing and prints no count.
|
|
38526
|
+
test: `${wrapper} test --offline --no-build-cache`
|
|
38527
|
+
};
|
|
38092
38528
|
}
|
|
38093
38529
|
default:
|
|
38094
38530
|
return { install: null, test: null };
|
|
@@ -38120,6 +38556,15 @@ function searchRuntimeVersion(repo, runtime) {
|
|
|
38120
38556
|
push(".ruby-version", repo.readText(".ruby-version"));
|
|
38121
38557
|
} else if (runtime === "dotnet") {
|
|
38122
38558
|
push("global.json sdk.version", readStringField(readObjectField(readJsonObject(repo, "global.json"), "sdk"), "version"));
|
|
38559
|
+
} else if (runtime === "jvm") {
|
|
38560
|
+
const pom = repo.readText("pom.xml");
|
|
38561
|
+
const gradle = repo.readText("build.gradle") ?? repo.readText("build.gradle.kts");
|
|
38562
|
+
push("build.gradle toolchain languageVersion", javaMajor(matchFirst(gradle, /JavaLanguageVersion\.of\(\s*["']?(\d+)["']?\s*\)/) ?? matchFirst(gradle, /jvmToolchain\(\s*(\d+)\s*\)/)));
|
|
38563
|
+
push(".java-version", javaMajor(repo.readText(".java-version")));
|
|
38564
|
+
push("pom.xml maven.compiler.release", javaMajor(matchFirst(pom, /<maven\.compiler\.release>\s*([^<\s]+)\s*</)));
|
|
38565
|
+
push("pom.xml java.version", javaMajor(matchFirst(pom, /<java\.version>\s*([^<\s]+)\s*</)));
|
|
38566
|
+
push("pom.xml maven.compiler.source", javaMajor(matchFirst(pom, /<maven\.compiler\.source>\s*([^<\s]+)\s*</)));
|
|
38567
|
+
push("build.gradle sourceCompatibility", javaMajor(matchFirst(gradle, /sourceCompatibility\s*=\s*JavaVersion\.VERSION_([\d_]+)/)?.replace("_", ".") ?? matchFirst(gradle, /sourceCompatibility\s*=\s*["']?([\d.]+)["']?/)));
|
|
38123
38568
|
}
|
|
38124
38569
|
let rangeFound = null;
|
|
38125
38570
|
for (const source of sources) {
|
|
@@ -38133,13 +38578,21 @@ function searchRuntimeVersion(repo, runtime) {
|
|
|
38133
38578
|
}
|
|
38134
38579
|
return { version: null, searched: sources.map((s) => s.label), rangeFound };
|
|
38135
38580
|
}
|
|
38581
|
+
function javaMajor(text) {
|
|
38582
|
+
if (text === null)
|
|
38583
|
+
return null;
|
|
38584
|
+
const match2 = /^(?:1\.(\d+)|(\d+))(?:[._][\d_.]*)?$/.exec(text.trim());
|
|
38585
|
+
if (match2 === null)
|
|
38586
|
+
return null;
|
|
38587
|
+
return match2[1] ?? match2[2] ?? null;
|
|
38588
|
+
}
|
|
38136
38589
|
function matchFirst(text, pattern) {
|
|
38137
38590
|
if (text === null)
|
|
38138
38591
|
return null;
|
|
38139
38592
|
const match2 = pattern.exec(text);
|
|
38140
38593
|
return match2 === null ? null : match2[1];
|
|
38141
38594
|
}
|
|
38142
|
-
var RUNTIME_MANIFESTS, MANIFEST_FILENAMES, NPM_PLACEHOLDER_TEST, REQUIREMENT_SPECIFIER, EXACT_VERSION;
|
|
38595
|
+
var RUNTIME_MANIFESTS, MANIFEST_FILENAMES, JVM_BUILD_FILES, NPM_PLACEHOLDER_TEST, REQUIREMENT_SPECIFIER, EXACT_VERSION;
|
|
38143
38596
|
var init_manifest2 = __esm({
|
|
38144
38597
|
"../../packages/envspec/dist/manifest.js"() {
|
|
38145
38598
|
"use strict";
|
|
@@ -38153,6 +38606,7 @@ var init_manifest2 = __esm({
|
|
|
38153
38606
|
{ runtime: "dotnet", files: [] }
|
|
38154
38607
|
];
|
|
38155
38608
|
MANIFEST_FILENAMES = RUNTIME_MANIFESTS.flatMap((m) => m.files).concat(["*.csproj", "*.fsproj", "*.sln"]).sort();
|
|
38609
|
+
JVM_BUILD_FILES = ["build.gradle", "build.gradle.kts", "pom.xml"];
|
|
38156
38610
|
NPM_PLACEHOLDER_TEST = /^echo\s+["']?Error:\s*no test specified["']?\s*&&\s*exit\s+1$/;
|
|
38157
38611
|
REQUIREMENT_SPECIFIER = /^[A-Za-z0-9._-]+(\[[A-Za-z0-9._,-]+\])?([<>=!~]=?[A-Za-z0-9._*+-]+(,[<>=!~]=?[A-Za-z0-9._*+-]+)*)?$/;
|
|
38158
38612
|
EXACT_VERSION = /^v?(\d+(?:\.\d+){0,2})$/;
|
|
@@ -38549,7 +39003,7 @@ function deriveFromReader(repo) {
|
|
|
38549
39003
|
searched: MANIFEST_FILENAMES,
|
|
38550
39004
|
detail: `no ecosystem manifest was found at the repo root (looked for ${MANIFEST_FILENAMES.join(", ")}), so the language runtime could not be identified`
|
|
38551
39005
|
});
|
|
38552
|
-
} else {
|
|
39006
|
+
} else if (runtime !== "jvm" || JVM_BUILD_FILES.some((file) => repo.exists(file))) {
|
|
38553
39007
|
derivedFrom.add("manifest");
|
|
38554
39008
|
}
|
|
38555
39009
|
if (detection.candidates.length > 1) {
|
|
@@ -38713,12 +39167,13 @@ function deriveRuntimeVersion(repo, runtime, job) {
|
|
|
38713
39167
|
const setup = SETUP_ACTIONS[runtime];
|
|
38714
39168
|
const searched = [];
|
|
38715
39169
|
let rangeFound = null;
|
|
39170
|
+
const pin = (raw) => runtime === "jvm" ? javaMajor(raw) : exactVersion(raw);
|
|
38716
39171
|
if (job !== null && setup !== void 0) {
|
|
38717
39172
|
const direct = findActionInput(job, setup.action, setup.input);
|
|
38718
39173
|
if (direct !== null) {
|
|
38719
39174
|
searched.push(`${job.file} ${setup.action} ${setup.input}`);
|
|
38720
39175
|
const reduced = reduceExpression(direct.command, job.singletons);
|
|
38721
|
-
const exact =
|
|
39176
|
+
const exact = pin(reduced);
|
|
38722
39177
|
if (exact !== null)
|
|
38723
39178
|
return { value: exact, searched, rangeFound: null };
|
|
38724
39179
|
if (reduced !== null)
|
|
@@ -38727,7 +39182,7 @@ function deriveRuntimeVersion(repo, runtime, job) {
|
|
|
38727
39182
|
const viaFile = findActionInput(job, setup.action, setup.fileInput);
|
|
38728
39183
|
if (viaFile !== null) {
|
|
38729
39184
|
searched.push(`${job.file} ${setup.action} ${setup.fileInput} -> ${viaFile.command}`);
|
|
38730
|
-
const exact =
|
|
39185
|
+
const exact = pin(repo.readText(viaFile.command));
|
|
38731
39186
|
if (exact !== null)
|
|
38732
39187
|
return { value: exact, searched, rangeFound: null };
|
|
38733
39188
|
}
|
|
@@ -38752,6 +39207,8 @@ function testSearchPaths(runtime, workflowFiles) {
|
|
|
38752
39207
|
paths.push("**/*_test.go");
|
|
38753
39208
|
if (runtime === "ruby")
|
|
38754
39209
|
paths.push("Gemfile", "Rakefile");
|
|
39210
|
+
if (runtime === "jvm")
|
|
39211
|
+
paths.push(...JVM_BUILD_FILES);
|
|
38755
39212
|
if (runtime === "unknown")
|
|
38756
39213
|
paths.push(...MANIFEST_FILENAMES);
|
|
38757
39214
|
return [...new Set(paths)].sort();
|
|
@@ -38769,6 +39226,9 @@ function describeTestSearch(repo, runtime, workflowFiles) {
|
|
|
38769
39226
|
if (runtime === "python") {
|
|
38770
39227
|
return `${ciPart}, and nothing in the repo names a test runner \u2014 no \`[tool.pytest.ini_options]\`, no \`pytest.ini\`, and no pytest dependency in \`pyproject.toml\` or a requirements file`;
|
|
38771
39228
|
}
|
|
39229
|
+
if (runtime === "jvm" && !JVM_BUILD_FILES.some((file) => repo.exists(file))) {
|
|
39230
|
+
return `${ciPart}, and the repo has Java sources but no build file (${JVM_BUILD_FILES.join(", ")}), so there is no build to run tests with. Compiling the sources with \`javac\` alone would run no tests`;
|
|
39231
|
+
}
|
|
38772
39232
|
return `${ciPart}, and no ${runtime} test convention applies to this tree`;
|
|
38773
39233
|
}
|
|
38774
39234
|
function installSearchPaths(runtime, workflowFiles) {
|
|
@@ -38777,6 +39237,8 @@ function installSearchPaths(runtime, workflowFiles) {
|
|
|
38777
39237
|
paths.push("package-lock.json", "pnpm-lock.yaml", "yarn.lock");
|
|
38778
39238
|
if (runtime === "python")
|
|
38779
39239
|
paths.push("poetry.lock", "pyproject.toml", "requirements.txt", "uv.lock");
|
|
39240
|
+
if (runtime === "jvm")
|
|
39241
|
+
paths.push(...JVM_BUILD_FILES);
|
|
38780
39242
|
if (runtime === "unknown")
|
|
38781
39243
|
paths.push(...MANIFEST_FILENAMES);
|
|
38782
39244
|
return [...new Set(paths)].sort();
|
|
@@ -38855,12 +39317,41 @@ var init_dist3 = __esm({
|
|
|
38855
39317
|
}
|
|
38856
39318
|
});
|
|
38857
39319
|
|
|
39320
|
+
// ../../packages/envrun/dist/gradleTestSummary.js
|
|
39321
|
+
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync23 } from "fs";
|
|
39322
|
+
import { join as join42 } from "path";
|
|
39323
|
+
function stageGradleTestSummary(jailHome) {
|
|
39324
|
+
const dir = join42(jailHome, ".gradle", "init.d");
|
|
39325
|
+
mkdirSync7(dir, { recursive: true });
|
|
39326
|
+
writeFileSync23(join42(dir, "terminalhire-test-summary.gradle"), GRADLE_TEST_SUMMARY_INIT);
|
|
39327
|
+
}
|
|
39328
|
+
var GRADLE_TEST_MARKER, GRADLE_TEST_SUMMARY_INIT;
|
|
39329
|
+
var init_gradleTestSummary = __esm({
|
|
39330
|
+
"../../packages/envrun/dist/gradleTestSummary.js"() {
|
|
39331
|
+
"use strict";
|
|
39332
|
+
GRADLE_TEST_MARKER = "terminalhire-gradle-tests:";
|
|
39333
|
+
GRADLE_TEST_SUMMARY_INIT = `// Written by terminalhire (TERM-1122): prints each Test task's counts, because
|
|
39334
|
+
// Gradle prints none when every test passes.
|
|
39335
|
+
allprojects {
|
|
39336
|
+
tasks.withType(Test).configureEach { task ->
|
|
39337
|
+
def label = task.path
|
|
39338
|
+
task.afterSuite { desc, result ->
|
|
39339
|
+
if (desc.parent == null) {
|
|
39340
|
+
println "${GRADLE_TEST_MARKER} task=\${label} total=\${result.testCount} passed=\${result.successfulTestCount} failed=\${result.failedTestCount} skipped=\${result.skippedTestCount}"
|
|
39341
|
+
}
|
|
39342
|
+
}
|
|
39343
|
+
}
|
|
39344
|
+
}
|
|
39345
|
+
`;
|
|
39346
|
+
}
|
|
39347
|
+
});
|
|
39348
|
+
|
|
38858
39349
|
// ../../packages/envrun/dist/thrun.js
|
|
38859
39350
|
import { execFileSync, spawnSync as spawnSync7 } from "child_process";
|
|
38860
|
-
import { existsSync as existsSync19, mkdirSync as
|
|
39351
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync8, mkdtempSync as mkdtempSync4, rmSync as rmSync11 } from "fs";
|
|
38861
39352
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
38862
39353
|
import { tmpdir as tmpdir4 } from "os";
|
|
38863
|
-
import { join as
|
|
39354
|
+
import { join as join43 } from "path";
|
|
38864
39355
|
function git(repoDir, args5, allowNonZero = false) {
|
|
38865
39356
|
const res = spawnSync7("git", [...args5], {
|
|
38866
39357
|
cwd: repoDir,
|
|
@@ -38875,7 +39366,7 @@ function git(repoDir, args5, allowNonZero = false) {
|
|
|
38875
39366
|
return res.stdout ?? "";
|
|
38876
39367
|
}
|
|
38877
39368
|
function collectWorkingDiff(repoDir, opts = {}) {
|
|
38878
|
-
if (!existsSync19(
|
|
39369
|
+
if (!existsSync19(join43(repoDir, ".git"))) {
|
|
38879
39370
|
throw new ThRunError(`${repoDir} is not a git checkout (no .git). \`th run\` ships the working diff, so it needs a repository to read one from.`);
|
|
38880
39371
|
}
|
|
38881
39372
|
const headSha = git(repoDir, ["rev-parse", "HEAD"]).trim();
|
|
@@ -39023,7 +39514,7 @@ function credentialFreeHome() {
|
|
|
39023
39514
|
return credentialFreeHomeDir;
|
|
39024
39515
|
let made;
|
|
39025
39516
|
try {
|
|
39026
|
-
made = mkdtempSync4(
|
|
39517
|
+
made = mkdtempSync4(join43(tmpdir4(), "th-run-nohome-"));
|
|
39027
39518
|
} catch (err) {
|
|
39028
39519
|
throw new RunRefusalError("could not create the empty directory this clone uses as its home, so the clone would read the credentials on this machine instead. That is our environment failing, not your tests: check that the temp directory is writable.", { cause: err });
|
|
39029
39520
|
}
|
|
@@ -39098,7 +39589,7 @@ function cloneTargetAtUnguarded(opts) {
|
|
|
39098
39589
|
if (persisted !== null) {
|
|
39099
39590
|
throw new RunRefusalError(`refusing to clone from a URL carrying ${persisted}: \`git remote add\` writes the source verbatim into .git/config, which is mounted where the repo\u2019s own test command runs. Fetch with the credential out of band so it is never written to disk \u2014 this runner takes one as an HTTP header, which is never persisted.`);
|
|
39100
39591
|
}
|
|
39101
|
-
|
|
39592
|
+
mkdirSync8(opts.dest, { recursive: true });
|
|
39102
39593
|
const runOut = (args5) => execFileSync("git", [...gitConfigArgs(), ...args5], {
|
|
39103
39594
|
cwd: opts.dest,
|
|
39104
39595
|
encoding: "utf8",
|
|
@@ -39137,7 +39628,7 @@ function cloneTargetAtUnguarded(opts) {
|
|
|
39137
39628
|
}
|
|
39138
39629
|
function scrubCloneSource(dest, run32) {
|
|
39139
39630
|
run32(["remote", "remove", "origin"]);
|
|
39140
|
-
rmSync11(
|
|
39631
|
+
rmSync11(join43(dest, ".git", "FETCH_HEAD"), { force: true });
|
|
39141
39632
|
}
|
|
39142
39633
|
function publishableTarget(url) {
|
|
39143
39634
|
if (separatorInTarget(url) !== null)
|
|
@@ -39276,12 +39767,18 @@ function refusedRun(fields) {
|
|
|
39276
39767
|
treeDigest: null,
|
|
39277
39768
|
baselinePatchSha256: null,
|
|
39278
39769
|
testCommandSource: "none",
|
|
39770
|
+
// Nothing was booted, so nobody chose an image. Same reasoning as `containerImage: null`
|
|
39771
|
+
// below: it must not read as an image we picked and cannot name.
|
|
39772
|
+
imageSource: "none",
|
|
39279
39773
|
boundaryRefusals: fields.boundaryRefusals,
|
|
39280
39774
|
touchedPaths: fields.touchedPaths,
|
|
39281
39775
|
preview: null,
|
|
39282
39776
|
containerImage: null,
|
|
39283
39777
|
containerImageDigest: null,
|
|
39284
39778
|
leaksClean: null,
|
|
39779
|
+
// Null for the same reason, and never `unobserved`: that word says we tried to take a
|
|
39780
|
+
// census and could not, and here there was nothing to take one of (TERM-1144).
|
|
39781
|
+
leakState: null,
|
|
39285
39782
|
// A refused run never held a lease, so there is no venue to describe. Same
|
|
39286
39783
|
// reasoning as `leaksClean` above: null because nothing happened, and it must
|
|
39287
39784
|
// not read as a venue we looked at and could not name.
|
|
@@ -39509,10 +40006,10 @@ async function runVerification(req, ctx) {
|
|
|
39509
40006
|
venueIdentity: null
|
|
39510
40007
|
};
|
|
39511
40008
|
}
|
|
39512
|
-
const stage =
|
|
39513
|
-
const cloneDir =
|
|
39514
|
-
const scratch =
|
|
39515
|
-
|
|
40009
|
+
const stage = join43(req.scratchRoot, runId);
|
|
40010
|
+
const cloneDir = join43(stage, "clone");
|
|
40011
|
+
const scratch = join43(stage, "scratch");
|
|
40012
|
+
mkdirSync8(scratch, { recursive: true });
|
|
39516
40013
|
assertSafeTargetSha(req.targetSha);
|
|
39517
40014
|
progress("clone", `${publishableTarget(req.targetRepo)} @ ${req.targetSha.slice(0, 12)}`);
|
|
39518
40015
|
cloneTargetAt({
|
|
@@ -39539,7 +40036,8 @@ async function runVerification(req, ctx) {
|
|
|
39539
40036
|
const derived = deriveEnvironmentSpec(cloneDir);
|
|
39540
40037
|
const spec = req.testCommandOverride === void 0 ? derived : { ...derived, testCommand: req.testCommandOverride };
|
|
39541
40038
|
progress("derive", `runtime=${spec.runtime} install=${String(spec.installCommand)} test=${String(spec.testCommand)}`);
|
|
39542
|
-
|
|
40039
|
+
refuseUnbuildableSpec(spec);
|
|
40040
|
+
const image = placement.imageFor(spec.runtime, req.image, spec.runtimeVersion, imageVariantFor(spec));
|
|
39543
40041
|
const resolved = await resolveLease(placement, runId);
|
|
39544
40042
|
if (!resolved.ok) {
|
|
39545
40043
|
return {
|
|
@@ -39574,10 +40072,12 @@ async function runVerification(req, ctx) {
|
|
|
39574
40072
|
const lease = resolved.lease;
|
|
39575
40073
|
try {
|
|
39576
40074
|
buildJail(scratch);
|
|
40075
|
+
if (spec.runtime === "jvm")
|
|
40076
|
+
stageGradleTestSummary(localJailPaths(scratch).jail);
|
|
39577
40077
|
const venuePaths = await lease.stage({
|
|
39578
40078
|
cloneDir,
|
|
39579
40079
|
scratchRoot: scratch,
|
|
39580
|
-
previewDir:
|
|
40080
|
+
previewDir: join43(stage, "preview"),
|
|
39581
40081
|
// On a dispatched run the commit is the statement of what was tested, so
|
|
39582
40082
|
// it rides with the tree and the venue seam refuses a tree that is not
|
|
39583
40083
|
// that commit (design §6 item 4, TERM-892 — the guard lives in
|
|
@@ -39624,7 +40124,7 @@ async function runVerification(req, ctx) {
|
|
|
39624
40124
|
// that `founder-declared` (as this did for one review round) signs the counterparty's
|
|
39625
40125
|
// name onto the developer's choice, which is worse than laundering it as `detected`:
|
|
39626
40126
|
// it is a specific false attribution inside a field a reviewer trusts.
|
|
39627
|
-
testCommandSource: req.testCommandOverride !== void 0 ? req.testCommandOverrideOrigin === "founder" ? "founder-declared" : "developer-declared" : derived.testCommand === null ? "none" : "detected",
|
|
40127
|
+
testCommandSource: req.testCommandOverride !== void 0 ? req.testCommandOverrideOrigin === "founder" ? "founder-declared" : req.testCommandOverrideOrigin === "operator" ? "operator-declared" : "developer-declared" : derived.testCommand === null ? "none" : "detected",
|
|
39628
40128
|
boundaryRefusals: [],
|
|
39629
40129
|
touchedPaths: pre.touchedPaths,
|
|
39630
40130
|
preview: null,
|
|
@@ -39634,7 +40134,14 @@ async function runVerification(req, ctx) {
|
|
|
39634
40134
|
// that measures one; a run without it is recordable but not attestable —
|
|
39635
40135
|
// `toAcceptancePredicate` refuses `missing-image-digest` (TERM-893).
|
|
39636
40136
|
containerImageDigest: null,
|
|
40137
|
+
// The image half of the provenance pair above. `detected` means the runtime mapping
|
|
40138
|
+
// chose the environment; an override names the human. Defaulting an unstated origin to
|
|
40139
|
+
// `developer-declared` is deliberate and matches `testCommandSource`: `th run --image`
|
|
40140
|
+
// runs on the developer's machine, judging the developer's work, so attributing it to
|
|
40141
|
+
// the operator would sign our name onto their choice.
|
|
40142
|
+
imageSource: req.image === void 0 ? "detected" : req.imageOrigin === "operator" ? "operator-declared" : "developer-declared",
|
|
39637
40143
|
leaksClean: verdict.leaks.clean,
|
|
40144
|
+
leakState: verdict.leaks.state,
|
|
39638
40145
|
// Built from the LEASE, over the client that ran the steps — never from
|
|
39639
40146
|
// `req.placement`, which is a request. `venueDescriptor.ts` carries the
|
|
39640
40147
|
// reasoning and the #735 failure that makes the distinction load-bearing.
|
|
@@ -39692,6 +40199,7 @@ var init_thrun = __esm({
|
|
|
39692
40199
|
init_execute();
|
|
39693
40200
|
init_placement();
|
|
39694
40201
|
init_venue();
|
|
40202
|
+
init_gradleTestSummary();
|
|
39695
40203
|
init_venueDescriptor();
|
|
39696
40204
|
init_result();
|
|
39697
40205
|
ThRunError = class extends Error {
|
|
@@ -39935,7 +40443,7 @@ var init_dbplan = __esm({
|
|
|
39935
40443
|
// ../../packages/envrun/dist/dbstack.js
|
|
39936
40444
|
import { spawnSync as spawnSync8 } from "child_process";
|
|
39937
40445
|
import { randomBytes as randomBytes12 } from "crypto";
|
|
39938
|
-
import { mkdirSync as
|
|
40446
|
+
import { mkdirSync as mkdirSync9 } from "fs";
|
|
39939
40447
|
function installCommandFor(runner) {
|
|
39940
40448
|
switch (runner) {
|
|
39941
40449
|
case "sql":
|
|
@@ -40166,7 +40674,7 @@ function startDatabase(req) {
|
|
|
40166
40674
|
if (!ready.ok) {
|
|
40167
40675
|
throw new DbStackError(`INFRASTRUCTURE/INCONCLUSIVE: Postgres never accepted queries at 127.0.0.1:${String(creds.port)} within the readiness window: ${ready.detail}`);
|
|
40168
40676
|
}
|
|
40169
|
-
const
|
|
40677
|
+
const query2 = (sql) => {
|
|
40170
40678
|
const res = docker2([
|
|
40171
40679
|
"exec",
|
|
40172
40680
|
`--env=PGPASSWORD=${creds.password}`,
|
|
@@ -40214,7 +40722,7 @@ function startDatabase(req) {
|
|
|
40214
40722
|
credentials: creds,
|
|
40215
40723
|
image,
|
|
40216
40724
|
readyMs: ready.ms,
|
|
40217
|
-
query,
|
|
40725
|
+
query: query2,
|
|
40218
40726
|
runOnNetwork,
|
|
40219
40727
|
teardown
|
|
40220
40728
|
};
|
|
@@ -40277,8 +40785,8 @@ async function installLocalMigrationTooling(opts) {
|
|
|
40277
40785
|
};
|
|
40278
40786
|
}
|
|
40279
40787
|
const { jail, tmp } = buildJail(opts.scratchRoot);
|
|
40280
|
-
|
|
40281
|
-
|
|
40788
|
+
mkdirSync9(jail, { recursive: true });
|
|
40789
|
+
mkdirSync9(tmp, { recursive: true });
|
|
40282
40790
|
const spec = {
|
|
40283
40791
|
profile: "install",
|
|
40284
40792
|
clone: opts.repoDir,
|
|
@@ -40573,6 +41081,7 @@ __export(dist_exports, {
|
|
|
40573
41081
|
GOOGLE_JWKS_URL: () => GOOGLE_JWKS_URL,
|
|
40574
41082
|
HostedVenueError: () => HostedVenueError,
|
|
40575
41083
|
JWKS_FETCH_TIMEOUT_MS: () => JWKS_FETCH_TIMEOUT_MS,
|
|
41084
|
+
LEAK_STATES: () => LEAK_STATES,
|
|
40576
41085
|
LOCAL_MEASUREMENT_PREFIX: () => LOCAL_MEASUREMENT_PREFIX,
|
|
40577
41086
|
LabelWatch: () => LabelWatch,
|
|
40578
41087
|
MIN_GIT_VERSION_FOR_END_OF_OPTIONS: () => MIN_GIT_VERSION_FOR_END_OF_OPTIONS,
|
|
@@ -40589,6 +41098,7 @@ __export(dist_exports, {
|
|
|
40589
41098
|
REDACTED_TARGET_SHA: () => REDACTED_TARGET_SHA,
|
|
40590
41099
|
RELEASED_LEASE_CENSUS_REASON: () => RELEASED_LEASE_CENSUS_REASON,
|
|
40591
41100
|
REPO_DIGEST_RE: () => REPO_DIGEST_RE,
|
|
41101
|
+
RUN_IMAGE_SOURCES: () => RUN_IMAGE_SOURCES,
|
|
40592
41102
|
RUN_LABEL_KEY: () => RUN_LABEL_KEY,
|
|
40593
41103
|
RUN_RESULT_FIELDS: () => RUN_RESULT_FIELDS,
|
|
40594
41104
|
RUN_RESULT_SCHEMA: () => RUN_RESULT_SCHEMA,
|
|
@@ -40605,6 +41115,7 @@ __export(dist_exports, {
|
|
|
40605
41115
|
VENUE_GCLOUD_CONFIG: () => VENUE_GCLOUD_CONFIG,
|
|
40606
41116
|
VENUE_SSH_USER: () => VENUE_SSH_USER,
|
|
40607
41117
|
VENV_DIR: () => VENV_DIR,
|
|
41118
|
+
VERIFICATION_OUTCOMES: () => VERIFICATION_OUTCOMES,
|
|
40608
41119
|
VenueRollbackError: () => VenueRollbackError,
|
|
40609
41120
|
acquireTransactionally: () => acquireTransactionally,
|
|
40610
41121
|
alembicChainPosition: () => alembicChainPosition,
|
|
@@ -40618,6 +41129,7 @@ __export(dist_exports, {
|
|
|
40618
41129
|
assertVenueOwnerDeclared: () => assertVenueOwnerDeclared,
|
|
40619
41130
|
bookkeepingFor: () => bookkeepingFor,
|
|
40620
41131
|
census: () => census,
|
|
41132
|
+
censusReport: () => censusReport,
|
|
40621
41133
|
censusTotal: () => censusTotal,
|
|
40622
41134
|
classifyBootFailure: () => classifyBootFailure,
|
|
40623
41135
|
classifyProbeFailure: () => classifyProbeFailure,
|
|
@@ -40637,6 +41149,7 @@ __export(dist_exports, {
|
|
|
40637
41149
|
detectRunner: () => detectRunner,
|
|
40638
41150
|
endOfOptionsUnsupported: () => endOfOptionsUnsupported,
|
|
40639
41151
|
ensureVenueServiceCredentials: () => ensureVenueServiceCredentials,
|
|
41152
|
+
exitCodeFor: () => exitCodeFor,
|
|
40640
41153
|
failureSourceOf: () => failureSourceOf,
|
|
40641
41154
|
findRunRefusal: () => findRunRefusal,
|
|
40642
41155
|
gcpBootArgv: () => gcpBootArgv,
|
|
@@ -40651,6 +41164,7 @@ __export(dist_exports, {
|
|
|
40651
41164
|
identityProbeCommand: () => identityProbeCommand,
|
|
40652
41165
|
imageForRuntime: () => imageForRuntime,
|
|
40653
41166
|
imageRepo: () => imageRepo,
|
|
41167
|
+
imageVariantFor: () => imageVariantFor,
|
|
40654
41168
|
installCommandFor: () => installCommandFor,
|
|
40655
41169
|
installLocalMigrationTooling: () => installLocalMigrationTooling,
|
|
40656
41170
|
isBookkeepingTable: () => isBookkeepingTable,
|
|
@@ -40680,6 +41194,7 @@ __export(dist_exports, {
|
|
|
40680
41194
|
readSchema: () => readSchema,
|
|
40681
41195
|
recordedApplied: () => recordedApplied,
|
|
40682
41196
|
refuseSshTransport: () => refuseSshTransport,
|
|
41197
|
+
refuseUnbuildableSpec: () => refuseUnbuildableSpec,
|
|
40683
41198
|
renderRunReport: () => renderRunReport,
|
|
40684
41199
|
renderVenueLine: () => renderVenueLine,
|
|
40685
41200
|
renderVerdictLine: () => renderVerdictLine,
|
|
@@ -41061,8 +41576,8 @@ __export(jpi_claim_exports, {
|
|
|
41061
41576
|
});
|
|
41062
41577
|
import {
|
|
41063
41578
|
readFileSync as readFileSync27,
|
|
41064
|
-
writeFileSync as
|
|
41065
|
-
mkdirSync as
|
|
41579
|
+
writeFileSync as writeFileSync24,
|
|
41580
|
+
mkdirSync as mkdirSync10,
|
|
41066
41581
|
mkdtempSync as mkdtempSync5,
|
|
41067
41582
|
renameSync as renameSync11,
|
|
41068
41583
|
existsSync as existsSync20,
|
|
@@ -41071,7 +41586,7 @@ import {
|
|
|
41071
41586
|
rmSync as rmSync12,
|
|
41072
41587
|
readdirSync as readdirSync3
|
|
41073
41588
|
} from "fs";
|
|
41074
|
-
import { join as
|
|
41589
|
+
import { join as join44, dirname as dirname10, isAbsolute as isAbsolute5, resolve as pathResolve } from "path";
|
|
41075
41590
|
import { createHash as createHash11 } from "crypto";
|
|
41076
41591
|
import { homedir as homedir26, hostname as osHostname } from "os";
|
|
41077
41592
|
import { execFile as execFile3, execFileSync as execFileSync2, spawnSync as spawnSync9 } from "child_process";
|
|
@@ -41090,7 +41605,7 @@ function markClaimNudged(id) {
|
|
|
41090
41605
|
const ids2 = readNudgedClaimIds();
|
|
41091
41606
|
ids2.add(id);
|
|
41092
41607
|
ensureStateDir(TERMINALHIRE_DIR17);
|
|
41093
|
-
|
|
41608
|
+
writeFileSync24(REPO_CONTINUITY_NUDGE_MARKER, JSON.stringify({ claimIds: [...ids2] }), "utf8");
|
|
41094
41609
|
} catch {
|
|
41095
41610
|
}
|
|
41096
41611
|
}
|
|
@@ -43355,7 +43870,7 @@ async function cmdAttach(id, worktree, branch) {
|
|
|
43355
43870
|
function workDirFor(repoFullName, issueNumber) {
|
|
43356
43871
|
const [owner, repo] = String(repoFullName).split("/");
|
|
43357
43872
|
const suffix = issueNumber ? `-${issueNumber}` : "";
|
|
43358
|
-
return
|
|
43873
|
+
return join44(homedir26(), "terminalhire", "work", `${owner}-${repo}${suffix}`);
|
|
43359
43874
|
}
|
|
43360
43875
|
function startBranchFor(repoFullName, issueNumber) {
|
|
43361
43876
|
const repo = String(repoFullName).split("/")[1] || "claim";
|
|
@@ -43611,7 +44126,7 @@ terminalhire claim: not started \u2014 starting forks ${claim.repoFullName} to y
|
|
|
43611
44126
|
);
|
|
43612
44127
|
process.exit(1);
|
|
43613
44128
|
}
|
|
43614
|
-
|
|
44129
|
+
mkdirSync10(join44(homedir26(), "terminalhire", "work"), { recursive: true });
|
|
43615
44130
|
const { createProgress: createProgress2, parseGitProgress: parseGitProgress2, splitProgressChunk: splitProgressChunk2, shStream: shStream2 } = await Promise.resolve().then(() => (init_progress(), progress_exports));
|
|
43616
44131
|
const progress = createProgress2();
|
|
43617
44132
|
let forkFullName;
|
|
@@ -43737,7 +44252,7 @@ function founderPostingIdOf(claim) {
|
|
|
43737
44252
|
}
|
|
43738
44253
|
function sliceWorkDirFor(claimLocalId) {
|
|
43739
44254
|
const safe = String(claimLocalId).replace(/[^A-Za-z0-9._-]/g, "-");
|
|
43740
|
-
return
|
|
44255
|
+
return join44(homedir26(), "terminalhire", "work", `slice-${safe}`);
|
|
43741
44256
|
}
|
|
43742
44257
|
function assertNoBooleanPath(dest, flagName) {
|
|
43743
44258
|
const last = String(dest).split(/[\\/]/).filter(Boolean).pop();
|
|
@@ -43854,9 +44369,9 @@ function writeSliceFiles(destDir, files) {
|
|
|
43854
44369
|
const unavailable = [];
|
|
43855
44370
|
for (const f of files) {
|
|
43856
44371
|
if (typeof f.content === "string") {
|
|
43857
|
-
const abs =
|
|
43858
|
-
|
|
43859
|
-
|
|
44372
|
+
const abs = join44(destDir, f.path);
|
|
44373
|
+
mkdirSync10(dirname10(abs), { recursive: true });
|
|
44374
|
+
writeFileSync24(abs, f.content, "utf8");
|
|
43860
44375
|
written.push(f.path);
|
|
43861
44376
|
} else {
|
|
43862
44377
|
unavailable.push({ path: f.path, reason: f.unavailableReason || "(no reason given)" });
|
|
@@ -43885,7 +44400,7 @@ function writeDeliveredBrief(destDir, spec) {
|
|
|
43885
44400
|
function ensureExcludedPackDir(destDir) {
|
|
43886
44401
|
let occupant = null;
|
|
43887
44402
|
try {
|
|
43888
|
-
occupant = lstatSync4(
|
|
44403
|
+
occupant = lstatSync4(join44(destDir, BRIEF_DIR));
|
|
43889
44404
|
} catch (err) {
|
|
43890
44405
|
if (err?.code !== "ENOENT") {
|
|
43891
44406
|
return {
|
|
@@ -43900,12 +44415,12 @@ function ensureExcludedPackDir(destDir) {
|
|
|
43900
44415
|
reason: `${BRIEF_DIR}/ already exists in the delivered tree, and excluding it would hide that content from your patch`
|
|
43901
44416
|
};
|
|
43902
44417
|
}
|
|
43903
|
-
const excludeFile =
|
|
44418
|
+
const excludeFile = join44(destDir, ".git", "info", "exclude");
|
|
43904
44419
|
try {
|
|
43905
44420
|
const existing = existsSync20(excludeFile) ? readFileSync27(excludeFile, "utf8") : "";
|
|
43906
44421
|
if (!existing.split("\n").includes(BRIEF_EXCLUDE_LINE)) {
|
|
43907
|
-
|
|
43908
|
-
|
|
44422
|
+
mkdirSync10(dirname10(excludeFile), { recursive: true });
|
|
44423
|
+
writeFileSync24(
|
|
43909
44424
|
excludeFile,
|
|
43910
44425
|
`${existing}${existing === "" || existing.endsWith("\n") ? "" : "\n"}${BRIEF_EXCLUDE_LINE}
|
|
43911
44426
|
`,
|
|
@@ -43919,9 +44434,9 @@ function ensureExcludedPackDir(destDir) {
|
|
|
43919
44434
|
}
|
|
43920
44435
|
function writePackFile(destDir, relPath, content, what) {
|
|
43921
44436
|
try {
|
|
43922
|
-
const abs =
|
|
43923
|
-
|
|
43924
|
-
|
|
44437
|
+
const abs = join44(destDir, relPath);
|
|
44438
|
+
mkdirSync10(dirname10(abs), { recursive: true });
|
|
44439
|
+
writeFileSync24(abs, content, { encoding: "utf8", flag: "wx" });
|
|
43925
44440
|
} catch (err) {
|
|
43926
44441
|
return { written: false, reason: `the ${what} could not be written (${err.message})` };
|
|
43927
44442
|
}
|
|
@@ -44322,7 +44837,7 @@ async function cmdSliceFullTier(claims, id, local, fullTierBody, flags, cloneRep
|
|
|
44322
44837
|
if (resolvedDir.suffixed) {
|
|
44323
44838
|
console.log(`terminalhire claim: the usual directory has content \u2014 using ${dest}`);
|
|
44324
44839
|
}
|
|
44325
|
-
|
|
44840
|
+
mkdirSync10(dest, { recursive: true });
|
|
44326
44841
|
const branch = `claim/${String(claim.id).replace(/[^A-Za-z0-9._-]/g, "-")}`;
|
|
44327
44842
|
let engine;
|
|
44328
44843
|
try {
|
|
@@ -44504,7 +45019,7 @@ async function attemptSliceDelivery(id, flags = {}) {
|
|
|
44504
45019
|
if (resolvedDir.suffixed) {
|
|
44505
45020
|
console.log(`terminalhire claim: the usual directory has content \u2014 using ${finalDest}`);
|
|
44506
45021
|
}
|
|
44507
|
-
|
|
45022
|
+
mkdirSync10(dirname10(finalDest), { recursive: true });
|
|
44508
45023
|
let dest = mkdtempSync5(`${finalDest}.tmp-`);
|
|
44509
45024
|
const { written, unavailable } = writeSliceFiles(dest, body.files);
|
|
44510
45025
|
const branch = `claim/${String(claim.id).replace(/[^A-Za-z0-9._-]/g, "-")}`;
|
|
@@ -45045,7 +45560,7 @@ async function cmdSubmit(id, flags = {}) {
|
|
|
45045
45560
|
const head = `${ghUser}:${claim.branch}`;
|
|
45046
45561
|
const title = flags.title || claim.title;
|
|
45047
45562
|
const noBody = Boolean(flags["no-body"]);
|
|
45048
|
-
const prBodyPath =
|
|
45563
|
+
const prBodyPath = join44(wt, "PR-BODY.md");
|
|
45049
45564
|
const bodySource = pickBodySource({
|
|
45050
45565
|
bodyFileFlag: flags["body-file"],
|
|
45051
45566
|
noBody,
|
|
@@ -45285,7 +45800,7 @@ function readClaimPushMarker() {
|
|
|
45285
45800
|
}
|
|
45286
45801
|
function writeClaimPushMarker(marker) {
|
|
45287
45802
|
ensureStateDir(TERMINALHIRE_DIR17);
|
|
45288
|
-
|
|
45803
|
+
writeFileSync24(CLAIM_PUSH_MARKER, JSON.stringify(marker, null, 2) + "\n", "utf8");
|
|
45289
45804
|
}
|
|
45290
45805
|
function clearClaimPushMarker() {
|
|
45291
45806
|
try {
|
|
@@ -46199,10 +46714,10 @@ var init_jpi_claim = __esm({
|
|
|
46199
46714
|
init_claim_push_bg();
|
|
46200
46715
|
init_founder_verdict_sync();
|
|
46201
46716
|
init_founder_note_sync();
|
|
46202
|
-
TERMINALHIRE_DIR17 = process.env.TERMINALHIRE_DIR ||
|
|
46203
|
-
INDEX_CACHE_FILE5 =
|
|
46204
|
-
CLAIM_PUSH_MARKER =
|
|
46205
|
-
REPO_CONTINUITY_NUDGE_MARKER =
|
|
46717
|
+
TERMINALHIRE_DIR17 = process.env.TERMINALHIRE_DIR || join44(homedir26(), ".terminalhire");
|
|
46718
|
+
INDEX_CACHE_FILE5 = join44(TERMINALHIRE_DIR17, "index-cache.json");
|
|
46719
|
+
CLAIM_PUSH_MARKER = join44(TERMINALHIRE_DIR17, "claim-push.json");
|
|
46720
|
+
REPO_CONTINUITY_NUDGE_MARKER = join44(TERMINALHIRE_DIR17, "repo-continuity-nudged.json");
|
|
46206
46721
|
API_URL6 = resolveApiBase();
|
|
46207
46722
|
CLAIM_SYNC_BASE4 = API_URL6;
|
|
46208
46723
|
CLAIM_CONSENT_VERSION = 1;
|
|
@@ -46472,16 +46987,16 @@ import {
|
|
|
46472
46987
|
readFileSync as readFileSync28,
|
|
46473
46988
|
renameSync as renameSync12,
|
|
46474
46989
|
rmSync as rmSync13,
|
|
46475
|
-
writeFileSync as
|
|
46990
|
+
writeFileSync as writeFileSync25
|
|
46476
46991
|
} from "fs";
|
|
46477
46992
|
import { homedir as homedir27 } from "os";
|
|
46478
|
-
import { join as
|
|
46993
|
+
import { join as join45 } from "path";
|
|
46479
46994
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
46480
46995
|
function stateDir3() {
|
|
46481
|
-
return process.env["TERMINALHIRE_DIR"] ||
|
|
46996
|
+
return process.env["TERMINALHIRE_DIR"] || join45(homedir27(), ".terminalhire");
|
|
46482
46997
|
}
|
|
46483
46998
|
function postingDraftFilePath() {
|
|
46484
|
-
return
|
|
46999
|
+
return join45(stateDir3(), "posting-drafts.json");
|
|
46485
47000
|
}
|
|
46486
47001
|
function blankFile2() {
|
|
46487
47002
|
return { version: 1, drafts: [] };
|
|
@@ -46508,7 +47023,7 @@ function writeFile(file) {
|
|
|
46508
47023
|
const path6 = postingDraftFilePath();
|
|
46509
47024
|
const tmp = `${path6}.${process.pid}.${randomUUID4()}.tmp`;
|
|
46510
47025
|
try {
|
|
46511
|
-
|
|
47026
|
+
writeFileSync25(tmp, `${JSON.stringify(file, null, 2)}
|
|
46512
47027
|
`, {
|
|
46513
47028
|
encoding: "utf8",
|
|
46514
47029
|
mode: 384,
|
|
@@ -46791,7 +47306,7 @@ __export(jpi_post_exports, {
|
|
|
46791
47306
|
import { existsSync as existsSync22, readFileSync as readFileSync29 } from "fs";
|
|
46792
47307
|
import { spawnSync as spawnSync10 } from "child_process";
|
|
46793
47308
|
import { createInterface as createInterface10 } from "readline";
|
|
46794
|
-
import { basename as basename6, join as
|
|
47309
|
+
import { basename as basename6, join as join46 } from "path";
|
|
46795
47310
|
function parsePostArgs(argv) {
|
|
46796
47311
|
const flags = {};
|
|
46797
47312
|
const positional = [];
|
|
@@ -46833,15 +47348,15 @@ function ownerRepo(remote) {
|
|
|
46833
47348
|
}
|
|
46834
47349
|
function detectStack(cwd) {
|
|
46835
47350
|
const stack = [];
|
|
46836
|
-
if (existsSync22(
|
|
46837
|
-
if (existsSync22(
|
|
47351
|
+
if (existsSync22(join46(cwd, "package.json"))) stack.push("node");
|
|
47352
|
+
if (existsSync22(join46(cwd, "next.config.js")) || existsSync22(join46(cwd, "next.config.mjs"))) {
|
|
46838
47353
|
stack.push("next.js");
|
|
46839
47354
|
}
|
|
46840
|
-
if (existsSync22(
|
|
47355
|
+
if (existsSync22(join46(cwd, "pyproject.toml")) || existsSync22(join46(cwd, "requirements.txt"))) {
|
|
46841
47356
|
stack.push("python");
|
|
46842
47357
|
}
|
|
46843
|
-
if (existsSync22(
|
|
46844
|
-
if (existsSync22(
|
|
47358
|
+
if (existsSync22(join46(cwd, "Cargo.toml"))) stack.push("rust");
|
|
47359
|
+
if (existsSync22(join46(cwd, "go.mod"))) stack.push("go");
|
|
46845
47360
|
return stack;
|
|
46846
47361
|
}
|
|
46847
47362
|
function captureRepository(cwd = process.cwd()) {
|
|
@@ -47261,25 +47776,25 @@ var init_jpi_repo = __esm({
|
|
|
47261
47776
|
import {
|
|
47262
47777
|
closeSync as closeSync5,
|
|
47263
47778
|
existsSync as existsSync23,
|
|
47264
|
-
mkdirSync as
|
|
47779
|
+
mkdirSync as mkdirSync11,
|
|
47265
47780
|
openSync as openSync5,
|
|
47266
47781
|
readFileSync as readFileSync30,
|
|
47267
47782
|
readdirSync as readdirSync4,
|
|
47268
47783
|
renameSync as renameSync13,
|
|
47269
47784
|
statSync as statSync5,
|
|
47270
47785
|
unlinkSync as unlinkSync4,
|
|
47271
|
-
writeFileSync as
|
|
47786
|
+
writeFileSync as writeFileSync26
|
|
47272
47787
|
} from "fs";
|
|
47273
47788
|
import { homedir as homedir28 } from "os";
|
|
47274
|
-
import { basename as basename7, dirname as dirname11, join as
|
|
47789
|
+
import { basename as basename7, dirname as dirname11, join as join47 } from "path";
|
|
47275
47790
|
function defaultUrl() {
|
|
47276
47791
|
return process.env["TERMINALHIRE_RECALL_URL"] || RECALL_URL;
|
|
47277
47792
|
}
|
|
47278
47793
|
function stateDir4() {
|
|
47279
|
-
return process.env["TERMINALHIRE_DIR"] ||
|
|
47794
|
+
return process.env["TERMINALHIRE_DIR"] || join47(homedir28(), ".terminalhire");
|
|
47280
47795
|
}
|
|
47281
47796
|
function recallCachePath() {
|
|
47282
|
-
return
|
|
47797
|
+
return join47(stateDir4(), "recall.json");
|
|
47283
47798
|
}
|
|
47284
47799
|
async function fetchRecalls(url = defaultUrl()) {
|
|
47285
47800
|
try {
|
|
@@ -47307,7 +47822,7 @@ function mutateCache(path6, mutate) {
|
|
|
47307
47822
|
const lock = `${path6}.lock`;
|
|
47308
47823
|
let held = false;
|
|
47309
47824
|
try {
|
|
47310
|
-
|
|
47825
|
+
mkdirSync11(dirname11(path6), { recursive: true, mode: 448 });
|
|
47311
47826
|
const deadline = Date.now() + LOCK_WAIT_MS;
|
|
47312
47827
|
while (!held && Date.now() < deadline) {
|
|
47313
47828
|
try {
|
|
@@ -47331,7 +47846,7 @@ function mutateCache(path6, mutate) {
|
|
|
47331
47846
|
if (mutate(existing) === false) return false;
|
|
47332
47847
|
const tmp = `${path6}.${process.pid}.${tmpCounter3 += 1}.tmp`;
|
|
47333
47848
|
try {
|
|
47334
|
-
|
|
47849
|
+
writeFileSync26(tmp, `${JSON.stringify(existing, null, 2)}
|
|
47335
47850
|
`, { mode: 384 });
|
|
47336
47851
|
renameSync13(tmp, path6);
|
|
47337
47852
|
} catch {
|
|
@@ -47359,7 +47874,7 @@ function sweepTempFiles(path6) {
|
|
|
47359
47874
|
const prefix = `${basename7(path6)}.`;
|
|
47360
47875
|
for (const name of readdirSync4(dir)) {
|
|
47361
47876
|
if (!name.startsWith(prefix) || !name.endsWith(".tmp")) continue;
|
|
47362
|
-
const full =
|
|
47877
|
+
const full = join47(dir, name);
|
|
47363
47878
|
try {
|
|
47364
47879
|
if (Date.now() - statSync5(full).mtimeMs > 6e4) unlinkSync4(full);
|
|
47365
47880
|
} catch {
|
|
@@ -47464,7 +47979,7 @@ __export(jpi_run_exports, {
|
|
|
47464
47979
|
});
|
|
47465
47980
|
import { existsSync as existsSync24, readFileSync as readFileSync31, realpathSync as realpathSync4 } from "fs";
|
|
47466
47981
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
47467
|
-
import { join as
|
|
47982
|
+
import { join as join48, resolve as resolve5 } from "path";
|
|
47468
47983
|
import { tmpdir as tmpdir5 } from "os";
|
|
47469
47984
|
import { mkdtempSync as mkdtempSync6, rmSync as rmSync14 } from "fs";
|
|
47470
47985
|
function parseArgs2(argv) {
|
|
@@ -47489,7 +48004,7 @@ function parseArgs2(argv) {
|
|
|
47489
48004
|
function runScratchRoot() {
|
|
47490
48005
|
let root;
|
|
47491
48006
|
try {
|
|
47492
|
-
root = mkdtempSync6(
|
|
48007
|
+
root = mkdtempSync6(join48(tmpdir5(), "th-run-"));
|
|
47493
48008
|
} catch (err) {
|
|
47494
48009
|
process.stderr.write(
|
|
47495
48010
|
`terminalhire: could not create the temporary directory this run works in, so nothing was cloned and nothing was executed. That is our environment failing, not your tests: check that the temp directory is writable. (${String(err?.message ?? err)})
|
|
@@ -47526,7 +48041,7 @@ async function loadEngine() {
|
|
|
47526
48041
|
}
|
|
47527
48042
|
}
|
|
47528
48043
|
function readConfig2(localDir) {
|
|
47529
|
-
const file =
|
|
48044
|
+
const file = join48(localDir, ".th-run.json");
|
|
47530
48045
|
if (!existsSync24(file)) return {};
|
|
47531
48046
|
try {
|
|
47532
48047
|
const parsed = JSON.parse(readFileSync31(file, "utf8"));
|
|
@@ -47632,6 +48147,11 @@ async function once(engine, opts) {
|
|
|
47632
48147
|
preview: opts.preview,
|
|
47633
48148
|
...opts.placement ? { placement: opts.placement } : {},
|
|
47634
48149
|
...opts.testCommand ? { testCommandOverride: opts.testCommand } : {},
|
|
48150
|
+
// No `imageOrigin` beside it, deliberately. This flag runs on the DEVELOPER's machine,
|
|
48151
|
+
// judging the developer's work, so it takes `thrun`'s default of `developer` — the same
|
|
48152
|
+
// reasoning that makes `--test-command` developer-declared. An operator override is a
|
|
48153
|
+
// server-side caller, not this flag.
|
|
48154
|
+
...opts.image ? { image: opts.image } : {},
|
|
47635
48155
|
onProgress: (stage, detail) => {
|
|
47636
48156
|
if (!opts.json) process.stderr.write(` ${stage.padEnd(8)} ${detail}
|
|
47637
48157
|
`);
|
|
@@ -47677,8 +48197,7 @@ Expiry and revocation are not built yet (TERM-350 phase 5); Ctrl-C is the only s
|
|
|
47677
48197
|
process.stderr.write(` total ${String(Date.now() - started)}ms
|
|
47678
48198
|
`);
|
|
47679
48199
|
}
|
|
47680
|
-
|
|
47681
|
-
return result.outcome === "completed" ? 0 : 1;
|
|
48200
|
+
return engine.exitCodeFor(result);
|
|
47682
48201
|
}
|
|
47683
48202
|
async function run10() {
|
|
47684
48203
|
const argv = process.argv.slice(2);
|
|
@@ -47745,6 +48264,7 @@ async function run10() {
|
|
|
47745
48264
|
watch: parsed.bools.has("watch"),
|
|
47746
48265
|
json: parsed.bools.has("json"),
|
|
47747
48266
|
testCommand: pick2("test-command") ?? null,
|
|
48267
|
+
image: pick2("image") ?? null,
|
|
47748
48268
|
keepSeconds,
|
|
47749
48269
|
scratch: runScratchRoot()
|
|
47750
48270
|
};
|
|
@@ -47823,6 +48343,9 @@ Options:
|
|
|
47823
48343
|
--keep <seconds> Hold the preview open this long, at most ${String(KEEP_MAX_SECONDS)}
|
|
47824
48344
|
(default: until Ctrl-C).
|
|
47825
48345
|
--test-command <cmd> Disclosed override of the derived test command.
|
|
48346
|
+
--image <ref> Disclosed override of the container image. Use when no image is
|
|
48347
|
+
mapped for the repo's runtime. Recorded as developer-declared
|
|
48348
|
+
provenance, which the attestation refuses to sign.
|
|
47826
48349
|
--help
|
|
47827
48350
|
|
|
47828
48351
|
Defaults are read from .th-run.json in the local checkout when present, so a
|
|
@@ -48130,7 +48653,7 @@ function finalize(build) {
|
|
|
48130
48653
|
};
|
|
48131
48654
|
}
|
|
48132
48655
|
function reconstruct(files, opts = {}) {
|
|
48133
|
-
const
|
|
48656
|
+
const join63 = opts.joinSidechains !== false;
|
|
48134
48657
|
const mains = [];
|
|
48135
48658
|
const sidechains = [];
|
|
48136
48659
|
for (const file of files) {
|
|
@@ -48155,7 +48678,7 @@ function reconstruct(files, opts = {}) {
|
|
|
48155
48678
|
}
|
|
48156
48679
|
const orphanedSidechainPaths = [];
|
|
48157
48680
|
const joinedPaths = /* @__PURE__ */ new Set();
|
|
48158
|
-
if (
|
|
48681
|
+
if (join63) {
|
|
48159
48682
|
const sidechainsBySession = /* @__PURE__ */ new Map();
|
|
48160
48683
|
for (const sc of sidechains) {
|
|
48161
48684
|
const acc = sidechainsBySession.get(sc.sessionId) ?? [];
|
|
@@ -48491,9 +49014,9 @@ __export(trajectory_exports, {
|
|
|
48491
49014
|
runTrajectory: () => runTrajectory,
|
|
48492
49015
|
runTrajectoryPush: () => runTrajectoryPush
|
|
48493
49016
|
});
|
|
48494
|
-
import { existsSync as existsSync25, readFileSync as readFileSync32, readdirSync as readdirSync5, writeFileSync as
|
|
49017
|
+
import { existsSync as existsSync25, readFileSync as readFileSync32, readdirSync as readdirSync5, writeFileSync as writeFileSync27 } from "fs";
|
|
48495
49018
|
import { homedir as homedir29 } from "os";
|
|
48496
|
-
import { join as
|
|
49019
|
+
import { join as join49 } from "path";
|
|
48497
49020
|
function isRecord4(value) {
|
|
48498
49021
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
48499
49022
|
}
|
|
@@ -48525,7 +49048,7 @@ function findJsonlFiles(dir) {
|
|
|
48525
49048
|
return out;
|
|
48526
49049
|
}
|
|
48527
49050
|
for (const entry of entries) {
|
|
48528
|
-
const full =
|
|
49051
|
+
const full = join49(dir, entry.name);
|
|
48529
49052
|
if (entry.isDirectory()) {
|
|
48530
49053
|
out.push(...findJsonlFiles(full));
|
|
48531
49054
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
@@ -48646,12 +49169,12 @@ function renderMarkdown(view) {
|
|
|
48646
49169
|
return lines.join("\n");
|
|
48647
49170
|
}
|
|
48648
49171
|
function writeExportArtifacts(score, markdown) {
|
|
48649
|
-
const dir = process.env.TERMINALHIRE_DIR ||
|
|
49172
|
+
const dir = process.env.TERMINALHIRE_DIR || join49(homedir29(), ".terminalhire");
|
|
48650
49173
|
ensureStateDir(dir);
|
|
48651
|
-
const jsonPath =
|
|
48652
|
-
const mdPath =
|
|
48653
|
-
|
|
48654
|
-
|
|
49174
|
+
const jsonPath = join49(dir, "trajectory-export.json");
|
|
49175
|
+
const mdPath = join49(dir, "trajectory-export.md");
|
|
49176
|
+
writeFileSync27(jsonPath, JSON.stringify(score, null, 2) + "\n", "utf8");
|
|
49177
|
+
writeFileSync27(mdPath, markdown, "utf8");
|
|
48655
49178
|
return { jsonPath, mdPath };
|
|
48656
49179
|
}
|
|
48657
49180
|
function renderInward(allNodes, view, files) {
|
|
@@ -48670,7 +49193,7 @@ function renderInward(allNodes, view, files) {
|
|
|
48670
49193
|
console.log("");
|
|
48671
49194
|
}
|
|
48672
49195
|
function buildTrajectory() {
|
|
48673
|
-
const projectsDir =
|
|
49196
|
+
const projectsDir = join49(homedir29(), ".claude", "projects");
|
|
48674
49197
|
if (!existsSync25(projectsDir)) return null;
|
|
48675
49198
|
const paths = findJsonlFiles(projectsDir);
|
|
48676
49199
|
if (paths.length === 0) return null;
|
|
@@ -49484,10 +50007,10 @@ var init_jpi_intro = __esm({
|
|
|
49484
50007
|
});
|
|
49485
50008
|
|
|
49486
50009
|
// src/chat-keystore.ts
|
|
49487
|
-
import { existsSync as existsSync26, linkSync as linkSync2, readFileSync as readFileSync33, rmSync as rmSync15, unlinkSync as unlinkSync5, writeFileSync as
|
|
50010
|
+
import { existsSync as existsSync26, linkSync as linkSync2, readFileSync as readFileSync33, rmSync as rmSync15, unlinkSync as unlinkSync5, writeFileSync as writeFileSync28 } from "fs";
|
|
49488
50011
|
import { randomBytes as randomBytes13 } from "crypto";
|
|
49489
50012
|
import { homedir as homedir30 } from "os";
|
|
49490
|
-
import { join as
|
|
50013
|
+
import { join as join50 } from "path";
|
|
49491
50014
|
async function loadOrCreateIdentity() {
|
|
49492
50015
|
const key = await loadKey();
|
|
49493
50016
|
if (existsSync26(IDENTITY_FILE)) {
|
|
@@ -49531,7 +50054,7 @@ Recovery: if you intend to reset your chat identity, delete the file yourself an
|
|
|
49531
50054
|
function publishIdentityBlob(blob) {
|
|
49532
50055
|
const tmpFile = `${IDENTITY_FILE}.${process.pid}.${randomBytes13(6).toString("hex")}.tmp`;
|
|
49533
50056
|
try {
|
|
49534
|
-
|
|
50057
|
+
writeFileSync28(tmpFile, JSON.stringify(blob, null, 2), {
|
|
49535
50058
|
encoding: "utf8",
|
|
49536
50059
|
mode: 384,
|
|
49537
50060
|
flag: "wx"
|
|
@@ -49560,16 +50083,16 @@ var init_chat_keystore = __esm({
|
|
|
49560
50083
|
init_src();
|
|
49561
50084
|
init_github_auth();
|
|
49562
50085
|
init_state_dir();
|
|
49563
|
-
TERMINALHIRE_DIR18 = process.env.TERMINALHIRE_DIR ||
|
|
49564
|
-
IDENTITY_FILE =
|
|
50086
|
+
TERMINALHIRE_DIR18 = process.env.TERMINALHIRE_DIR || join50(homedir30(), ".terminalhire");
|
|
50087
|
+
IDENTITY_FILE = join50(TERMINALHIRE_DIR18, "chat-identity.enc");
|
|
49565
50088
|
HEX64_RE = /^[0-9a-f]{64}$/;
|
|
49566
50089
|
}
|
|
49567
50090
|
});
|
|
49568
50091
|
|
|
49569
50092
|
// src/chat-client.ts
|
|
49570
|
-
import { existsSync as existsSync27, readFileSync as readFileSync34, writeFileSync as
|
|
50093
|
+
import { existsSync as existsSync27, readFileSync as readFileSync34, writeFileSync as writeFileSync29 } from "fs";
|
|
49571
50094
|
import { homedir as homedir31 } from "os";
|
|
49572
|
-
import { join as
|
|
50095
|
+
import { join as join51 } from "path";
|
|
49573
50096
|
function defaultReadPeerPins() {
|
|
49574
50097
|
try {
|
|
49575
50098
|
if (!existsSync27(PEERS_FILE)) return {};
|
|
@@ -49586,7 +50109,7 @@ function defaultReadPeerPins() {
|
|
|
49586
50109
|
}
|
|
49587
50110
|
function defaultWritePeerPins(pins) {
|
|
49588
50111
|
ensureStateDir(TERMINALHIRE_DIR19);
|
|
49589
|
-
|
|
50112
|
+
writeFileSync29(PEERS_FILE, JSON.stringify(pins, null, 2), { mode: 384, encoding: "utf8" });
|
|
49590
50113
|
}
|
|
49591
50114
|
function defaultChatClientDeps() {
|
|
49592
50115
|
return {
|
|
@@ -49778,8 +50301,8 @@ var init_chat_client = __esm({
|
|
|
49778
50301
|
init_api_base();
|
|
49779
50302
|
CHAT_BASE = resolveApiBase();
|
|
49780
50303
|
GH_SESSION_COOKIE7 = "__jpi_gh_session";
|
|
49781
|
-
TERMINALHIRE_DIR19 = process.env.TERMINALHIRE_DIR ||
|
|
49782
|
-
PEERS_FILE =
|
|
50304
|
+
TERMINALHIRE_DIR19 = process.env.TERMINALHIRE_DIR || join51(homedir31(), ".terminalhire");
|
|
50305
|
+
PEERS_FILE = join51(TERMINALHIRE_DIR19, "chat-peers.json");
|
|
49783
50306
|
REQUEST_TIMEOUT_MS2 = 1e4;
|
|
49784
50307
|
ChatNotLinkedError = class extends Error {
|
|
49785
50308
|
constructor(message = missingSessionLines(null).join(" ")) {
|
|
@@ -50215,9 +50738,9 @@ __export(jpi_chat_read_exports, {
|
|
|
50215
50738
|
syncUnreadBadge: () => syncUnreadBadge,
|
|
50216
50739
|
writeReadCursor: () => writeReadCursor
|
|
50217
50740
|
});
|
|
50218
|
-
import { existsSync as existsSync28, readFileSync as readFileSync35, writeFileSync as
|
|
50741
|
+
import { existsSync as existsSync28, readFileSync as readFileSync35, writeFileSync as writeFileSync30 } from "fs";
|
|
50219
50742
|
import { homedir as homedir32 } from "os";
|
|
50220
|
-
import { join as
|
|
50743
|
+
import { join as join52 } from "path";
|
|
50221
50744
|
async function syncUnreadBadge(deps = {}) {
|
|
50222
50745
|
const readCookie = deps.readCookie ?? readWebSessionCookie;
|
|
50223
50746
|
const fetchImpl = deps.fetchImpl ?? globalThis.fetch;
|
|
@@ -50239,7 +50762,7 @@ async function syncUnreadBadge(deps = {}) {
|
|
|
50239
50762
|
);
|
|
50240
50763
|
const entry = JSON.parse(readFileSync35(cacheFile, "utf8"));
|
|
50241
50764
|
entry.unreadChat = { count: total };
|
|
50242
|
-
|
|
50765
|
+
writeFileSync30(cacheFile, JSON.stringify(entry), "utf8");
|
|
50243
50766
|
} catch {
|
|
50244
50767
|
}
|
|
50245
50768
|
}
|
|
@@ -50264,7 +50787,7 @@ function writeReadCursor(login, iso, deps = {}) {
|
|
|
50264
50787
|
if (prev && iso <= prev) return;
|
|
50265
50788
|
cursors[login] = iso;
|
|
50266
50789
|
ensureStateDir(TERMINALHIRE_DIR20);
|
|
50267
|
-
|
|
50790
|
+
writeFileSync30(READS_FILE, JSON.stringify(cursors, null, 2), { mode: 384, encoding: "utf8" });
|
|
50268
50791
|
}
|
|
50269
50792
|
async function postReadCursor(peerLogin, lastReadAt, deps = {}) {
|
|
50270
50793
|
const readCookie = deps.readCookie ?? readWebSessionCookie;
|
|
@@ -50629,9 +51152,9 @@ var init_jpi_chat_read = __esm({
|
|
|
50629
51152
|
init_api_base();
|
|
50630
51153
|
CHAT_BASE2 = resolveApiBase();
|
|
50631
51154
|
GH_SESSION_COOKIE8 = "__jpi_gh_session";
|
|
50632
|
-
TERMINALHIRE_DIR20 = process.env.TERMINALHIRE_DIR ||
|
|
50633
|
-
READS_FILE =
|
|
50634
|
-
INDEX_CACHE_FILE6 =
|
|
51155
|
+
TERMINALHIRE_DIR20 = process.env.TERMINALHIRE_DIR || join52(homedir32(), ".terminalhire");
|
|
51156
|
+
READS_FILE = join52(TERMINALHIRE_DIR20, "chat-reads.json");
|
|
51157
|
+
INDEX_CACHE_FILE6 = join52(TERMINALHIRE_DIR20, "index-cache.json");
|
|
50635
51158
|
REACHABLE_DISPLAY = { shareActivity: false, optin: false, lastSeen: null };
|
|
50636
51159
|
}
|
|
50637
51160
|
});
|
|
@@ -51172,7 +51695,7 @@ __export(jpi_chat_exports, {
|
|
|
51172
51695
|
import { createInterface as createInterface11 } from "readline";
|
|
51173
51696
|
import { existsSync as existsSync29, readFileSync as readFileSync36 } from "fs";
|
|
51174
51697
|
import { homedir as homedir33 } from "os";
|
|
51175
|
-
import { join as
|
|
51698
|
+
import { join as join53 } from "path";
|
|
51176
51699
|
function defaultPromptAck({ input = process.stdin, output = process.stdout } = {}) {
|
|
51177
51700
|
if (!input || input.isTTY !== true) return Promise.resolve(false);
|
|
51178
51701
|
const rl = createInterface11({ input, output });
|
|
@@ -51356,8 +51879,8 @@ function mergeMessages(existing, incoming) {
|
|
|
51356
51879
|
}
|
|
51357
51880
|
function readCachedSessionCase() {
|
|
51358
51881
|
try {
|
|
51359
|
-
const p =
|
|
51360
|
-
process.env.TERMINALHIRE_DIR ||
|
|
51882
|
+
const p = join53(
|
|
51883
|
+
process.env.TERMINALHIRE_DIR || join53(homedir33(), ".terminalhire"),
|
|
51361
51884
|
"index-cache.json"
|
|
51362
51885
|
);
|
|
51363
51886
|
if (!existsSync29(p)) return null;
|
|
@@ -52124,8 +52647,8 @@ function sparkline(rows) {
|
|
|
52124
52647
|
const tail2 = sorted.slice(-24);
|
|
52125
52648
|
return tail2.map((c) => SPARK_LEVELS[STATE_LEVEL[c.state] ?? 1]).join("");
|
|
52126
52649
|
}
|
|
52127
|
-
function fuzzyMatch(
|
|
52128
|
-
const q =
|
|
52650
|
+
function fuzzyMatch(query2, candidate) {
|
|
52651
|
+
const q = query2.toLowerCase();
|
|
52129
52652
|
const c = candidate.toLowerCase();
|
|
52130
52653
|
if (q === "") return true;
|
|
52131
52654
|
let i = 0;
|
|
@@ -52134,9 +52657,9 @@ function fuzzyMatch(query, candidate) {
|
|
|
52134
52657
|
}
|
|
52135
52658
|
return i === q.length;
|
|
52136
52659
|
}
|
|
52137
|
-
function substrMatch(
|
|
52138
|
-
if (
|
|
52139
|
-
return candidate.toLowerCase().includes(
|
|
52660
|
+
function substrMatch(query2, candidate) {
|
|
52661
|
+
if (query2 === "") return true;
|
|
52662
|
+
return candidate.toLowerCase().includes(query2.toLowerCase());
|
|
52140
52663
|
}
|
|
52141
52664
|
function runHubTui({
|
|
52142
52665
|
input = process.stdin,
|
|
@@ -53173,15 +53696,15 @@ __export(mcp_config_exports, {
|
|
|
53173
53696
|
writeServerToFile: () => writeServerToFile
|
|
53174
53697
|
});
|
|
53175
53698
|
import { homedir as homedir34 } from "os";
|
|
53176
|
-
import { join as
|
|
53177
|
-
import { existsSync as existsSync30, readFileSync as readFileSync37, copyFileSync as copyFileSync3, writeFileSync as
|
|
53699
|
+
import { join as join54 } from "path";
|
|
53700
|
+
import { existsSync as existsSync30, readFileSync as readFileSync37, copyFileSync as copyFileSync3, writeFileSync as writeFileSync31, mkdirSync as mkdirSync12 } from "fs";
|
|
53178
53701
|
import { dirname as dirname12 } from "path";
|
|
53179
53702
|
function serverEntry() {
|
|
53180
53703
|
return { command: SERVER_COMMAND, args: [...SERVER_ARGS] };
|
|
53181
53704
|
}
|
|
53182
53705
|
function hostConfigPath(host, home = homedir34()) {
|
|
53183
53706
|
if (!host || !Array.isArray(host.relPath)) return null;
|
|
53184
|
-
return
|
|
53707
|
+
return join54(home, ...host.relPath);
|
|
53185
53708
|
}
|
|
53186
53709
|
function jsonSnippet(host) {
|
|
53187
53710
|
const entry = serverEntry();
|
|
@@ -53277,9 +53800,9 @@ function writeServerToFile(configPath, serversKey, entry = serverEntry()) {
|
|
|
53277
53800
|
backupPath = `${configPath}.terminalhire-backup-${ts}`;
|
|
53278
53801
|
copyFileSync3(configPath, backupPath);
|
|
53279
53802
|
} else {
|
|
53280
|
-
|
|
53803
|
+
mkdirSync12(dirname12(configPath), { recursive: true });
|
|
53281
53804
|
}
|
|
53282
|
-
|
|
53805
|
+
writeFileSync31(configPath, merged.text, "utf8");
|
|
53283
53806
|
return { status: "written", backupPath, added: merged.added };
|
|
53284
53807
|
}
|
|
53285
53808
|
async function initMcpStep({
|
|
@@ -65526,9 +66049,9 @@ var require_schemes = __commonJS({
|
|
|
65526
66049
|
wsComponent.secure = void 0;
|
|
65527
66050
|
}
|
|
65528
66051
|
if (wsComponent.resourceName) {
|
|
65529
|
-
const [path6,
|
|
66052
|
+
const [path6, query2] = wsComponent.resourceName.split("?");
|
|
65530
66053
|
wsComponent.path = path6 && path6 !== "/" ? path6 : void 0;
|
|
65531
|
-
wsComponent.query =
|
|
66054
|
+
wsComponent.query = query2;
|
|
65532
66055
|
wsComponent.resourceName = void 0;
|
|
65533
66056
|
}
|
|
65534
66057
|
wsComponent.fragment = void 0;
|
|
@@ -75835,7 +76358,7 @@ async function claimWorkspaceResult(args5 = {}) {
|
|
|
75835
76358
|
try {
|
|
75836
76359
|
const claims = await Promise.resolve().then(() => (init_claims(), claims_exports));
|
|
75837
76360
|
const { existsSync: existsSync37, readFileSync: readFileSync43, lstatSync: lstatSync5 } = await import("fs");
|
|
75838
|
-
const { join:
|
|
76361
|
+
const { join: join63 } = await import("path");
|
|
75839
76362
|
const { BRIEF_REL_PATH: BRIEF_REL_PATH2, VERIFY_REL_PATH: VERIFY_REL_PATH2, AGENTS_REL_PATH: AGENTS_REL_PATH2, sha256OfUtf8: sha256OfUtf82 } = await Promise.resolve().then(() => (init_jpi_claim(), jpi_claim_exports));
|
|
75840
76363
|
const packPaths = (c) => {
|
|
75841
76364
|
const p = {};
|
|
@@ -75848,7 +76371,7 @@ async function claimWorkspaceResult(args5 = {}) {
|
|
|
75848
76371
|
if (c.workspacePack?.[member] !== true) continue;
|
|
75849
76372
|
const digest = c.packDigests?.[member];
|
|
75850
76373
|
if (typeof digest !== "string" || digest === "") continue;
|
|
75851
|
-
const abs =
|
|
76374
|
+
const abs = join63(c.worktreePath, rel);
|
|
75852
76375
|
try {
|
|
75853
76376
|
const st = lstatSync5(abs);
|
|
75854
76377
|
if (!st.isFile() || st.size > 1024 * 1024) continue;
|
|
@@ -75867,7 +76390,7 @@ async function claimWorkspaceResult(args5 = {}) {
|
|
|
75867
76390
|
hint: `No workspace has been delivered for this claim yet. A human runs: terminalhire claim start ${c.id} --watch`
|
|
75868
76391
|
};
|
|
75869
76392
|
}
|
|
75870
|
-
if (!existsSync37(c.worktreePath) || !existsSync37(
|
|
76393
|
+
if (!existsSync37(c.worktreePath) || !existsSync37(join63(c.worktreePath, ".git"))) {
|
|
75871
76394
|
return {
|
|
75872
76395
|
status: "not_ready",
|
|
75873
76396
|
claimId: c.id,
|
|
@@ -75985,10 +76508,10 @@ async function run17() {
|
|
|
75985
76508
|
let version2 = "0.0.0";
|
|
75986
76509
|
try {
|
|
75987
76510
|
const { readFileSync: readFileSync43, existsSync: existsSync37 } = await import("fs");
|
|
75988
|
-
const { join:
|
|
76511
|
+
const { join: join63 } = await import("path");
|
|
75989
76512
|
const { fileURLToPath: fileURLToPath15 } = await import("url");
|
|
75990
76513
|
const here = fileURLToPath15(new URL(".", import.meta.url));
|
|
75991
|
-
for (const p of [
|
|
76514
|
+
for (const p of [join63(here, "..", "..", "package.json"), join63(here, "..", "package.json")]) {
|
|
75992
76515
|
if (existsSync37(p)) {
|
|
75993
76516
|
const pkg = JSON.parse(readFileSync43(p, "utf8"));
|
|
75994
76517
|
if (pkg.version) {
|
|
@@ -76289,10 +76812,10 @@ async function run18() {
|
|
|
76289
76812
|
let version2 = "0.0.0";
|
|
76290
76813
|
try {
|
|
76291
76814
|
const { readFileSync: readFileSync43, existsSync: existsSync37 } = await import("fs");
|
|
76292
|
-
const { join:
|
|
76815
|
+
const { join: join63 } = await import("path");
|
|
76293
76816
|
const { fileURLToPath: fileURLToPath15 } = await import("url");
|
|
76294
76817
|
const here = fileURLToPath15(new URL(".", import.meta.url));
|
|
76295
|
-
for (const p of [
|
|
76818
|
+
for (const p of [join63(here, "..", "..", "package.json"), join63(here, "..", "package.json")]) {
|
|
76296
76819
|
if (existsSync37(p)) {
|
|
76297
76820
|
const pkg = JSON.parse(readFileSync43(p, "utf8"));
|
|
76298
76821
|
if (pkg.version) {
|
|
@@ -76853,7 +77376,7 @@ __export(signal_exports, {
|
|
|
76853
77376
|
});
|
|
76854
77377
|
import { readFileSync as readFileSync38, readdirSync as readdirSync6 } from "fs";
|
|
76855
77378
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
76856
|
-
import { join as
|
|
77379
|
+
import { join as join55 } from "path";
|
|
76857
77380
|
function safeGit(args5, cwd) {
|
|
76858
77381
|
try {
|
|
76859
77382
|
return execFileSync5("git", ["-C", cwd, ...args5], {
|
|
@@ -76894,7 +77417,7 @@ function readFileSafe(path6) {
|
|
|
76894
77417
|
}
|
|
76895
77418
|
}
|
|
76896
77419
|
function tokensFromPackageJson(cwd) {
|
|
76897
|
-
const pkg = readJsonSafe(
|
|
77420
|
+
const pkg = readJsonSafe(join55(cwd, "package.json"));
|
|
76898
77421
|
if (!pkg || typeof pkg !== "object") return [];
|
|
76899
77422
|
const p = pkg;
|
|
76900
77423
|
const deps = {
|
|
@@ -76908,9 +77431,9 @@ function workspaceMemberDirs(cwd) {
|
|
|
76908
77431
|
const dirs = [cwd];
|
|
76909
77432
|
for (const group of ["apps", "packages"]) {
|
|
76910
77433
|
try {
|
|
76911
|
-
const groupDir =
|
|
77434
|
+
const groupDir = join55(cwd, group);
|
|
76912
77435
|
for (const e of readdirSync6(groupDir, { withFileTypes: true })) {
|
|
76913
|
-
if (e.isDirectory() && !e.isSymbolicLink()) dirs.push(
|
|
77436
|
+
if (e.isDirectory() && !e.isSymbolicLink()) dirs.push(join55(groupDir, e.name));
|
|
76914
77437
|
}
|
|
76915
77438
|
} catch {
|
|
76916
77439
|
}
|
|
@@ -76918,18 +77441,18 @@ function workspaceMemberDirs(cwd) {
|
|
|
76918
77441
|
return dirs;
|
|
76919
77442
|
}
|
|
76920
77443
|
function tokensFromRequirementsTxt(cwd) {
|
|
76921
|
-
const content = readFileSafe(
|
|
77444
|
+
const content = readFileSafe(join55(cwd, "requirements.txt"));
|
|
76922
77445
|
if (!content) return [];
|
|
76923
77446
|
return content.split("\n").map((l) => l.trim().split(/[>=<!\[;]/)[0].trim().toLowerCase()).filter(Boolean);
|
|
76924
77447
|
}
|
|
76925
77448
|
function tokensFromGoMod(cwd) {
|
|
76926
|
-
const content = readFileSafe(
|
|
77449
|
+
const content = readFileSafe(join55(cwd, "go.mod"));
|
|
76927
77450
|
if (!content) return [];
|
|
76928
77451
|
const requires = Array.from(content.matchAll(/^\s+([^\s]+)\s+v/gm)).map((m) => m[1].split("/").pop() ?? "").filter(Boolean);
|
|
76929
77452
|
return ["go", ...requires];
|
|
76930
77453
|
}
|
|
76931
77454
|
function tokensFromCargoToml(cwd) {
|
|
76932
|
-
const content = readFileSafe(
|
|
77455
|
+
const content = readFileSafe(join55(cwd, "Cargo.toml"));
|
|
76933
77456
|
if (!content) return [];
|
|
76934
77457
|
const deps = [];
|
|
76935
77458
|
let inDeps = false;
|
|
@@ -76950,7 +77473,7 @@ function tokensFromFileExtensions(cwd) {
|
|
|
76950
77473
|
const tokens = [];
|
|
76951
77474
|
const scanDirs = [cwd];
|
|
76952
77475
|
try {
|
|
76953
|
-
const srcDir =
|
|
77476
|
+
const srcDir = join55(cwd, "src");
|
|
76954
77477
|
readdirSync6(srcDir);
|
|
76955
77478
|
scanDirs.push(srcDir);
|
|
76956
77479
|
} catch {
|
|
@@ -77150,7 +77673,7 @@ var jpi_config_exports = {};
|
|
|
77150
77673
|
__export(jpi_config_exports, {
|
|
77151
77674
|
run: () => run24
|
|
77152
77675
|
});
|
|
77153
|
-
import { join as
|
|
77676
|
+
import { join as join56 } from "path";
|
|
77154
77677
|
import { homedir as homedir35 } from "os";
|
|
77155
77678
|
function parseNudgeMode2(raw) {
|
|
77156
77679
|
if (raw === "session" || raw === "always") return raw;
|
|
@@ -77338,8 +77861,8 @@ var init_jpi_config = __esm({
|
|
|
77338
77861
|
"bin/jpi-config.js"() {
|
|
77339
77862
|
"use strict";
|
|
77340
77863
|
init_config();
|
|
77341
|
-
TERMINALHIRE_DIR21 = process.env.TERMINALHIRE_DIR ||
|
|
77342
|
-
CONFIG_FILE2 =
|
|
77864
|
+
TERMINALHIRE_DIR21 = process.env.TERMINALHIRE_DIR || join56(homedir35(), ".terminalhire");
|
|
77865
|
+
CONFIG_FILE2 = join56(TERMINALHIRE_DIR21, "config.json");
|
|
77343
77866
|
}
|
|
77344
77867
|
});
|
|
77345
77868
|
|
|
@@ -77348,8 +77871,8 @@ var jpi_spinner_exports = {};
|
|
|
77348
77871
|
__export(jpi_spinner_exports, {
|
|
77349
77872
|
run: () => run25
|
|
77350
77873
|
});
|
|
77351
|
-
import { readFileSync as readFileSync39, writeFileSync as
|
|
77352
|
-
import { join as
|
|
77874
|
+
import { readFileSync as readFileSync39, writeFileSync as writeFileSync32, copyFileSync as copyFileSync4, existsSync as existsSync31 } from "fs";
|
|
77875
|
+
import { join as join57 } from "path";
|
|
77353
77876
|
import { homedir as homedir36 } from "os";
|
|
77354
77877
|
import { createInterface as createInterface13 } from "readline";
|
|
77355
77878
|
function readConfig3() {
|
|
@@ -77362,7 +77885,7 @@ function readConfig3() {
|
|
|
77362
77885
|
function writeConfig2(patch) {
|
|
77363
77886
|
ensureStateDir(TH_DIR);
|
|
77364
77887
|
const merged = { ...readConfig3(), ...patch };
|
|
77365
|
-
|
|
77888
|
+
writeFileSync32(CONFIG_FILE3, JSON.stringify(merged, null, 2) + "\n", "utf8");
|
|
77366
77889
|
}
|
|
77367
77890
|
function backupSettings() {
|
|
77368
77891
|
if (!existsSync31(SETTINGS_PATH)) return null;
|
|
@@ -77596,10 +78119,10 @@ var init_jpi_spinner = __esm({
|
|
|
77596
78119
|
"use strict";
|
|
77597
78120
|
init_spinner();
|
|
77598
78121
|
init_state_dir();
|
|
77599
|
-
TH_DIR = process.env["TERMINALHIRE_DIR"] ||
|
|
77600
|
-
CONFIG_FILE3 =
|
|
77601
|
-
SETTINGS_PATH = process.env["TERMINALHIRE_CLAUDE_SETTINGS"] ||
|
|
77602
|
-
CACHE_FILE2 =
|
|
78122
|
+
TH_DIR = process.env["TERMINALHIRE_DIR"] || join57(homedir36(), ".terminalhire");
|
|
78123
|
+
CONFIG_FILE3 = join57(TH_DIR, "config.json");
|
|
78124
|
+
SETTINGS_PATH = process.env["TERMINALHIRE_CLAUDE_SETTINGS"] || join57(homedir36(), ".claude", "settings.json");
|
|
78125
|
+
CACHE_FILE2 = join57(TH_DIR, "index-cache.json");
|
|
77603
78126
|
}
|
|
77604
78127
|
});
|
|
77605
78128
|
|
|
@@ -77608,8 +78131,8 @@ var jpi_sync_exports = {};
|
|
|
77608
78131
|
__export(jpi_sync_exports, {
|
|
77609
78132
|
run: () => run26
|
|
77610
78133
|
});
|
|
77611
|
-
import { readFileSync as readFileSync40, writeFileSync as
|
|
77612
|
-
import { join as
|
|
78134
|
+
import { readFileSync as readFileSync40, writeFileSync as writeFileSync33, existsSync as existsSync32, rmSync as rmSync16 } from "fs";
|
|
78135
|
+
import { join as join58 } from "path";
|
|
77613
78136
|
import { homedir as homedir37, hostname as osHostname2 } from "os";
|
|
77614
78137
|
import { createInterface as createInterface14 } from "readline";
|
|
77615
78138
|
function oauthSyncBase() {
|
|
@@ -77633,7 +78156,7 @@ function readMarker() {
|
|
|
77633
78156
|
}
|
|
77634
78157
|
function writeMarker(marker) {
|
|
77635
78158
|
ensureStateDir(TH_DIR2);
|
|
77636
|
-
|
|
78159
|
+
writeFileSync33(TIER1_MARKER, JSON.stringify(marker, null, 2) + "\n", "utf8");
|
|
77637
78160
|
}
|
|
77638
78161
|
function clearMarker() {
|
|
77639
78162
|
try {
|
|
@@ -77962,8 +78485,8 @@ var init_jpi_sync = __esm({
|
|
|
77962
78485
|
init_open_url();
|
|
77963
78486
|
init_state_dir();
|
|
77964
78487
|
init_api_base();
|
|
77965
|
-
TH_DIR2 = process.env["TERMINALHIRE_DIR"] ||
|
|
77966
|
-
TIER1_MARKER =
|
|
78488
|
+
TH_DIR2 = process.env["TERMINALHIRE_DIR"] || join58(homedir37(), ".terminalhire");
|
|
78489
|
+
TIER1_MARKER = join58(TH_DIR2, "tier1.json");
|
|
77967
78490
|
API_URL8 = resolveApiBase();
|
|
77968
78491
|
warnSharedCredentialsIfNonProd(API_URL8);
|
|
77969
78492
|
POLL_INTERVAL_MS = 2e3;
|
|
@@ -77978,30 +78501,30 @@ __export(jpi_init_exports, {
|
|
|
77978
78501
|
run: () => run27
|
|
77979
78502
|
});
|
|
77980
78503
|
import { existsSync as existsSync33 } from "fs";
|
|
77981
|
-
import { join as
|
|
78504
|
+
import { join as join59, resolve as resolve6 } from "path";
|
|
77982
78505
|
import { fileURLToPath as fileURLToPath10, pathToFileURL } from "url";
|
|
77983
78506
|
import { createInterface as createInterface15 } from "readline";
|
|
77984
78507
|
import { spawnSync as spawnSync12 } from "child_process";
|
|
77985
78508
|
function resolveScript(name) {
|
|
77986
|
-
const distPath = resolve6(
|
|
77987
|
-
const legacyPath = resolve6(
|
|
78509
|
+
const distPath = resolve6(join59(__dirname5, "..", "..", "dist", "bin", `${name}.js`));
|
|
78510
|
+
const legacyPath = resolve6(join59(__dirname5, `${name}.js`));
|
|
77988
78511
|
return existsSync33(distPath) ? distPath : legacyPath;
|
|
77989
78512
|
}
|
|
77990
78513
|
function resolveSrc(name) {
|
|
77991
|
-
const distPath = resolve6(
|
|
77992
|
-
const legacyPath = resolve6(
|
|
78514
|
+
const distPath = resolve6(join59(__dirname5, "..", "..", "dist", "src", `${name}.js`));
|
|
78515
|
+
const legacyPath = resolve6(join59(__dirname5, "..", "src", `${name}.js`));
|
|
77993
78516
|
return existsSync33(distPath) ? distPath : legacyPath;
|
|
77994
78517
|
}
|
|
77995
78518
|
function resolveInstallJs() {
|
|
77996
|
-
const fromDist = resolve6(
|
|
77997
|
-
const fromBin = resolve6(
|
|
78519
|
+
const fromDist = resolve6(join59(__dirname5, "..", "..", "install.js"));
|
|
78520
|
+
const fromBin = resolve6(join59(__dirname5, "..", "install.js"));
|
|
77998
78521
|
if (existsSync33(fromDist)) return fromDist;
|
|
77999
78522
|
if (existsSync33(fromBin)) return fromBin;
|
|
78000
78523
|
return fromBin;
|
|
78001
78524
|
}
|
|
78002
78525
|
function resolveStatuslineInstallJs() {
|
|
78003
|
-
const fromDist = resolve6(
|
|
78004
|
-
const fromBin = resolve6(
|
|
78526
|
+
const fromDist = resolve6(join59(__dirname5, "..", "..", "statusline-install.js"));
|
|
78527
|
+
const fromBin = resolve6(join59(__dirname5, "..", "statusline-install.js"));
|
|
78005
78528
|
if (existsSync33(fromDist)) return fromDist;
|
|
78006
78529
|
if (existsSync33(fromBin)) return fromBin;
|
|
78007
78530
|
return fromBin;
|
|
@@ -79006,7 +79529,7 @@ __export(jpi_save_exports, {
|
|
|
79006
79529
|
run: () => run29
|
|
79007
79530
|
});
|
|
79008
79531
|
import { readFileSync as readFileSync41, existsSync as existsSync34 } from "fs";
|
|
79009
|
-
import { join as
|
|
79532
|
+
import { join as join60 } from "path";
|
|
79010
79533
|
import { homedir as homedir38 } from "os";
|
|
79011
79534
|
import { fileURLToPath as fileURLToPath12 } from "url";
|
|
79012
79535
|
function findJobInCache(jobId) {
|
|
@@ -79105,8 +79628,8 @@ var init_jpi_save = __esm({
|
|
|
79105
79628
|
"bin/jpi-save.js"() {
|
|
79106
79629
|
"use strict";
|
|
79107
79630
|
__dirname7 = fileURLToPath12(new URL(".", import.meta.url));
|
|
79108
|
-
TERMINALHIRE_DIR22 = process.env.TERMINALHIRE_DIR ||
|
|
79109
|
-
INDEX_CACHE_FILE7 =
|
|
79631
|
+
TERMINALHIRE_DIR22 = process.env.TERMINALHIRE_DIR || join60(homedir38(), ".terminalhire");
|
|
79632
|
+
INDEX_CACHE_FILE7 = join60(TERMINALHIRE_DIR22, "index-cache.json");
|
|
79110
79633
|
}
|
|
79111
79634
|
});
|
|
79112
79635
|
|
|
@@ -79156,10 +79679,10 @@ async function run30() {
|
|
|
79156
79679
|
console.log(" rough edges you find.");
|
|
79157
79680
|
console.log(" \u2022 A spot on the founding-contributors wall.");
|
|
79158
79681
|
console.log("");
|
|
79159
|
-
const
|
|
79682
|
+
const join63 = await ask5(
|
|
79160
79683
|
' Type "yes" to join the beta as a Founding Contributor (anything else cancels): '
|
|
79161
79684
|
);
|
|
79162
|
-
if ((
|
|
79685
|
+
if ((join63 || "").toLowerCase() !== "yes") {
|
|
79163
79686
|
console.log("\n No problem \u2014 nothing was sent. Run `terminalhire beta` any time.\n");
|
|
79164
79687
|
rl.close();
|
|
79165
79688
|
return;
|
|
@@ -79250,13 +79773,13 @@ __export(jpi_feedback_exports, {
|
|
|
79250
79773
|
});
|
|
79251
79774
|
import { createInterface as createInterface17 } from "readline";
|
|
79252
79775
|
import { readFileSync as readFileSync42, existsSync as existsSync35 } from "fs";
|
|
79253
|
-
import { join as
|
|
79776
|
+
import { join as join61 } from "path";
|
|
79254
79777
|
import { fileURLToPath as fileURLToPath13 } from "url";
|
|
79255
79778
|
function readLocalVersion3() {
|
|
79256
79779
|
try {
|
|
79257
79780
|
for (const p of [
|
|
79258
|
-
|
|
79259
|
-
|
|
79781
|
+
join61(__dirname8, "..", "..", "package.json"),
|
|
79782
|
+
join61(__dirname8, "..", "package.json")
|
|
79260
79783
|
]) {
|
|
79261
79784
|
if (existsSync35(p)) {
|
|
79262
79785
|
const pkg = JSON.parse(readFileSync42(p, "utf8"));
|
|
@@ -79399,7 +79922,7 @@ var init_jpi_feedback = __esm({
|
|
|
79399
79922
|
init_package_version();
|
|
79400
79923
|
init_api_base();
|
|
79401
79924
|
import { fileURLToPath as fileURLToPath14 } from "url";
|
|
79402
|
-
import { join as
|
|
79925
|
+
import { join as join62 } from "path";
|
|
79403
79926
|
import { existsSync as existsSync36 } from "fs";
|
|
79404
79927
|
|
|
79405
79928
|
// src/state-dir-pin.ts
|
|
@@ -79499,7 +80022,7 @@ var SUBCOMMANDS = [
|
|
|
79499
80022
|
var firstArg = process.argv[2];
|
|
79500
80023
|
if (!firstArg && !process.stdin.isTTY) {
|
|
79501
80024
|
const { default: childProcess } = await import("child_process");
|
|
79502
|
-
const nudgeScript =
|
|
80025
|
+
const nudgeScript = join62(__dirname9, "jpi.js");
|
|
79503
80026
|
const child = childProcess.spawnSync(process.execPath, [nudgeScript], {
|
|
79504
80027
|
stdio: ["inherit", "inherit", "inherit"]
|
|
79505
80028
|
});
|
|
@@ -80021,8 +80544,8 @@ if (firstArg === "statusline") {
|
|
|
80021
80544
|
console.error("Usage: terminalhire statusline --on | --off");
|
|
80022
80545
|
process.exit(1);
|
|
80023
80546
|
}
|
|
80024
|
-
const fromDist =
|
|
80025
|
-
const fromBin =
|
|
80547
|
+
const fromDist = join62(__dirname9, "..", "..", "statusline-install.js");
|
|
80548
|
+
const fromBin = join62(__dirname9, "..", "statusline-install.js");
|
|
80026
80549
|
const installer = existsSync36(fromDist) ? fromDist : fromBin;
|
|
80027
80550
|
const { spawnSync: spawnSync13 } = await import("child_process");
|
|
80028
80551
|
const child = spawnSync13(process.execPath, uninstall ? [installer, "--uninstall"] : [installer], {
|