@whittlelabs/sifter 0.33.3 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin.js +1167 -639
- package/bin.js.map +4 -4
- package/package.json +1 -1
package/bin.js
CHANGED
|
@@ -3122,6 +3122,37 @@ var require_registry = __commonJS({
|
|
|
3122
3122
|
}
|
|
3123
3123
|
});
|
|
3124
3124
|
|
|
3125
|
+
// ../../packages/loom/dist/runtime/requirements.js
|
|
3126
|
+
var require_requirements = __commonJS({
|
|
3127
|
+
"../../packages/loom/dist/runtime/requirements.js"(exports2) {
|
|
3128
|
+
"use strict";
|
|
3129
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3130
|
+
exports2.REQUIRES_EXECUTOR_TAG = exports2.EXECUTOR_ID = void 0;
|
|
3131
|
+
exports2.requirementTags = requirementTags;
|
|
3132
|
+
exports2.readRequiredExecutor = readRequiredExecutor;
|
|
3133
|
+
exports2.EXECUTOR_ID = /^[a-z][a-z0-9-]{0,63}$/;
|
|
3134
|
+
exports2.REQUIRES_EXECUTOR_TAG = "requires-executor:";
|
|
3135
|
+
function requirementTags(requires) {
|
|
3136
|
+
if (!requires?.executor)
|
|
3137
|
+
return [];
|
|
3138
|
+
if (!exports2.EXECUTOR_ID.test(requires.executor)) {
|
|
3139
|
+
throw new Error(`prompt-execution: requires.executor "${requires.executor}" is not an executor id`);
|
|
3140
|
+
}
|
|
3141
|
+
return [`${exports2.REQUIRES_EXECUTOR_TAG}${requires.executor}`];
|
|
3142
|
+
}
|
|
3143
|
+
function readRequiredExecutor(tags) {
|
|
3144
|
+
for (const tag of tags ?? []) {
|
|
3145
|
+
if (!tag.startsWith(exports2.REQUIRES_EXECUTOR_TAG))
|
|
3146
|
+
continue;
|
|
3147
|
+
const executor = tag.slice(exports2.REQUIRES_EXECUTOR_TAG.length);
|
|
3148
|
+
if (exports2.EXECUTOR_ID.test(executor))
|
|
3149
|
+
return executor;
|
|
3150
|
+
}
|
|
3151
|
+
return null;
|
|
3152
|
+
}
|
|
3153
|
+
}
|
|
3154
|
+
});
|
|
3155
|
+
|
|
3125
3156
|
// ../../packages/loom/dist/runtime/prompt-execution.js
|
|
3126
3157
|
var require_prompt_execution = __commonJS({
|
|
3127
3158
|
"../../packages/loom/dist/runtime/prompt-execution.js"(exports2) {
|
|
@@ -3131,6 +3162,7 @@ var require_prompt_execution = __commonJS({
|
|
|
3131
3162
|
exports2.renderPromptExecution = renderPromptExecution;
|
|
3132
3163
|
exports2.pickProviderHints = pickProviderHints;
|
|
3133
3164
|
exports2.renderTemplate = renderTemplate;
|
|
3165
|
+
var requirements_1 = require_requirements();
|
|
3134
3166
|
function readPromptExecutionSpec(inputs) {
|
|
3135
3167
|
const specRow = inputs.find((i) => i.label === "spec");
|
|
3136
3168
|
if (!specRow)
|
|
@@ -3162,6 +3194,15 @@ var require_prompt_execution = __commonJS({
|
|
|
3162
3194
|
}
|
|
3163
3195
|
}
|
|
3164
3196
|
}
|
|
3197
|
+
if (spec.requires !== void 0) {
|
|
3198
|
+
const req = spec.requires;
|
|
3199
|
+
if (typeof req !== "object" || req === null || Array.isArray(req)) {
|
|
3200
|
+
throw new Error("prompt-execution: spec.requires must be an object when present");
|
|
3201
|
+
}
|
|
3202
|
+
if (req.executor !== void 0 && (typeof req.executor !== "string" || !requirements_1.EXECUTOR_ID.test(req.executor))) {
|
|
3203
|
+
throw new Error("prompt-execution: spec.requires.executor must be an executor id");
|
|
3204
|
+
}
|
|
3205
|
+
}
|
|
3165
3206
|
if (spec.gates !== void 0) {
|
|
3166
3207
|
if (!Array.isArray(spec.gates)) {
|
|
3167
3208
|
throw new Error("prompt-execution: spec.gates must be an array when present");
|
|
@@ -3337,7 +3378,7 @@ var require_runtime = __commonJS({
|
|
|
3337
3378
|
"../../packages/loom/dist/runtime/index.js"(exports2) {
|
|
3338
3379
|
"use strict";
|
|
3339
3380
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3340
|
-
exports2.validateAgainstSchema = exports2.readShuttleStrategy = exports2.shuttleStrategyInput = exports2.PROMPT_EXECUTION_STRATEGY = exports2.SHUTTLE_STRATEGY_LABEL = exports2.pickProviderHints = exports2.renderTemplate = exports2.renderPromptExecution = exports2.readPromptExecutionSpec = void 0;
|
|
3381
|
+
exports2.validateAgainstSchema = exports2.readRequiredExecutor = exports2.requirementTags = exports2.REQUIRES_EXECUTOR_TAG = exports2.EXECUTOR_ID = exports2.readShuttleStrategy = exports2.shuttleStrategyInput = exports2.PROMPT_EXECUTION_STRATEGY = exports2.SHUTTLE_STRATEGY_LABEL = exports2.pickProviderHints = exports2.renderTemplate = exports2.renderPromptExecution = exports2.readPromptExecutionSpec = void 0;
|
|
3341
3382
|
var prompt_execution_1 = require_prompt_execution();
|
|
3342
3383
|
Object.defineProperty(exports2, "readPromptExecutionSpec", { enumerable: true, get: function() {
|
|
3343
3384
|
return prompt_execution_1.readPromptExecutionSpec;
|
|
@@ -3364,6 +3405,19 @@ var require_runtime = __commonJS({
|
|
|
3364
3405
|
Object.defineProperty(exports2, "readShuttleStrategy", { enumerable: true, get: function() {
|
|
3365
3406
|
return strategy_1.readShuttleStrategy;
|
|
3366
3407
|
} });
|
|
3408
|
+
var requirements_1 = require_requirements();
|
|
3409
|
+
Object.defineProperty(exports2, "EXECUTOR_ID", { enumerable: true, get: function() {
|
|
3410
|
+
return requirements_1.EXECUTOR_ID;
|
|
3411
|
+
} });
|
|
3412
|
+
Object.defineProperty(exports2, "REQUIRES_EXECUTOR_TAG", { enumerable: true, get: function() {
|
|
3413
|
+
return requirements_1.REQUIRES_EXECUTOR_TAG;
|
|
3414
|
+
} });
|
|
3415
|
+
Object.defineProperty(exports2, "requirementTags", { enumerable: true, get: function() {
|
|
3416
|
+
return requirements_1.requirementTags;
|
|
3417
|
+
} });
|
|
3418
|
+
Object.defineProperty(exports2, "readRequiredExecutor", { enumerable: true, get: function() {
|
|
3419
|
+
return requirements_1.readRequiredExecutor;
|
|
3420
|
+
} });
|
|
3367
3421
|
var validate_1 = require_validate();
|
|
3368
3422
|
Object.defineProperty(exports2, "validateAgainstSchema", { enumerable: true, get: function() {
|
|
3369
3423
|
return validate_1.validateAgainstSchema;
|
|
@@ -3377,7 +3431,9 @@ var require_prompt_execution2 = __commonJS({
|
|
|
3377
3431
|
"use strict";
|
|
3378
3432
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3379
3433
|
exports2.buildPromptExecutionInputs = buildPromptExecutionInputs;
|
|
3434
|
+
exports2.promptExecutionTags = promptExecutionTags;
|
|
3380
3435
|
var strategy_1 = require_strategy();
|
|
3436
|
+
var requirements_1 = require_requirements();
|
|
3381
3437
|
function buildPromptExecutionInputs(options) {
|
|
3382
3438
|
const spec = {
|
|
3383
3439
|
rendering: options.rendering,
|
|
@@ -3386,6 +3442,10 @@ var require_prompt_execution2 = __commonJS({
|
|
|
3386
3442
|
};
|
|
3387
3443
|
if (options.workspace)
|
|
3388
3444
|
spec.workspace = options.workspace;
|
|
3445
|
+
if (options.requires?.executor) {
|
|
3446
|
+
(0, requirements_1.requirementTags)(options.requires);
|
|
3447
|
+
spec.requires = { executor: options.requires.executor };
|
|
3448
|
+
}
|
|
3389
3449
|
if (options.providerHints)
|
|
3390
3450
|
spec.providerHints = options.providerHints;
|
|
3391
3451
|
if (options.costCapHint)
|
|
@@ -3423,6 +3483,10 @@ var require_prompt_execution2 = __commonJS({
|
|
|
3423
3483
|
}
|
|
3424
3484
|
return inputs;
|
|
3425
3485
|
}
|
|
3486
|
+
function promptExecutionTags(options) {
|
|
3487
|
+
const tags = [.../* @__PURE__ */ new Set([...options.tags ?? [], ...(0, requirements_1.requirementTags)(options.requires)])];
|
|
3488
|
+
return tags.length > 0 ? tags : void 0;
|
|
3489
|
+
}
|
|
3426
3490
|
}
|
|
3427
3491
|
});
|
|
3428
3492
|
|
|
@@ -9780,12 +9844,15 @@ var require_dist = __commonJS({
|
|
|
9780
9844
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
|
|
9781
9845
|
};
|
|
9782
9846
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
9783
|
-
exports2.SeedWorkflowsError = exports2.WorkflowBuilderError = exports2.seedWorkflows = exports2.canonicaliseWorkflow = exports2.synthesiseLinearChain = exports2.describeJobPoolRef = exports2.literalJobPool = exports2.principalJobPool = exports2.jobsCreateNode = exports2.httpNode = exports2.promptNode = exports2.defineWorkflow = exports2.buildPromptExecutionInputs = void 0;
|
|
9847
|
+
exports2.SeedWorkflowsError = exports2.WorkflowBuilderError = exports2.seedWorkflows = exports2.canonicaliseWorkflow = exports2.synthesiseLinearChain = exports2.describeJobPoolRef = exports2.literalJobPool = exports2.principalJobPool = exports2.jobsCreateNode = exports2.httpNode = exports2.promptNode = exports2.defineWorkflow = exports2.promptExecutionTags = exports2.buildPromptExecutionInputs = void 0;
|
|
9784
9848
|
__exportStar(require_runtime(), exports2);
|
|
9785
9849
|
var prompt_execution_1 = require_prompt_execution2();
|
|
9786
9850
|
Object.defineProperty(exports2, "buildPromptExecutionInputs", { enumerable: true, get: function() {
|
|
9787
9851
|
return prompt_execution_1.buildPromptExecutionInputs;
|
|
9788
9852
|
} });
|
|
9853
|
+
Object.defineProperty(exports2, "promptExecutionTags", { enumerable: true, get: function() {
|
|
9854
|
+
return prompt_execution_1.promptExecutionTags;
|
|
9855
|
+
} });
|
|
9789
9856
|
var define_workflow_1 = require_define_workflow();
|
|
9790
9857
|
Object.defineProperty(exports2, "defineWorkflow", { enumerable: true, get: function() {
|
|
9791
9858
|
return define_workflow_1.defineWorkflow;
|
|
@@ -9837,8 +9904,9 @@ var require_types2 = __commonJS({
|
|
|
9837
9904
|
"../../packages/shuttle/dist/executors/types.js"(exports2) {
|
|
9838
9905
|
"use strict";
|
|
9839
9906
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
9840
|
-
exports2.ExecutorEnvironmentError = void 0;
|
|
9907
|
+
exports2.MODEL_UNAVAILABLE = exports2.ExecutorModelUnavailableError = exports2.ExecutorEnvironmentError = void 0;
|
|
9841
9908
|
exports2.isExecutorEnvironmentError = isExecutorEnvironmentError;
|
|
9909
|
+
exports2.isExecutorModelUnavailableError = isExecutorModelUnavailableError;
|
|
9842
9910
|
var ExecutorEnvironmentError = class extends Error {
|
|
9843
9911
|
/** What the operator should do, as one clause: "run `claude` and sign in". */
|
|
9844
9912
|
remedy;
|
|
@@ -9852,6 +9920,17 @@ var require_types2 = __commonJS({
|
|
|
9852
9920
|
function isExecutorEnvironmentError(err) {
|
|
9853
9921
|
return err instanceof Error && err.name === "ExecutorEnvironmentError";
|
|
9854
9922
|
}
|
|
9923
|
+
var ExecutorModelUnavailableError = class extends Error {
|
|
9924
|
+
constructor(message) {
|
|
9925
|
+
super(message);
|
|
9926
|
+
this.name = "ExecutorModelUnavailableError";
|
|
9927
|
+
}
|
|
9928
|
+
};
|
|
9929
|
+
exports2.ExecutorModelUnavailableError = ExecutorModelUnavailableError;
|
|
9930
|
+
function isExecutorModelUnavailableError(err) {
|
|
9931
|
+
return err instanceof Error && err.name === "ExecutorModelUnavailableError";
|
|
9932
|
+
}
|
|
9933
|
+
exports2.MODEL_UNAVAILABLE = "model-unavailable";
|
|
9855
9934
|
}
|
|
9856
9935
|
});
|
|
9857
9936
|
|
|
@@ -10070,6 +10149,7 @@ var require_agent_process = __commonJS({
|
|
|
10070
10149
|
exports2.firstLine = firstLine;
|
|
10071
10150
|
exports2.keepTranscript = keepTranscript;
|
|
10072
10151
|
exports2.classifyAgentFault = classifyAgentFault;
|
|
10152
|
+
exports2.isModelUnavailable = isModelUnavailable;
|
|
10073
10153
|
exports2.agentFailure = agentFailure;
|
|
10074
10154
|
var types_1 = require_types2();
|
|
10075
10155
|
var child_process_1 = require("child_process");
|
|
@@ -10187,11 +10267,16 @@ var require_agent_process = __commonJS({
|
|
|
10187
10267
|
}
|
|
10188
10268
|
return null;
|
|
10189
10269
|
}
|
|
10270
|
+
function isModelUnavailable(failure, vocab) {
|
|
10271
|
+
return failure.apiErrorStatus === 404 || vocab.modelUnavailable.test(failure.text ?? "");
|
|
10272
|
+
}
|
|
10190
10273
|
function agentFailure(local, message, facts, vocab) {
|
|
10191
|
-
|
|
10192
|
-
|
|
10193
|
-
|
|
10194
|
-
|
|
10274
|
+
const remedy = local ? classifyAgentFault(facts, vocab) : null;
|
|
10275
|
+
if (remedy)
|
|
10276
|
+
return new types_1.ExecutorEnvironmentError(message, remedy);
|
|
10277
|
+
if (isModelUnavailable(facts, vocab))
|
|
10278
|
+
return new types_1.ExecutorModelUnavailableError(message);
|
|
10279
|
+
return new Error(message);
|
|
10195
10280
|
}
|
|
10196
10281
|
}
|
|
10197
10282
|
});
|
|
@@ -10611,7 +10696,10 @@ var require_claude_code = __commonJS({
|
|
|
10611
10696
|
loginRemedy: LOGIN_REMEDY,
|
|
10612
10697
|
limitRemedy: LIMIT_REMEDY,
|
|
10613
10698
|
signedOut: SIGNED_OUT,
|
|
10614
|
-
outOfUsage: OUT_OF_USAGE
|
|
10699
|
+
outOfUsage: OUT_OF_USAGE,
|
|
10700
|
+
// claude 2.x: "There's an issue with the selected model (x). It may not
|
|
10701
|
+
// exist or you may not have access to it." beside the provider's 404.
|
|
10702
|
+
modelUnavailable: /issue with the selected model|may not exist or you may not have access/i
|
|
10615
10703
|
};
|
|
10616
10704
|
function classifyEnvironmentFault(failure) {
|
|
10617
10705
|
return (0, agent_process_1.classifyAgentFault)(failure, CLAUDE_FAULTS);
|
|
@@ -10984,6 +11072,7 @@ var require_claude_code = __commonJS({
|
|
|
10984
11072
|
let finalText = null;
|
|
10985
11073
|
const readPaths = [];
|
|
10986
11074
|
let usage = null;
|
|
11075
|
+
const toolCalls = {};
|
|
10987
11076
|
let resultMeta = null;
|
|
10988
11077
|
let structuredOutput = null;
|
|
10989
11078
|
let sessionId = null;
|
|
@@ -11011,6 +11100,8 @@ var require_claude_code = __commonJS({
|
|
|
11011
11100
|
const b = block;
|
|
11012
11101
|
if (b?.type !== "tool_use")
|
|
11013
11102
|
continue;
|
|
11103
|
+
if (typeof b.name === "string")
|
|
11104
|
+
toolCalls[b.name] = (toolCalls[b.name] ?? 0) + 1;
|
|
11014
11105
|
const fp = b.input?.file_path;
|
|
11015
11106
|
if (b.name === "Read" && typeof fp === "string") {
|
|
11016
11107
|
readPaths.push(fp);
|
|
@@ -11037,13 +11128,19 @@ var require_claude_code = __commonJS({
|
|
|
11037
11128
|
}
|
|
11038
11129
|
const u = event.usage;
|
|
11039
11130
|
const cost = event.total_cost_usd;
|
|
11131
|
+
const turns = event.num_turns;
|
|
11040
11132
|
usage = {
|
|
11041
11133
|
...typeof u?.input_tokens === "number" ? { inputTokens: u.input_tokens } : {},
|
|
11042
11134
|
...typeof u?.output_tokens === "number" ? { outputTokens: u.output_tokens } : {},
|
|
11043
|
-
...typeof
|
|
11135
|
+
...typeof u?.cache_read_input_tokens === "number" ? { cacheReadInputTokens: u.cache_read_input_tokens } : {},
|
|
11136
|
+
...typeof u?.cache_creation_input_tokens === "number" ? { cacheCreationInputTokens: u.cache_creation_input_tokens } : {},
|
|
11137
|
+
...typeof cost === "number" ? { costUsd: cost } : {},
|
|
11138
|
+
...typeof turns === "number" ? { turns } : {}
|
|
11044
11139
|
};
|
|
11045
11140
|
}
|
|
11046
11141
|
}
|
|
11142
|
+
if (usage && Object.keys(toolCalls).length > 0)
|
|
11143
|
+
usage.toolCalls = toolCalls;
|
|
11047
11144
|
return { finalText, readPaths, usage, resultMeta, structuredOutput, sessionId, model, toolInputs };
|
|
11048
11145
|
}
|
|
11049
11146
|
}
|
|
@@ -11306,7 +11403,10 @@ var require_codex = __commonJS({
|
|
|
11306
11403
|
loginRemedy: "run `codex login` and sign in (or `codex login --with-api-key`)",
|
|
11307
11404
|
limitRemedy: "wait for the plan's usage limit to reset, or raise it",
|
|
11308
11405
|
signedOut: /not logged in|run `?codex login|401 unauthorized|invalid api key|refresh token|token (?:has )?expired|sign in again/i,
|
|
11309
|
-
outOfUsage: /usage limit|hit your (?:\w+ )?limit|insufficient_quota|exceeded your current quota|429 too many requests/i
|
|
11406
|
+
outOfUsage: /usage limit|hit your (?:\w+ )?limit|insufficient_quota|exceeded your current quota|429 too many requests/i,
|
|
11407
|
+
// OpenAI's words for a model the key may not use, and codex's for one a
|
|
11408
|
+
// ChatGPT sign-in does not include.
|
|
11409
|
+
modelUnavailable: /model_not_found|model .*(?:does not exist|you do not have access to it)|model is not supported|404 not found.*model/i
|
|
11310
11410
|
};
|
|
11311
11411
|
var READINESS_PROMPT = "Reply with the single word: ok";
|
|
11312
11412
|
var READINESS_TIMEOUT_MS = 12e4;
|
|
@@ -11727,6 +11827,10 @@ var require_copilot = __commonJS({
|
|
|
11727
11827
|
limitRemedy: "the account has no Copilot allowance left: on an organization seat, an owner must allow paid usage in the organization's Copilot policies and fund a budget for it; otherwise wait for the monthly reset",
|
|
11728
11828
|
signedOut: /not (?:logged|signed) in|run `?copilot login|no authentication|authentication (?:failed|required)|bad credentials/i,
|
|
11729
11829
|
outOfUsage: /exceeded your monthly quota|premium request|usage limit|hit your (?:\w+ )?limit|exceeded .*(?:allowance|limit)/i,
|
|
11830
|
+
// copilot 1.0.98 offers only the models the account may use, so a model
|
|
11831
|
+
// that does not exist and one a policy disables both read: Model "x" from
|
|
11832
|
+
// --model flag is not available.
|
|
11833
|
+
modelUnavailable: /model "?[^"\n]*"? (?:from --model flag )?is not available|model .*is not (?:enabled|supported)/i,
|
|
11730
11834
|
notEntitled: {
|
|
11731
11835
|
pattern: /access denied by policy|not authorized to use this copilot feature/i,
|
|
11732
11836
|
remedy: "this account's Copilot does not allow the Copilot CLI: on an organization seat, an owner must assign the seat and enable the Copilot CLI policy, then run `copilot login` again so the new seat is picked up"
|
|
@@ -13135,6 +13239,7 @@ var require_anthropic_api = __commonJS({
|
|
|
13135
13239
|
var keep_1 = require_dist2();
|
|
13136
13240
|
var env_ref_1 = require_env_ref();
|
|
13137
13241
|
var validate_output_1 = require_validate_output();
|
|
13242
|
+
var types_1 = require_types2();
|
|
13138
13243
|
var models_1 = require_models();
|
|
13139
13244
|
var DEFAULT_BASE_URL = "https://api.anthropic.com/v1/messages";
|
|
13140
13245
|
var DEFAULT_MODEL = "claude-sonnet-4-6";
|
|
@@ -13251,7 +13356,11 @@ var require_anthropic_api = __commonJS({
|
|
|
13251
13356
|
const apiErr = envelope?.error;
|
|
13252
13357
|
if (apiErr?.message) {
|
|
13253
13358
|
const kind = apiErr.type ? ` (${apiErr.type})` : "";
|
|
13254
|
-
|
|
13359
|
+
const message = `Anthropic API error${kind}: ${apiErr.message} [HTTP ${response.status}]`;
|
|
13360
|
+
if (response.status === 404 && apiErr.type === "not_found_error") {
|
|
13361
|
+
throw new types_1.ExecutorModelUnavailableError(message);
|
|
13362
|
+
}
|
|
13363
|
+
throw new Error(message);
|
|
13255
13364
|
}
|
|
13256
13365
|
throw new Error(`HTTP ${response.status}${bodyText ? `: ${bodyText}` : ""}`);
|
|
13257
13366
|
}
|
|
@@ -13832,10 +13941,11 @@ var require_scaffold = __commonJS({
|
|
|
13832
13941
|
function planScaffold2(brand, setupOptions, existing) {
|
|
13833
13942
|
const pools = Array.isArray(existing.pools) ? existing.pools : [];
|
|
13834
13943
|
const first = pools[0];
|
|
13835
|
-
const
|
|
13944
|
+
const pooled = first !== null && typeof first === "object" && typeof first.executor === "string" ? first.executor : void 0;
|
|
13945
|
+
const executors = existing.executors !== null && typeof existing.executors === "object" ? existing.executors : {};
|
|
13946
|
+
const prior = pooled ?? Object.keys(executors)[0];
|
|
13836
13947
|
const executor = setupOptions.executor ?? prior ?? brand.defaultExecutor;
|
|
13837
13948
|
const source = setupOptions.executor !== void 0 ? "flag" : prior !== void 0 ? "existing" : "default";
|
|
13838
|
-
const executors = existing.executors !== null && typeof existing.executors === "object" ? existing.executors : {};
|
|
13839
13949
|
const block = executor === void 0 ? void 0 : executors[executor];
|
|
13840
13950
|
const keptBlock = setupOptions.executor === void 0 && block !== null && typeof block === "object" ? block : void 0;
|
|
13841
13951
|
return { executor, source, keptBlock };
|
|
@@ -13910,7 +14020,7 @@ var require_checks = __commonJS({
|
|
|
13910
14020
|
}
|
|
13911
14021
|
function activeAgent(config) {
|
|
13912
14022
|
const configured = configuredExecutors(config);
|
|
13913
|
-
const pooled = config.pools.map((p) => p.executor).find((e) => AGENT_EXECUTORS2.includes(e) && configured.includes(e));
|
|
14023
|
+
const pooled = config.pools.map((p) => p.executor).find((e) => e !== void 0 && AGENT_EXECUTORS2.includes(e) && configured.includes(e));
|
|
13914
14024
|
return pooled ?? configured.find((e) => AGENT_EXECUTORS2.includes(e)) ?? null;
|
|
13915
14025
|
}
|
|
13916
14026
|
function agentSettings(config, subject) {
|
|
@@ -22240,6 +22350,8 @@ var require_subscribe = __commonJS({
|
|
|
22240
22350
|
return outcome;
|
|
22241
22351
|
}
|
|
22242
22352
|
var STOPPED = Symbol("stopped");
|
|
22353
|
+
var DECLINE_WINDOW = 25;
|
|
22354
|
+
var DECLINED_MEMORY = 1e3;
|
|
22243
22355
|
function subscribe(opts) {
|
|
22244
22356
|
const logger = opts.logger ?? NULL_LOGGER;
|
|
22245
22357
|
const pollIntervalMs = opts.pollIntervalMs ?? 2e3;
|
|
@@ -22257,6 +22369,16 @@ var require_subscribe = __commonJS({
|
|
|
22257
22369
|
let wakeStartup = null;
|
|
22258
22370
|
let unavailableSince = null;
|
|
22259
22371
|
let rateLimited = null;
|
|
22372
|
+
const accepts = opts.accepts;
|
|
22373
|
+
const declined = /* @__PURE__ */ new Set();
|
|
22374
|
+
function noteDeclined(jobId) {
|
|
22375
|
+
if (declined.has(jobId))
|
|
22376
|
+
return;
|
|
22377
|
+
if (declined.size >= DECLINED_MEMORY)
|
|
22378
|
+
declined.clear();
|
|
22379
|
+
declined.add(jobId);
|
|
22380
|
+
logger.debug?.("declined a job this subscriber cannot run; it stays queued for another member", { jobId });
|
|
22381
|
+
}
|
|
22260
22382
|
function noteReachable() {
|
|
22261
22383
|
if (unavailableSince !== null) {
|
|
22262
22384
|
logger.info(`Sift is reachable again after ${formatDuration(Date.now() - unavailableSince)}`);
|
|
@@ -22422,9 +22544,10 @@ var require_subscribe = __commonJS({
|
|
|
22422
22544
|
}
|
|
22423
22545
|
try {
|
|
22424
22546
|
const paused = holds.size > 0;
|
|
22547
|
+
const free = maxConcurrency - inflight;
|
|
22425
22548
|
const { data, directives } = await opts.jobsClient.listDispatchableJobs({
|
|
22426
22549
|
pools: resolvedPoolIds,
|
|
22427
|
-
limit: paused ? 1 :
|
|
22550
|
+
limit: paused ? 1 : accepts ? Math.max(free, DECLINE_WINDOW) : free,
|
|
22428
22551
|
sort: "priority:desc,queued_at:asc"
|
|
22429
22552
|
});
|
|
22430
22553
|
noteReachable();
|
|
@@ -22447,6 +22570,10 @@ var require_subscribe = __commonJS({
|
|
|
22447
22570
|
for (const job of data) {
|
|
22448
22571
|
if (inflight >= maxConcurrency)
|
|
22449
22572
|
break;
|
|
22573
|
+
if (accepts && !accepts(job)) {
|
|
22574
|
+
noteDeclined(job.id);
|
|
22575
|
+
continue;
|
|
22576
|
+
}
|
|
22450
22577
|
inflight++;
|
|
22451
22578
|
void runOnce(job).finally(() => {
|
|
22452
22579
|
inflight--;
|
|
@@ -22542,7 +22669,8 @@ var require_subscribe = __commonJS({
|
|
|
22542
22669
|
}
|
|
22543
22670
|
await opts.jobsClient.submit(dispatch.job.id, {
|
|
22544
22671
|
status: result.status,
|
|
22545
|
-
...result.reason !== void 0 ? { reason: result.reason } : {}
|
|
22672
|
+
...result.reason !== void 0 ? { reason: result.reason } : {},
|
|
22673
|
+
...result.status === "failed" && result.failureCode !== void 0 ? { failureCode: result.failureCode } : {}
|
|
22546
22674
|
});
|
|
22547
22675
|
} catch (err) {
|
|
22548
22676
|
if (isFatal(err)) {
|
|
@@ -22664,7 +22792,12 @@ var require_schema4 = __commonJS({
|
|
|
22664
22792
|
name: zod_1.z.string().optional(),
|
|
22665
22793
|
tags: zod_1.z.array(zod_1.z.string()).optional(),
|
|
22666
22794
|
minPriority: zod_1.z.number().int().optional(),
|
|
22667
|
-
|
|
22795
|
+
/**
|
|
22796
|
+
* Deprecated (whittlelabs ADR 0118): a Sifter chooses the executor for
|
|
22797
|
+
* each job from `executors`, in their order. A pool that still names one,
|
|
22798
|
+
* as configs before 0.34 did, tries it first for its own jobs.
|
|
22799
|
+
*/
|
|
22800
|
+
executor: zod_1.z.string().optional()
|
|
22668
22801
|
}).refine((pool) => pool.id !== void 0 || pool.name !== void 0, {
|
|
22669
22802
|
message: 'Each pool must specify at least one of "id" or "name"'
|
|
22670
22803
|
});
|
|
@@ -22704,6 +22837,11 @@ var require_schema4 = __commonJS({
|
|
|
22704
22837
|
concurrency: zod_1.z.object({
|
|
22705
22838
|
maxJobs: zod_1.z.number().int().positive().default(defaults_1.DEFAULTS.concurrency.maxJobs)
|
|
22706
22839
|
}).default(defaults_1.DEFAULTS.concurrency),
|
|
22840
|
+
/**
|
|
22841
|
+
* The executors this runner may run jobs on, keyed by id. The order they
|
|
22842
|
+
* are written in is the order a job tries them (ADR 0118): a job that
|
|
22843
|
+
* requires none runs on the first that can run jobs on this machine.
|
|
22844
|
+
*/
|
|
22707
22845
|
executors: zod_1.z.record(zod_1.z.string(), executorSchema),
|
|
22708
22846
|
logging: zod_1.z.object({
|
|
22709
22847
|
level: zod_1.z.enum(["debug", "info", "warn", "error"]).default(defaults_1.DEFAULTS.logging.level),
|
|
@@ -22719,6 +22857,7 @@ var require_loader = __commonJS({
|
|
|
22719
22857
|
"../../packages/shuttle/dist/config/loader.js"(exports2) {
|
|
22720
22858
|
"use strict";
|
|
22721
22859
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
22860
|
+
exports2.resolveConfigPath = resolveConfigPath;
|
|
22722
22861
|
exports2.loadConfig = loadConfig;
|
|
22723
22862
|
var fs_1 = require("fs");
|
|
22724
22863
|
var path_1 = require("path");
|
|
@@ -25994,174 +26133,425 @@ var require_chain = __commonJS({
|
|
|
25994
26133
|
}
|
|
25995
26134
|
});
|
|
25996
26135
|
|
|
25997
|
-
// ../../packages/shuttle/dist/
|
|
25998
|
-
var
|
|
25999
|
-
"../../packages/shuttle/dist/
|
|
26136
|
+
// ../../packages/shuttle/dist/executors/output-gates.js
|
|
26137
|
+
var require_output_gates = __commonJS({
|
|
26138
|
+
"../../packages/shuttle/dist/executors/output-gates.js"(exports2) {
|
|
26000
26139
|
"use strict";
|
|
26001
|
-
var __importDefault = exports2 && exports2.__importDefault || function(mod) {
|
|
26002
|
-
return mod && mod.__esModule ? mod : { "default": mod };
|
|
26003
|
-
};
|
|
26004
26140
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
26005
|
-
exports2.
|
|
26006
|
-
exports2.
|
|
26007
|
-
|
|
26008
|
-
|
|
26009
|
-
|
|
26010
|
-
var
|
|
26011
|
-
var
|
|
26012
|
-
var
|
|
26013
|
-
|
|
26014
|
-
|
|
26015
|
-
|
|
26016
|
-
|
|
26017
|
-
|
|
26018
|
-
|
|
26019
|
-
|
|
26020
|
-
|
|
26021
|
-
|
|
26022
|
-
|
|
26023
|
-
|
|
26024
|
-
const
|
|
26025
|
-
|
|
26026
|
-
|
|
26027
|
-
|
|
26028
|
-
|
|
26029
|
-
|
|
26030
|
-
const
|
|
26031
|
-
|
|
26032
|
-
|
|
26033
|
-
|
|
26034
|
-
|
|
26035
|
-
|
|
26036
|
-
|
|
26037
|
-
}
|
|
26038
|
-
}
|
|
26039
|
-
const authEnv = gitToken !== null ? buildGitAuthEnv([primary.remote, ...contextPlan.materialize.map((c) => c.git.remote)], gitToken) : void 0;
|
|
26040
|
-
const git = (args, cwd) => runGit(args, cwd, { timeoutMs, signal, allowedProtocols, extraEnv: authEnv });
|
|
26041
|
-
const primaryResult = await materializeCommit(primary, primaryDir, git);
|
|
26042
|
-
if (!primaryResult.ok) {
|
|
26043
|
-
await fs_1.promises.rm(primaryDir, { recursive: true, force: true }).catch(() => {
|
|
26044
|
-
});
|
|
26045
|
-
await fs_1.promises.mkdir(primaryDir).catch(() => {
|
|
26046
|
-
});
|
|
26047
|
-
return { materialized: false, warning: primaryResult.warning, context: [] };
|
|
26048
|
-
}
|
|
26049
|
-
const context = [];
|
|
26050
|
-
for (const planned of contextPlan.skip) {
|
|
26051
|
-
context.push({ ...planned, materialized: false });
|
|
26141
|
+
exports2.isSanctionedPaint = isSanctionedPaint;
|
|
26142
|
+
exports2.unsanctionedPaints = unsanctionedPaints;
|
|
26143
|
+
exports2.resolvePath = resolvePath;
|
|
26144
|
+
exports2.evaluateOutputGates = evaluateOutputGates;
|
|
26145
|
+
exports2.renderRepairPrompt = renderRepairPrompt;
|
|
26146
|
+
var INPUT_REF = "input:";
|
|
26147
|
+
var COLOR_BEARING = ["fill", "stroke", "color", "stop-color", "flood-color", "lighting-color"];
|
|
26148
|
+
var INERT = /* @__PURE__ */ new Set(["none", "inherit", "initial", "unset", "transparent", "currentcolor"]);
|
|
26149
|
+
function isSanctionedPaint(raw) {
|
|
26150
|
+
const value = raw.trim().toLowerCase();
|
|
26151
|
+
if (value === "")
|
|
26152
|
+
return true;
|
|
26153
|
+
if (INERT.has(value))
|
|
26154
|
+
return true;
|
|
26155
|
+
if (/^url\(\s*['"]?#[^)'"]+['"]?\s*\)$/.test(value))
|
|
26156
|
+
return true;
|
|
26157
|
+
const varMatch = /^var\(\s*(--[a-z0-9-]+)\s*(?:,([\s\S]*))?\)$/.exec(value);
|
|
26158
|
+
if (!varMatch)
|
|
26159
|
+
return false;
|
|
26160
|
+
const [, name, fallback] = varMatch;
|
|
26161
|
+
if (!name.startsWith("--color-"))
|
|
26162
|
+
return false;
|
|
26163
|
+
return fallback === void 0 || isSanctionedPaint(fallback);
|
|
26164
|
+
}
|
|
26165
|
+
function unsanctionedPaints(source) {
|
|
26166
|
+
const found = [];
|
|
26167
|
+
const attrs = COLOR_BEARING.join("|");
|
|
26168
|
+
const attribute = new RegExp(`\\b(?:${attrs})\\s*=\\s*(['"])([\\s\\S]*?)\\1`, "gi");
|
|
26169
|
+
const declaration = new RegExp(`\\b(?:${attrs})\\s*:\\s*([^;"'}\\n]+)`, "gi");
|
|
26170
|
+
for (const [, , value] of source.matchAll(attribute)) {
|
|
26171
|
+
if (!isSanctionedPaint(value))
|
|
26172
|
+
found.push(value.trim());
|
|
26052
26173
|
}
|
|
26053
|
-
|
|
26054
|
-
|
|
26055
|
-
|
|
26056
|
-
for (const entry of contextPlan.materialize) {
|
|
26057
|
-
const dir = path_1.default.join(contextRoot, entry.name);
|
|
26058
|
-
await fs_1.promises.mkdir(dir);
|
|
26059
|
-
const result = await materializeCommit(entry.git, dir, git);
|
|
26060
|
-
context.push({
|
|
26061
|
-
name: entry.name,
|
|
26062
|
-
requestedName: entry.requestedName,
|
|
26063
|
-
materialized: result.ok,
|
|
26064
|
-
...result.ok ? {} : { warning: result.warning }
|
|
26065
|
-
});
|
|
26066
|
-
}
|
|
26174
|
+
for (const [, value] of source.matchAll(declaration)) {
|
|
26175
|
+
if (!isSanctionedPaint(value))
|
|
26176
|
+
found.push(value.trim());
|
|
26067
26177
|
}
|
|
26068
|
-
|
|
26069
|
-
return { materialized: true, primaryDir, context };
|
|
26178
|
+
return found;
|
|
26070
26179
|
}
|
|
26071
|
-
function
|
|
26072
|
-
|
|
26073
|
-
|
|
26074
|
-
|
|
26075
|
-
|
|
26076
|
-
|
|
26077
|
-
|
|
26078
|
-
|
|
26079
|
-
|
|
26080
|
-
plan.order.set(requestedName, index);
|
|
26081
|
-
const resolved = readContextRepo(entry, index);
|
|
26082
|
-
if ("warning" in resolved) {
|
|
26083
|
-
plan.skip.push({ name: sanitizeMountName(requestedName, usedNames), requestedName, warning: resolved.warning });
|
|
26084
|
-
return;
|
|
26085
|
-
}
|
|
26086
|
-
if (plan.materialize.length >= maxContext) {
|
|
26087
|
-
plan.skip.push({
|
|
26088
|
-
name: sanitizeMountName(requestedName, usedNames),
|
|
26089
|
-
requestedName,
|
|
26090
|
-
warning: `skipped: exceeds the ${maxContext}-context-repo cap`
|
|
26091
|
-
});
|
|
26092
|
-
return;
|
|
26180
|
+
function resolvePath(root, path) {
|
|
26181
|
+
let ctx = root;
|
|
26182
|
+
for (const seg of path.split(".")) {
|
|
26183
|
+
const project = seg.endsWith("[*]");
|
|
26184
|
+
const key = project ? seg.slice(0, -3) : seg;
|
|
26185
|
+
if (Array.isArray(ctx)) {
|
|
26186
|
+
ctx = ctx.map((el) => key ? el?.[key] : el);
|
|
26187
|
+
} else {
|
|
26188
|
+
ctx = key ? ctx?.[key] : ctx;
|
|
26093
26189
|
}
|
|
26094
|
-
|
|
26095
|
-
|
|
26096
|
-
name: sanitizeMountName(requestedName, usedNames),
|
|
26097
|
-
requestedName
|
|
26098
|
-
});
|
|
26099
|
-
});
|
|
26100
|
-
return plan;
|
|
26101
|
-
}
|
|
26102
|
-
function contextOrder(plan, requestedName) {
|
|
26103
|
-
return plan.order.get(requestedName) ?? Number.MAX_SAFE_INTEGER;
|
|
26104
|
-
}
|
|
26105
|
-
async function materializeCommit(gitWorkspace, dir, git) {
|
|
26106
|
-
const hasCommit = () => git(["cat-file", "-e", `${gitWorkspace.commit}^{commit}`], dir).then((r) => r.code === 0);
|
|
26107
|
-
const init = await git(["init", "-q"], dir);
|
|
26108
|
-
if (init.code !== 0)
|
|
26109
|
-
return { ok: false, warning: `git init failed: ${firstLine(init.stderr)}` };
|
|
26110
|
-
const attempts = [];
|
|
26111
|
-
for (const ref of gitWorkspace.fetchRefs ?? []) {
|
|
26112
|
-
attempts.push({
|
|
26113
|
-
source: `${gitWorkspace.remote} ${ref}`,
|
|
26114
|
-
args: ["fetch", "--no-tags", "--depth=1", gitWorkspace.remote, ref]
|
|
26115
|
-
});
|
|
26116
|
-
}
|
|
26117
|
-
attempts.push({
|
|
26118
|
-
source: `${gitWorkspace.remote} commit`,
|
|
26119
|
-
args: ["fetch", "--no-tags", "--depth=1", gitWorkspace.remote, gitWorkspace.commit]
|
|
26120
|
-
});
|
|
26121
|
-
const failures = [];
|
|
26122
|
-
let present = await hasCommit();
|
|
26123
|
-
for (const { source, args } of attempts) {
|
|
26124
|
-
if (present)
|
|
26125
|
-
break;
|
|
26126
|
-
const result = await git(args, dir);
|
|
26127
|
-
if (result.code !== 0) {
|
|
26128
|
-
failures.push(`${source}: ${firstLine(result.stderr)}`);
|
|
26129
|
-
continue;
|
|
26190
|
+
if (project && !Array.isArray(ctx)) {
|
|
26191
|
+
ctx = ctx == null ? [] : [ctx];
|
|
26130
26192
|
}
|
|
26131
|
-
present = await hasCommit();
|
|
26132
|
-
if (!present)
|
|
26133
|
-
failures.push(`${source}: fetch succeeded but ${gitWorkspace.commit} is still absent`);
|
|
26134
|
-
}
|
|
26135
|
-
if (!present) {
|
|
26136
|
-
return {
|
|
26137
|
-
ok: false,
|
|
26138
|
-
warning: `could not materialize ${gitWorkspace.commit} from ${gitWorkspace.remote}` + (failures.length > 0 ? ` (${failures.join("; ")})` : "")
|
|
26139
|
-
};
|
|
26140
26193
|
}
|
|
26141
|
-
|
|
26142
|
-
if (checkout.code !== 0)
|
|
26143
|
-
return { ok: false, warning: `git checkout failed: ${firstLine(checkout.stderr)}` };
|
|
26144
|
-
return { ok: true };
|
|
26194
|
+
return ctx;
|
|
26145
26195
|
}
|
|
26146
|
-
function
|
|
26147
|
-
|
|
26148
|
-
|
|
26149
|
-
|
|
26150
|
-
|
|
26151
|
-
|
|
26152
|
-
|
|
26153
|
-
const origin = `${url.protocol}//${url.host}/`;
|
|
26154
|
-
if (!origins.includes(origin))
|
|
26155
|
-
origins.push(origin);
|
|
26156
|
-
} catch {
|
|
26157
|
-
continue;
|
|
26158
|
-
}
|
|
26196
|
+
function resolveRef(ref, output, inputs) {
|
|
26197
|
+
if (ref.startsWith(INPUT_REF)) {
|
|
26198
|
+
const label = ref.slice(INPUT_REF.length);
|
|
26199
|
+
const row = inputs.find((i) => i.label === label) ?? inputs.find((i) => i.label === "artifacts" && i.payload.label === label);
|
|
26200
|
+
if (!row)
|
|
26201
|
+
return void 0;
|
|
26202
|
+
return Object.prototype.hasOwnProperty.call(row.payload, "value") ? row.payload.value : row.payload;
|
|
26159
26203
|
}
|
|
26160
|
-
|
|
26161
|
-
|
|
26162
|
-
|
|
26163
|
-
|
|
26164
|
-
|
|
26204
|
+
return resolvePath(output, ref);
|
|
26205
|
+
}
|
|
26206
|
+
function asStrings(value) {
|
|
26207
|
+
if (Array.isArray(value))
|
|
26208
|
+
return value.map((v) => String(v));
|
|
26209
|
+
if (value == null)
|
|
26210
|
+
return [];
|
|
26211
|
+
return [String(value)];
|
|
26212
|
+
}
|
|
26213
|
+
var PRIMITIVES = {
|
|
26214
|
+
/**
|
|
26215
|
+
* `coverage` — the values at `got` must exactly cover the set at `want`:
|
|
26216
|
+
* every wanted value present, nothing invented, none repeated. Params:
|
|
26217
|
+
* `{ got: <output path>, want: <ref>, subject?: <noun> }`.
|
|
26218
|
+
*/
|
|
26219
|
+
coverage(params, output, inputs) {
|
|
26220
|
+
const subject = typeof params.subject === "string" ? params.subject : "item";
|
|
26221
|
+
const got = asStrings(resolveRef(String(params.got), output, inputs));
|
|
26222
|
+
const want = asStrings(resolveRef(String(params.want), output, inputs));
|
|
26223
|
+
const gotSet = new Set(got);
|
|
26224
|
+
const wantSet = new Set(want);
|
|
26225
|
+
const missing = want.filter((v) => !gotSet.has(v));
|
|
26226
|
+
const unknown = [...new Set(got.filter((v) => !wantSet.has(v)))];
|
|
26227
|
+
const seen = /* @__PURE__ */ new Set();
|
|
26228
|
+
const duplicated = [];
|
|
26229
|
+
for (const v of got) {
|
|
26230
|
+
if (seen.has(v))
|
|
26231
|
+
duplicated.push(v);
|
|
26232
|
+
else
|
|
26233
|
+
seen.add(v);
|
|
26234
|
+
}
|
|
26235
|
+
if (missing.length === 0 && unknown.length === 0 && duplicated.length === 0)
|
|
26236
|
+
return [];
|
|
26237
|
+
const parts = [];
|
|
26238
|
+
if (missing.length)
|
|
26239
|
+
parts.push(`missing ${subject}(s): [${missing.join(", ")}]`);
|
|
26240
|
+
if (unknown.length)
|
|
26241
|
+
parts.push(`not a known ${subject}: [${unknown.join(", ")}]`);
|
|
26242
|
+
if (duplicated.length)
|
|
26243
|
+
parts.push(`assessed more than once: [${[...new Set(duplicated)].join(", ")}]`);
|
|
26244
|
+
return [
|
|
26245
|
+
`every ${subject} must be covered exactly once \u2014 ${parts.join("; ")}. Return one entry per ${subject}, using its exact id.`
|
|
26246
|
+
];
|
|
26247
|
+
},
|
|
26248
|
+
/**
|
|
26249
|
+
* `non_empty_when` — the array at `path` must be non-empty, optionally only
|
|
26250
|
+
* when `when.path` equals `when.equals`. Params:
|
|
26251
|
+
* `{ path: <output path>, when?: { path: <output path>, equals: <value> } }`.
|
|
26252
|
+
*/
|
|
26253
|
+
non_empty_when(params, output) {
|
|
26254
|
+
const when = params.when;
|
|
26255
|
+
if (when && typeof when.path === "string") {
|
|
26256
|
+
if (resolvePath(output, when.path) !== when.equals)
|
|
26257
|
+
return [];
|
|
26258
|
+
}
|
|
26259
|
+
const path = String(params.path);
|
|
26260
|
+
const value = resolvePath(output, path);
|
|
26261
|
+
if (Array.isArray(value) && value.length > 0)
|
|
26262
|
+
return [];
|
|
26263
|
+
const cond = when && typeof when.path === "string" ? ` when ${when.path} is ${JSON.stringify(when.equals)}` : "";
|
|
26264
|
+
return [
|
|
26265
|
+
`'${path}' must be a non-empty array${cond}; it was ${Array.isArray(value) ? "empty" : "absent"}.`
|
|
26266
|
+
];
|
|
26267
|
+
},
|
|
26268
|
+
/**
|
|
26269
|
+
* `bounded_palette` — every colour in the sources at `path` must be named
|
|
26270
|
+
* by role rather than written as a value. Params:
|
|
26271
|
+
* `{ path: <output path>, roles?: <role names for the repair turn> }`.
|
|
26272
|
+
*
|
|
26273
|
+
* A drawing the model authors is markup the house did not write, and a
|
|
26274
|
+
* literal in it is a colour outside the consuming palette: unproved
|
|
26275
|
+
* against the colours beside it, unchecked for contrast on the ground it
|
|
26276
|
+
* lands on, and fixed to one theme. The consumer strips such a paint at
|
|
26277
|
+
* render, so an artifact that carries one silently loses it. Catching it
|
|
26278
|
+
* HERE is what makes that a repair the model can make while it still has
|
|
26279
|
+
* the drawing in hand, instead of a defect nobody sees until the picture
|
|
26280
|
+
* comes out plain.
|
|
26281
|
+
*/
|
|
26282
|
+
bounded_palette(params, output) {
|
|
26283
|
+
const path = String(params.path);
|
|
26284
|
+
const value = resolvePath(output, path);
|
|
26285
|
+
const sources = (Array.isArray(value) ? value : [value]).filter((v) => typeof v === "string" && v.length > 0);
|
|
26286
|
+
const offenders = [...new Set(sources.flatMap(unsanctionedPaints))];
|
|
26287
|
+
if (offenders.length === 0)
|
|
26288
|
+
return [];
|
|
26289
|
+
const roles = Array.isArray(params.roles) ? params.roles.map(String) : [];
|
|
26290
|
+
const vocabulary = roles.length > 0 ? ` Use one of: ${roles.join(", ")}.` : "";
|
|
26291
|
+
return [
|
|
26292
|
+
`'${path}' states ${offenders.length} colour value${offenders.length === 1 ? "" : "s"} directly (${offenders.slice(0, 8).join(", ")}${offenders.length > 8 ? ", \u2026" : ""}). Every colour must be named by role \u2014 var(--color-\u2026), currentColor, or none \u2014 never as a hex, rgb(), hsl() or colour name, because a value cannot adapt to the reader's theme and was never checked against the colours beside it.${vocabulary} Redraw with roles and return the whole output again.`
|
|
26293
|
+
];
|
|
26294
|
+
}
|
|
26295
|
+
};
|
|
26296
|
+
function evaluateOutputGates(gates, output, inputs) {
|
|
26297
|
+
const findings = [];
|
|
26298
|
+
for (const gate of gates) {
|
|
26299
|
+
const primitive = PRIMITIVES[gate.primitive];
|
|
26300
|
+
if (!primitive) {
|
|
26301
|
+
findings.push({ gate: gate.name, message: `unknown gate primitive '${gate.primitive}'` });
|
|
26302
|
+
continue;
|
|
26303
|
+
}
|
|
26304
|
+
for (const message of primitive(gate.params, output, inputs)) {
|
|
26305
|
+
findings.push({ gate: gate.name, message });
|
|
26306
|
+
}
|
|
26307
|
+
}
|
|
26308
|
+
return { ok: findings.length === 0, findings };
|
|
26309
|
+
}
|
|
26310
|
+
function renderRepairPrompt(findings) {
|
|
26311
|
+
return [
|
|
26312
|
+
"Your previous answer did not satisfy these output checks. Return the corrected, complete answer that resolves every item below. Produce the same output shape with the problems fixed, and nothing else \u2014 no commentary, no explanation of the changes.",
|
|
26313
|
+
"",
|
|
26314
|
+
...findings.map((f) => `- [${f.gate}] ${f.message}`)
|
|
26315
|
+
].join("\n");
|
|
26316
|
+
}
|
|
26317
|
+
}
|
|
26318
|
+
});
|
|
26319
|
+
|
|
26320
|
+
// ../../packages/shuttle/dist/logging/logger.js
|
|
26321
|
+
var require_logger = __commonJS({
|
|
26322
|
+
"../../packages/shuttle/dist/logging/logger.js"(exports2) {
|
|
26323
|
+
"use strict";
|
|
26324
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
26325
|
+
exports2.createLogger = createLogger;
|
|
26326
|
+
exports2.setGlobalLogger = setGlobalLogger;
|
|
26327
|
+
exports2.getLogger = getLogger;
|
|
26328
|
+
var LEVEL_ORDER = {
|
|
26329
|
+
debug: 0,
|
|
26330
|
+
info: 1,
|
|
26331
|
+
warn: 2,
|
|
26332
|
+
error: 3
|
|
26333
|
+
};
|
|
26334
|
+
function formatContext(context) {
|
|
26335
|
+
return Object.entries(context).map(([k, v]) => `${k}=${typeof v === "string" ? v : JSON.stringify(v)}`).join(" ");
|
|
26336
|
+
}
|
|
26337
|
+
function formatPretty(level, message, context) {
|
|
26338
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
26339
|
+
const tag = level.toUpperCase().padEnd(5);
|
|
26340
|
+
const base = `[${timestamp}] ${tag} ${message}`;
|
|
26341
|
+
if (context && Object.keys(context).length > 0) {
|
|
26342
|
+
return `${base} ${formatContext(context)}`;
|
|
26343
|
+
}
|
|
26344
|
+
return base;
|
|
26345
|
+
}
|
|
26346
|
+
function formatJson(level, message, context) {
|
|
26347
|
+
const entry = {
|
|
26348
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
26349
|
+
level,
|
|
26350
|
+
message,
|
|
26351
|
+
...context
|
|
26352
|
+
};
|
|
26353
|
+
return JSON.stringify(entry);
|
|
26354
|
+
}
|
|
26355
|
+
function createLogger(options) {
|
|
26356
|
+
const threshold = LEVEL_ORDER[options.level];
|
|
26357
|
+
const format = options.format === "json" ? formatJson : formatPretty;
|
|
26358
|
+
function emit(level, message, context) {
|
|
26359
|
+
if (LEVEL_ORDER[level] < threshold)
|
|
26360
|
+
return;
|
|
26361
|
+
const line = format(level, message, context);
|
|
26362
|
+
if (level === "error") {
|
|
26363
|
+
console.error(line);
|
|
26364
|
+
} else if (level === "warn") {
|
|
26365
|
+
console.warn(line);
|
|
26366
|
+
} else {
|
|
26367
|
+
console.log(line);
|
|
26368
|
+
}
|
|
26369
|
+
}
|
|
26370
|
+
return {
|
|
26371
|
+
debug: (message, context) => emit("debug", message, context),
|
|
26372
|
+
info: (message, context) => emit("info", message, context),
|
|
26373
|
+
warn: (message, context) => emit("warn", message, context),
|
|
26374
|
+
error: (message, context) => emit("error", message, context)
|
|
26375
|
+
};
|
|
26376
|
+
}
|
|
26377
|
+
var globalLogger = createLogger({ level: "info", format: "pretty" });
|
|
26378
|
+
function setGlobalLogger(logger) {
|
|
26379
|
+
globalLogger = logger;
|
|
26380
|
+
}
|
|
26381
|
+
function getLogger() {
|
|
26382
|
+
return globalLogger;
|
|
26383
|
+
}
|
|
26384
|
+
}
|
|
26385
|
+
});
|
|
26386
|
+
|
|
26387
|
+
// ../../packages/shuttle/dist/workspace/git.js
|
|
26388
|
+
var require_git = __commonJS({
|
|
26389
|
+
"../../packages/shuttle/dist/workspace/git.js"(exports2) {
|
|
26390
|
+
"use strict";
|
|
26391
|
+
var __importDefault = exports2 && exports2.__importDefault || function(mod) {
|
|
26392
|
+
return mod && mod.__esModule ? mod : { "default": mod };
|
|
26393
|
+
};
|
|
26394
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
26395
|
+
exports2.gitMaterializer = void 0;
|
|
26396
|
+
exports2.buildGitAuthEnv = buildGitAuthEnv;
|
|
26397
|
+
var child_process_1 = require("child_process");
|
|
26398
|
+
var fs_1 = require("fs");
|
|
26399
|
+
var path_1 = __importDefault(require("path"));
|
|
26400
|
+
var DEFAULT_GIT_TIMEOUT_MS = 12e4;
|
|
26401
|
+
var DEFAULT_GIT_PROTOCOLS = "https:ssh:git";
|
|
26402
|
+
var DEFAULT_MAX_CONTEXT_REPOS = 5;
|
|
26403
|
+
exports2.gitMaterializer = {
|
|
26404
|
+
namespace: "git",
|
|
26405
|
+
materialize: materializeGit
|
|
26406
|
+
};
|
|
26407
|
+
async function materializeGit(request, runRoot, options) {
|
|
26408
|
+
const resolvedPrimary = readGitWorkspace(request);
|
|
26409
|
+
const primaryDir = path_1.default.join(runRoot, "primary");
|
|
26410
|
+
await fs_1.promises.mkdir(primaryDir, { recursive: true });
|
|
26411
|
+
if ("warning" in resolvedPrimary) {
|
|
26412
|
+
return { materialized: false, warning: resolvedPrimary.warning, context: [] };
|
|
26413
|
+
}
|
|
26414
|
+
const primary = resolvedPrimary.git;
|
|
26415
|
+
const timeoutMs = options.commandTimeoutMs ?? DEFAULT_GIT_TIMEOUT_MS;
|
|
26416
|
+
const allowedProtocols = options.allowedProtocols ?? DEFAULT_GIT_PROTOCOLS;
|
|
26417
|
+
const signal = options.signal;
|
|
26418
|
+
const maxContext = options.maxContextRepos ?? DEFAULT_MAX_CONTEXT_REPOS;
|
|
26419
|
+
const contextPlan = planContextRepos(primary.context, maxContext);
|
|
26420
|
+
const ref = primary.fetchCredential;
|
|
26421
|
+
let gitToken = null;
|
|
26422
|
+
if (ref && typeof ref.name === "string" && typeof ref.principal === "string" && options.credentials) {
|
|
26423
|
+
try {
|
|
26424
|
+
gitToken = await options.credentials.reveal(ref);
|
|
26425
|
+
} catch {
|
|
26426
|
+
gitToken = null;
|
|
26427
|
+
}
|
|
26428
|
+
}
|
|
26429
|
+
const authEnv = gitToken !== null ? buildGitAuthEnv([primary.remote, ...contextPlan.materialize.map((c) => c.git.remote)], gitToken) : void 0;
|
|
26430
|
+
const git = (args, cwd) => runGit(args, cwd, { timeoutMs, signal, allowedProtocols, extraEnv: authEnv });
|
|
26431
|
+
const primaryResult = await materializeCommit(primary, primaryDir, git);
|
|
26432
|
+
if (!primaryResult.ok) {
|
|
26433
|
+
await fs_1.promises.rm(primaryDir, { recursive: true, force: true }).catch(() => {
|
|
26434
|
+
});
|
|
26435
|
+
await fs_1.promises.mkdir(primaryDir).catch(() => {
|
|
26436
|
+
});
|
|
26437
|
+
return { materialized: false, warning: primaryResult.warning, context: [] };
|
|
26438
|
+
}
|
|
26439
|
+
const context = [];
|
|
26440
|
+
for (const planned of contextPlan.skip) {
|
|
26441
|
+
context.push({ ...planned, materialized: false });
|
|
26442
|
+
}
|
|
26443
|
+
if (contextPlan.materialize.length > 0) {
|
|
26444
|
+
const contextRoot = path_1.default.join(runRoot, "context");
|
|
26445
|
+
await fs_1.promises.mkdir(contextRoot, { recursive: true });
|
|
26446
|
+
for (const entry of contextPlan.materialize) {
|
|
26447
|
+
const dir = path_1.default.join(contextRoot, entry.name);
|
|
26448
|
+
await fs_1.promises.mkdir(dir);
|
|
26449
|
+
const result = await materializeCommit(entry.git, dir, git);
|
|
26450
|
+
context.push({
|
|
26451
|
+
name: entry.name,
|
|
26452
|
+
requestedName: entry.requestedName,
|
|
26453
|
+
materialized: result.ok,
|
|
26454
|
+
...result.ok ? {} : { warning: result.warning }
|
|
26455
|
+
});
|
|
26456
|
+
}
|
|
26457
|
+
}
|
|
26458
|
+
context.sort((a, b) => contextOrder(contextPlan, a.requestedName) - contextOrder(contextPlan, b.requestedName));
|
|
26459
|
+
return { materialized: true, primaryDir, context };
|
|
26460
|
+
}
|
|
26461
|
+
function planContextRepos(raw, maxContext) {
|
|
26462
|
+
const plan = { materialize: [], skip: [], order: /* @__PURE__ */ new Map() };
|
|
26463
|
+
if (raw === void 0)
|
|
26464
|
+
return plan;
|
|
26465
|
+
if (!Array.isArray(raw))
|
|
26466
|
+
return plan;
|
|
26467
|
+
const usedNames = /* @__PURE__ */ new Set();
|
|
26468
|
+
raw.forEach((entry, index) => {
|
|
26469
|
+
const requestedName = entry && typeof entry.name === "string" ? entry.name : `context-${index}`;
|
|
26470
|
+
plan.order.set(requestedName, index);
|
|
26471
|
+
const resolved = readContextRepo(entry, index);
|
|
26472
|
+
if ("warning" in resolved) {
|
|
26473
|
+
plan.skip.push({ name: sanitizeMountName(requestedName, usedNames), requestedName, warning: resolved.warning });
|
|
26474
|
+
return;
|
|
26475
|
+
}
|
|
26476
|
+
if (plan.materialize.length >= maxContext) {
|
|
26477
|
+
plan.skip.push({
|
|
26478
|
+
name: sanitizeMountName(requestedName, usedNames),
|
|
26479
|
+
requestedName,
|
|
26480
|
+
warning: `skipped: exceeds the ${maxContext}-context-repo cap`
|
|
26481
|
+
});
|
|
26482
|
+
return;
|
|
26483
|
+
}
|
|
26484
|
+
plan.materialize.push({
|
|
26485
|
+
git: resolved.git,
|
|
26486
|
+
name: sanitizeMountName(requestedName, usedNames),
|
|
26487
|
+
requestedName
|
|
26488
|
+
});
|
|
26489
|
+
});
|
|
26490
|
+
return plan;
|
|
26491
|
+
}
|
|
26492
|
+
function contextOrder(plan, requestedName) {
|
|
26493
|
+
return plan.order.get(requestedName) ?? Number.MAX_SAFE_INTEGER;
|
|
26494
|
+
}
|
|
26495
|
+
async function materializeCommit(gitWorkspace, dir, git) {
|
|
26496
|
+
const hasCommit = () => git(["cat-file", "-e", `${gitWorkspace.commit}^{commit}`], dir).then((r) => r.code === 0);
|
|
26497
|
+
const init = await git(["init", "-q"], dir);
|
|
26498
|
+
if (init.code !== 0)
|
|
26499
|
+
return { ok: false, warning: `git init failed: ${firstLine(init.stderr)}` };
|
|
26500
|
+
const attempts = [];
|
|
26501
|
+
for (const ref of gitWorkspace.fetchRefs ?? []) {
|
|
26502
|
+
attempts.push({
|
|
26503
|
+
source: `${gitWorkspace.remote} ${ref}`,
|
|
26504
|
+
args: ["fetch", "--no-tags", "--depth=1", gitWorkspace.remote, ref]
|
|
26505
|
+
});
|
|
26506
|
+
}
|
|
26507
|
+
attempts.push({
|
|
26508
|
+
source: `${gitWorkspace.remote} commit`,
|
|
26509
|
+
args: ["fetch", "--no-tags", "--depth=1", gitWorkspace.remote, gitWorkspace.commit]
|
|
26510
|
+
});
|
|
26511
|
+
const failures = [];
|
|
26512
|
+
let present = await hasCommit();
|
|
26513
|
+
for (const { source, args } of attempts) {
|
|
26514
|
+
if (present)
|
|
26515
|
+
break;
|
|
26516
|
+
const result = await git(args, dir);
|
|
26517
|
+
if (result.code !== 0) {
|
|
26518
|
+
failures.push(`${source}: ${firstLine(result.stderr)}`);
|
|
26519
|
+
continue;
|
|
26520
|
+
}
|
|
26521
|
+
present = await hasCommit();
|
|
26522
|
+
if (!present)
|
|
26523
|
+
failures.push(`${source}: fetch succeeded but ${gitWorkspace.commit} is still absent`);
|
|
26524
|
+
}
|
|
26525
|
+
if (!present) {
|
|
26526
|
+
return {
|
|
26527
|
+
ok: false,
|
|
26528
|
+
warning: `could not materialize ${gitWorkspace.commit} from ${gitWorkspace.remote}` + (failures.length > 0 ? ` (${failures.join("; ")})` : "")
|
|
26529
|
+
};
|
|
26530
|
+
}
|
|
26531
|
+
const checkout = await git(["checkout", "--detach", gitWorkspace.commit], dir);
|
|
26532
|
+
if (checkout.code !== 0)
|
|
26533
|
+
return { ok: false, warning: `git checkout failed: ${firstLine(checkout.stderr)}` };
|
|
26534
|
+
return { ok: true };
|
|
26535
|
+
}
|
|
26536
|
+
function buildGitAuthEnv(remotes, token) {
|
|
26537
|
+
const origins = [];
|
|
26538
|
+
for (const remote of remotes) {
|
|
26539
|
+
try {
|
|
26540
|
+
const url = new URL(remote);
|
|
26541
|
+
if (url.protocol !== "https:")
|
|
26542
|
+
continue;
|
|
26543
|
+
const origin = `${url.protocol}//${url.host}/`;
|
|
26544
|
+
if (!origins.includes(origin))
|
|
26545
|
+
origins.push(origin);
|
|
26546
|
+
} catch {
|
|
26547
|
+
continue;
|
|
26548
|
+
}
|
|
26549
|
+
}
|
|
26550
|
+
if (origins.length === 0)
|
|
26551
|
+
return void 0;
|
|
26552
|
+
const basic = Buffer.from(`x-access-token:${token}`).toString("base64");
|
|
26553
|
+
const env = { GIT_CONFIG_COUNT: String(origins.length) };
|
|
26554
|
+
origins.forEach((origin, i) => {
|
|
26165
26555
|
env[`GIT_CONFIG_KEY_${i}`] = `http.${origin}.extraheader`;
|
|
26166
26556
|
env[`GIT_CONFIG_VALUE_${i}`] = `Authorization: Basic ${basic}`;
|
|
26167
26557
|
});
|
|
@@ -26500,6 +26890,130 @@ var require_workspace = __commonJS({
|
|
|
26500
26890
|
}
|
|
26501
26891
|
});
|
|
26502
26892
|
|
|
26893
|
+
// ../../packages/shuttle/dist/core/run-dispatch.js
|
|
26894
|
+
var require_run_dispatch = __commonJS({
|
|
26895
|
+
"../../packages/shuttle/dist/core/run-dispatch.js"(exports2) {
|
|
26896
|
+
"use strict";
|
|
26897
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
26898
|
+
exports2.GATE_REPAIR_BUDGET = void 0;
|
|
26899
|
+
exports2.runDispatch = runDispatch;
|
|
26900
|
+
exports2.runOutputGates = runOutputGates;
|
|
26901
|
+
exports2.mergeRepairedResponse = mergeRepairedResponse;
|
|
26902
|
+
var loom_1 = require_dist();
|
|
26903
|
+
var output_gates_1 = require_output_gates();
|
|
26904
|
+
var logger_1 = require_logger();
|
|
26905
|
+
var workspace_1 = require_workspace();
|
|
26906
|
+
exports2.GATE_REPAIR_BUDGET = 2;
|
|
26907
|
+
async function runDispatch(dispatch, executor, options) {
|
|
26908
|
+
const { credentials, signal } = options;
|
|
26909
|
+
const environment = executor.prepareEnvironment ? await executor.prepareEnvironment(dispatch) : void 0;
|
|
26910
|
+
let workspace = null;
|
|
26911
|
+
if (environment?.workspaceRequest) {
|
|
26912
|
+
try {
|
|
26913
|
+
workspace = await (0, workspace_1.materializeWorkspace)(environment.workspaceRequest, {
|
|
26914
|
+
...environment.materializeOptions ?? {},
|
|
26915
|
+
credentials,
|
|
26916
|
+
signal
|
|
26917
|
+
});
|
|
26918
|
+
} catch (err) {
|
|
26919
|
+
(0, logger_1.getLogger)().warn("workspace materialization failed; running prompt-only", {
|
|
26920
|
+
jobId: dispatch.job.id,
|
|
26921
|
+
error: err instanceof Error ? err.message : String(err)
|
|
26922
|
+
});
|
|
26923
|
+
workspace = null;
|
|
26924
|
+
}
|
|
26925
|
+
}
|
|
26926
|
+
const ctx = {
|
|
26927
|
+
...options.reportProgress ? { reportProgress: options.reportProgress } : {},
|
|
26928
|
+
workspace,
|
|
26929
|
+
credentials
|
|
26930
|
+
};
|
|
26931
|
+
let response;
|
|
26932
|
+
try {
|
|
26933
|
+
response = await executor.execute(dispatch, signal, ctx);
|
|
26934
|
+
} catch (error) {
|
|
26935
|
+
return { kind: "executor-failed", error };
|
|
26936
|
+
} finally {
|
|
26937
|
+
if (workspace)
|
|
26938
|
+
await workspace.cleanup();
|
|
26939
|
+
}
|
|
26940
|
+
const gated = await runOutputGates(dispatch, response, executor, signal, ctx);
|
|
26941
|
+
if (!gated.ok)
|
|
26942
|
+
return { kind: "gate-failed", reason: gated.reason };
|
|
26943
|
+
return { kind: "completed", response: gated.response };
|
|
26944
|
+
}
|
|
26945
|
+
async function runOutputGates(dispatch, response, executor, signal, ctx) {
|
|
26946
|
+
let spec;
|
|
26947
|
+
try {
|
|
26948
|
+
spec = (0, loom_1.readPromptExecutionSpec)(dispatch.inputs);
|
|
26949
|
+
} catch {
|
|
26950
|
+
return { ok: true, response };
|
|
26951
|
+
}
|
|
26952
|
+
const gates = spec.gates;
|
|
26953
|
+
if (!gates || gates.length === 0)
|
|
26954
|
+
return { ok: true, response };
|
|
26955
|
+
let current = response;
|
|
26956
|
+
let result = (0, output_gates_1.evaluateOutputGates)(gates, current.parsed ?? {}, dispatch.inputs);
|
|
26957
|
+
let attempts = 0;
|
|
26958
|
+
while (!result.ok && attempts < exports2.GATE_REPAIR_BUDGET && current.continuation !== void 0 && typeof executor.continue === "function") {
|
|
26959
|
+
try {
|
|
26960
|
+
const repaired = await executor.continue(current.continuation, (0, output_gates_1.renderRepairPrompt)(result.findings), signal, ctx);
|
|
26961
|
+
current = mergeRepairedResponse(current, repaired);
|
|
26962
|
+
} catch {
|
|
26963
|
+
break;
|
|
26964
|
+
}
|
|
26965
|
+
result = (0, output_gates_1.evaluateOutputGates)(gates, current.parsed ?? {}, dispatch.inputs);
|
|
26966
|
+
attempts += 1;
|
|
26967
|
+
}
|
|
26968
|
+
if (result.ok)
|
|
26969
|
+
return { ok: true, response: current };
|
|
26970
|
+
const detail = result.findings.map((f) => `[${f.gate}] ${f.message}`).join(" | ");
|
|
26971
|
+
return {
|
|
26972
|
+
ok: false,
|
|
26973
|
+
reason: `output gate(s) failed${attempts > 0 ? ` after ${attempts} repair attempt(s)` : ""}: ${detail}`
|
|
26974
|
+
};
|
|
26975
|
+
}
|
|
26976
|
+
function mergeRepairedResponse(original, repaired) {
|
|
26977
|
+
const replaced = new Set(repaired.outputs.map((o) => o.label));
|
|
26978
|
+
const outputs = [...original.outputs.filter((o) => !replaced.has(o.label)), ...repaired.outputs];
|
|
26979
|
+
const usage = sumUsage(original.usage, repaired.usage);
|
|
26980
|
+
return {
|
|
26981
|
+
...original,
|
|
26982
|
+
...repaired,
|
|
26983
|
+
outputs,
|
|
26984
|
+
...usage ? { usage } : {}
|
|
26985
|
+
};
|
|
26986
|
+
}
|
|
26987
|
+
var ADDITIVE_USAGE = [
|
|
26988
|
+
"inputTokens",
|
|
26989
|
+
"outputTokens",
|
|
26990
|
+
"cacheReadInputTokens",
|
|
26991
|
+
"cacheCreationInputTokens",
|
|
26992
|
+
"costUsd",
|
|
26993
|
+
"turns"
|
|
26994
|
+
];
|
|
26995
|
+
function sumUsage(a, b) {
|
|
26996
|
+
if (!a)
|
|
26997
|
+
return b;
|
|
26998
|
+
if (!b)
|
|
26999
|
+
return a;
|
|
27000
|
+
const sum = { ...a, ...b };
|
|
27001
|
+
for (const key of ADDITIVE_USAGE) {
|
|
27002
|
+
if (a[key] === void 0 && b[key] === void 0)
|
|
27003
|
+
continue;
|
|
27004
|
+
sum[key] = (a[key] ?? 0) + (b[key] ?? 0);
|
|
27005
|
+
}
|
|
27006
|
+
if (a.toolCalls || b.toolCalls) {
|
|
27007
|
+
const calls = { ...a.toolCalls ?? {} };
|
|
27008
|
+
for (const [name, n] of Object.entries(b.toolCalls ?? {}))
|
|
27009
|
+
calls[name] = (calls[name] ?? 0) + n;
|
|
27010
|
+
sum.toolCalls = calls;
|
|
27011
|
+
}
|
|
27012
|
+
return sum;
|
|
27013
|
+
}
|
|
27014
|
+
}
|
|
27015
|
+
});
|
|
27016
|
+
|
|
26503
27017
|
// ../../packages/shuttle/dist/credentials/registry.js
|
|
26504
27018
|
var require_registry2 = __commonJS({
|
|
26505
27019
|
"../../packages/shuttle/dist/credentials/registry.js"(exports2) {
|
|
@@ -26519,350 +27033,118 @@ var require_registry2 = __commonJS({
|
|
|
26519
27033
|
return reveal.apiKey;
|
|
26520
27034
|
});
|
|
26521
27035
|
registerCredentialResolver("github-user-token", async (keep, principal) => {
|
|
26522
|
-
try {
|
|
26523
|
-
const reveal = await keep.getUserGithubToken(principal);
|
|
26524
|
-
return reveal.access_token;
|
|
26525
|
-
} catch {
|
|
26526
|
-
return null;
|
|
26527
|
-
}
|
|
26528
|
-
});
|
|
26529
|
-
}
|
|
26530
|
-
});
|
|
26531
|
-
|
|
26532
|
-
// ../../packages/shuttle/dist/credentials/broker.js
|
|
26533
|
-
var require_broker = __commonJS({
|
|
26534
|
-
"../../packages/shuttle/dist/credentials/broker.js"(exports2) {
|
|
26535
|
-
"use strict";
|
|
26536
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
26537
|
-
exports2.createCredentialBroker = createCredentialBroker;
|
|
26538
|
-
var keep_1 = require_dist2();
|
|
26539
|
-
var env_ref_1 = require_env_ref();
|
|
26540
|
-
var registry_1 = require_registry2();
|
|
26541
|
-
function createCredentialBroker(config, deps = {}) {
|
|
26542
|
-
if (typeof config !== "object" || config === null || config.apiKeyFrom !== "job-metadata") {
|
|
26543
|
-
return null;
|
|
26544
|
-
}
|
|
26545
|
-
const cfg = config;
|
|
26546
|
-
const keepApiUrl = (0, env_ref_1.resolveConfigStringOrEnv)(cfg, "keepApiUrl", "KEEP_API_URL");
|
|
26547
|
-
const clientId = (0, env_ref_1.resolveConfigStringOrEnv)(cfg, "keepClientId", "KEEP_CLIENT_ID");
|
|
26548
|
-
const clientSecret = (0, env_ref_1.resolveConfigStringOrEnv)(cfg, "keepClientSecret", "KEEP_CLIENT_SECRET");
|
|
26549
|
-
const stmFactory = deps.buildServiceTokenManager ?? ((c) => new keep_1.ServiceTokenManager(c));
|
|
26550
|
-
const stm = stmFactory({ keepApiUrl, clientId, clientSecret });
|
|
26551
|
-
const keepFactory = deps.buildKeepClient ?? ((c) => new keep_1.KeepClient(c));
|
|
26552
|
-
return {
|
|
26553
|
-
async reveal({ name, principal }) {
|
|
26554
|
-
const resolver = (0, registry_1.getCredentialResolver)(name);
|
|
26555
|
-
if (!resolver)
|
|
26556
|
-
return null;
|
|
26557
|
-
const serviceToken = await stm.getToken();
|
|
26558
|
-
if (!serviceToken) {
|
|
26559
|
-
throw new Error("credential broker: Keep service-token exchange failed. Check KEEP_CLIENT_ID / KEEP_CLIENT_SECRET.");
|
|
26560
|
-
}
|
|
26561
|
-
const keep = keepFactory({ baseUrl: keepApiUrl, serviceToken });
|
|
26562
|
-
return resolver(keep, principal);
|
|
26563
|
-
}
|
|
26564
|
-
};
|
|
26565
|
-
}
|
|
26566
|
-
}
|
|
26567
|
-
});
|
|
26568
|
-
|
|
26569
|
-
// ../../packages/shuttle/dist/credentials/index.js
|
|
26570
|
-
var require_credentials = __commonJS({
|
|
26571
|
-
"../../packages/shuttle/dist/credentials/index.js"(exports2) {
|
|
26572
|
-
"use strict";
|
|
26573
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
26574
|
-
exports2.getCredentialResolver = exports2.registerCredentialResolver = exports2.createCredentialBroker = void 0;
|
|
26575
|
-
var broker_1 = require_broker();
|
|
26576
|
-
Object.defineProperty(exports2, "createCredentialBroker", { enumerable: true, get: function() {
|
|
26577
|
-
return broker_1.createCredentialBroker;
|
|
26578
|
-
} });
|
|
26579
|
-
var registry_1 = require_registry2();
|
|
26580
|
-
Object.defineProperty(exports2, "registerCredentialResolver", { enumerable: true, get: function() {
|
|
26581
|
-
return registry_1.registerCredentialResolver;
|
|
26582
|
-
} });
|
|
26583
|
-
Object.defineProperty(exports2, "getCredentialResolver", { enumerable: true, get: function() {
|
|
26584
|
-
return registry_1.getCredentialResolver;
|
|
26585
|
-
} });
|
|
26586
|
-
}
|
|
26587
|
-
});
|
|
26588
|
-
|
|
26589
|
-
// ../../packages/shuttle/dist/executors/output-gates.js
|
|
26590
|
-
var require_output_gates = __commonJS({
|
|
26591
|
-
"../../packages/shuttle/dist/executors/output-gates.js"(exports2) {
|
|
26592
|
-
"use strict";
|
|
26593
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
26594
|
-
exports2.isSanctionedPaint = isSanctionedPaint;
|
|
26595
|
-
exports2.unsanctionedPaints = unsanctionedPaints;
|
|
26596
|
-
exports2.resolvePath = resolvePath;
|
|
26597
|
-
exports2.evaluateOutputGates = evaluateOutputGates;
|
|
26598
|
-
exports2.renderRepairPrompt = renderRepairPrompt;
|
|
26599
|
-
var INPUT_REF = "input:";
|
|
26600
|
-
var COLOR_BEARING = ["fill", "stroke", "color", "stop-color", "flood-color", "lighting-color"];
|
|
26601
|
-
var INERT = /* @__PURE__ */ new Set(["none", "inherit", "initial", "unset", "transparent", "currentcolor"]);
|
|
26602
|
-
function isSanctionedPaint(raw) {
|
|
26603
|
-
const value = raw.trim().toLowerCase();
|
|
26604
|
-
if (value === "")
|
|
26605
|
-
return true;
|
|
26606
|
-
if (INERT.has(value))
|
|
26607
|
-
return true;
|
|
26608
|
-
if (/^url\(\s*['"]?#[^)'"]+['"]?\s*\)$/.test(value))
|
|
26609
|
-
return true;
|
|
26610
|
-
const varMatch = /^var\(\s*(--[a-z0-9-]+)\s*(?:,([\s\S]*))?\)$/.exec(value);
|
|
26611
|
-
if (!varMatch)
|
|
26612
|
-
return false;
|
|
26613
|
-
const [, name, fallback] = varMatch;
|
|
26614
|
-
if (!name.startsWith("--color-"))
|
|
26615
|
-
return false;
|
|
26616
|
-
return fallback === void 0 || isSanctionedPaint(fallback);
|
|
26617
|
-
}
|
|
26618
|
-
function unsanctionedPaints(source) {
|
|
26619
|
-
const found = [];
|
|
26620
|
-
const attrs = COLOR_BEARING.join("|");
|
|
26621
|
-
const attribute = new RegExp(`\\b(?:${attrs})\\s*=\\s*(['"])([\\s\\S]*?)\\1`, "gi");
|
|
26622
|
-
const declaration = new RegExp(`\\b(?:${attrs})\\s*:\\s*([^;"'}\\n]+)`, "gi");
|
|
26623
|
-
for (const [, , value] of source.matchAll(attribute)) {
|
|
26624
|
-
if (!isSanctionedPaint(value))
|
|
26625
|
-
found.push(value.trim());
|
|
26626
|
-
}
|
|
26627
|
-
for (const [, value] of source.matchAll(declaration)) {
|
|
26628
|
-
if (!isSanctionedPaint(value))
|
|
26629
|
-
found.push(value.trim());
|
|
26630
|
-
}
|
|
26631
|
-
return found;
|
|
26632
|
-
}
|
|
26633
|
-
function resolvePath(root, path) {
|
|
26634
|
-
let ctx = root;
|
|
26635
|
-
for (const seg of path.split(".")) {
|
|
26636
|
-
const project = seg.endsWith("[*]");
|
|
26637
|
-
const key = project ? seg.slice(0, -3) : seg;
|
|
26638
|
-
if (Array.isArray(ctx)) {
|
|
26639
|
-
ctx = ctx.map((el) => key ? el?.[key] : el);
|
|
26640
|
-
} else {
|
|
26641
|
-
ctx = key ? ctx?.[key] : ctx;
|
|
26642
|
-
}
|
|
26643
|
-
if (project && !Array.isArray(ctx)) {
|
|
26644
|
-
ctx = ctx == null ? [] : [ctx];
|
|
26645
|
-
}
|
|
26646
|
-
}
|
|
26647
|
-
return ctx;
|
|
26648
|
-
}
|
|
26649
|
-
function resolveRef(ref, output, inputs) {
|
|
26650
|
-
if (ref.startsWith(INPUT_REF)) {
|
|
26651
|
-
const label = ref.slice(INPUT_REF.length);
|
|
26652
|
-
const row = inputs.find((i) => i.label === label) ?? inputs.find((i) => i.label === "artifacts" && i.payload.label === label);
|
|
26653
|
-
if (!row)
|
|
26654
|
-
return void 0;
|
|
26655
|
-
return Object.prototype.hasOwnProperty.call(row.payload, "value") ? row.payload.value : row.payload;
|
|
26656
|
-
}
|
|
26657
|
-
return resolvePath(output, ref);
|
|
26658
|
-
}
|
|
26659
|
-
function asStrings(value) {
|
|
26660
|
-
if (Array.isArray(value))
|
|
26661
|
-
return value.map((v) => String(v));
|
|
26662
|
-
if (value == null)
|
|
26663
|
-
return [];
|
|
26664
|
-
return [String(value)];
|
|
26665
|
-
}
|
|
26666
|
-
var PRIMITIVES = {
|
|
26667
|
-
/**
|
|
26668
|
-
* `coverage` — the values at `got` must exactly cover the set at `want`:
|
|
26669
|
-
* every wanted value present, nothing invented, none repeated. Params:
|
|
26670
|
-
* `{ got: <output path>, want: <ref>, subject?: <noun> }`.
|
|
26671
|
-
*/
|
|
26672
|
-
coverage(params, output, inputs) {
|
|
26673
|
-
const subject = typeof params.subject === "string" ? params.subject : "item";
|
|
26674
|
-
const got = asStrings(resolveRef(String(params.got), output, inputs));
|
|
26675
|
-
const want = asStrings(resolveRef(String(params.want), output, inputs));
|
|
26676
|
-
const gotSet = new Set(got);
|
|
26677
|
-
const wantSet = new Set(want);
|
|
26678
|
-
const missing = want.filter((v) => !gotSet.has(v));
|
|
26679
|
-
const unknown = [...new Set(got.filter((v) => !wantSet.has(v)))];
|
|
26680
|
-
const seen = /* @__PURE__ */ new Set();
|
|
26681
|
-
const duplicated = [];
|
|
26682
|
-
for (const v of got) {
|
|
26683
|
-
if (seen.has(v))
|
|
26684
|
-
duplicated.push(v);
|
|
26685
|
-
else
|
|
26686
|
-
seen.add(v);
|
|
26687
|
-
}
|
|
26688
|
-
if (missing.length === 0 && unknown.length === 0 && duplicated.length === 0)
|
|
26689
|
-
return [];
|
|
26690
|
-
const parts = [];
|
|
26691
|
-
if (missing.length)
|
|
26692
|
-
parts.push(`missing ${subject}(s): [${missing.join(", ")}]`);
|
|
26693
|
-
if (unknown.length)
|
|
26694
|
-
parts.push(`not a known ${subject}: [${unknown.join(", ")}]`);
|
|
26695
|
-
if (duplicated.length)
|
|
26696
|
-
parts.push(`assessed more than once: [${[...new Set(duplicated)].join(", ")}]`);
|
|
26697
|
-
return [
|
|
26698
|
-
`every ${subject} must be covered exactly once \u2014 ${parts.join("; ")}. Return one entry per ${subject}, using its exact id.`
|
|
26699
|
-
];
|
|
26700
|
-
},
|
|
26701
|
-
/**
|
|
26702
|
-
* `non_empty_when` — the array at `path` must be non-empty, optionally only
|
|
26703
|
-
* when `when.path` equals `when.equals`. Params:
|
|
26704
|
-
* `{ path: <output path>, when?: { path: <output path>, equals: <value> } }`.
|
|
26705
|
-
*/
|
|
26706
|
-
non_empty_when(params, output) {
|
|
26707
|
-
const when = params.when;
|
|
26708
|
-
if (when && typeof when.path === "string") {
|
|
26709
|
-
if (resolvePath(output, when.path) !== when.equals)
|
|
26710
|
-
return [];
|
|
26711
|
-
}
|
|
26712
|
-
const path = String(params.path);
|
|
26713
|
-
const value = resolvePath(output, path);
|
|
26714
|
-
if (Array.isArray(value) && value.length > 0)
|
|
26715
|
-
return [];
|
|
26716
|
-
const cond = when && typeof when.path === "string" ? ` when ${when.path} is ${JSON.stringify(when.equals)}` : "";
|
|
26717
|
-
return [
|
|
26718
|
-
`'${path}' must be a non-empty array${cond}; it was ${Array.isArray(value) ? "empty" : "absent"}.`
|
|
26719
|
-
];
|
|
26720
|
-
},
|
|
26721
|
-
/**
|
|
26722
|
-
* `bounded_palette` — every colour in the sources at `path` must be named
|
|
26723
|
-
* by role rather than written as a value. Params:
|
|
26724
|
-
* `{ path: <output path>, roles?: <role names for the repair turn> }`.
|
|
26725
|
-
*
|
|
26726
|
-
* A drawing the model authors is markup the house did not write, and a
|
|
26727
|
-
* literal in it is a colour outside the consuming palette: unproved
|
|
26728
|
-
* against the colours beside it, unchecked for contrast on the ground it
|
|
26729
|
-
* lands on, and fixed to one theme. The consumer strips such a paint at
|
|
26730
|
-
* render, so an artifact that carries one silently loses it. Catching it
|
|
26731
|
-
* HERE is what makes that a repair the model can make while it still has
|
|
26732
|
-
* the drawing in hand, instead of a defect nobody sees until the picture
|
|
26733
|
-
* comes out plain.
|
|
26734
|
-
*/
|
|
26735
|
-
bounded_palette(params, output) {
|
|
26736
|
-
const path = String(params.path);
|
|
26737
|
-
const value = resolvePath(output, path);
|
|
26738
|
-
const sources = (Array.isArray(value) ? value : [value]).filter((v) => typeof v === "string" && v.length > 0);
|
|
26739
|
-
const offenders = [...new Set(sources.flatMap(unsanctionedPaints))];
|
|
26740
|
-
if (offenders.length === 0)
|
|
26741
|
-
return [];
|
|
26742
|
-
const roles = Array.isArray(params.roles) ? params.roles.map(String) : [];
|
|
26743
|
-
const vocabulary = roles.length > 0 ? ` Use one of: ${roles.join(", ")}.` : "";
|
|
26744
|
-
return [
|
|
26745
|
-
`'${path}' states ${offenders.length} colour value${offenders.length === 1 ? "" : "s"} directly (${offenders.slice(0, 8).join(", ")}${offenders.length > 8 ? ", \u2026" : ""}). Every colour must be named by role \u2014 var(--color-\u2026), currentColor, or none \u2014 never as a hex, rgb(), hsl() or colour name, because a value cannot adapt to the reader's theme and was never checked against the colours beside it.${vocabulary} Redraw with roles and return the whole output again.`
|
|
26746
|
-
];
|
|
26747
|
-
}
|
|
26748
|
-
};
|
|
26749
|
-
function evaluateOutputGates(gates, output, inputs) {
|
|
26750
|
-
const findings = [];
|
|
26751
|
-
for (const gate of gates) {
|
|
26752
|
-
const primitive = PRIMITIVES[gate.primitive];
|
|
26753
|
-
if (!primitive) {
|
|
26754
|
-
findings.push({ gate: gate.name, message: `unknown gate primitive '${gate.primitive}'` });
|
|
26755
|
-
continue;
|
|
26756
|
-
}
|
|
26757
|
-
for (const message of primitive(gate.params, output, inputs)) {
|
|
26758
|
-
findings.push({ gate: gate.name, message });
|
|
26759
|
-
}
|
|
26760
|
-
}
|
|
26761
|
-
return { ok: findings.length === 0, findings };
|
|
26762
|
-
}
|
|
26763
|
-
function renderRepairPrompt(findings) {
|
|
26764
|
-
return [
|
|
26765
|
-
"Your previous answer did not satisfy these output checks. Return the corrected, complete answer that resolves every item below. Produce the same output shape with the problems fixed, and nothing else \u2014 no commentary, no explanation of the changes.",
|
|
26766
|
-
"",
|
|
26767
|
-
...findings.map((f) => `- [${f.gate}] ${f.message}`)
|
|
26768
|
-
].join("\n");
|
|
26769
|
-
}
|
|
27036
|
+
try {
|
|
27037
|
+
const reveal = await keep.getUserGithubToken(principal);
|
|
27038
|
+
return reveal.access_token;
|
|
27039
|
+
} catch {
|
|
27040
|
+
return null;
|
|
27041
|
+
}
|
|
27042
|
+
});
|
|
26770
27043
|
}
|
|
26771
27044
|
});
|
|
26772
27045
|
|
|
26773
|
-
// ../../packages/shuttle/dist/
|
|
26774
|
-
var
|
|
26775
|
-
"../../packages/shuttle/dist/
|
|
27046
|
+
// ../../packages/shuttle/dist/credentials/broker.js
|
|
27047
|
+
var require_broker = __commonJS({
|
|
27048
|
+
"../../packages/shuttle/dist/credentials/broker.js"(exports2) {
|
|
26776
27049
|
"use strict";
|
|
26777
27050
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
26778
|
-
exports2.
|
|
26779
|
-
|
|
26780
|
-
|
|
26781
|
-
var
|
|
26782
|
-
|
|
26783
|
-
|
|
26784
|
-
|
|
26785
|
-
error: 3
|
|
26786
|
-
};
|
|
26787
|
-
function formatContext(context) {
|
|
26788
|
-
return Object.entries(context).map(([k, v]) => `${k}=${typeof v === "string" ? v : JSON.stringify(v)}`).join(" ");
|
|
26789
|
-
}
|
|
26790
|
-
function formatPretty(level, message, context) {
|
|
26791
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
26792
|
-
const tag = level.toUpperCase().padEnd(5);
|
|
26793
|
-
const base = `[${timestamp}] ${tag} ${message}`;
|
|
26794
|
-
if (context && Object.keys(context).length > 0) {
|
|
26795
|
-
return `${base} ${formatContext(context)}`;
|
|
26796
|
-
}
|
|
26797
|
-
return base;
|
|
26798
|
-
}
|
|
26799
|
-
function formatJson(level, message, context) {
|
|
26800
|
-
const entry = {
|
|
26801
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
26802
|
-
level,
|
|
26803
|
-
message,
|
|
26804
|
-
...context
|
|
26805
|
-
};
|
|
26806
|
-
return JSON.stringify(entry);
|
|
26807
|
-
}
|
|
26808
|
-
function createLogger(options) {
|
|
26809
|
-
const threshold = LEVEL_ORDER[options.level];
|
|
26810
|
-
const format = options.format === "json" ? formatJson : formatPretty;
|
|
26811
|
-
function emit(level, message, context) {
|
|
26812
|
-
if (LEVEL_ORDER[level] < threshold)
|
|
26813
|
-
return;
|
|
26814
|
-
const line = format(level, message, context);
|
|
26815
|
-
if (level === "error") {
|
|
26816
|
-
console.error(line);
|
|
26817
|
-
} else if (level === "warn") {
|
|
26818
|
-
console.warn(line);
|
|
26819
|
-
} else {
|
|
26820
|
-
console.log(line);
|
|
26821
|
-
}
|
|
27051
|
+
exports2.createCredentialBroker = createCredentialBroker;
|
|
27052
|
+
var keep_1 = require_dist2();
|
|
27053
|
+
var env_ref_1 = require_env_ref();
|
|
27054
|
+
var registry_1 = require_registry2();
|
|
27055
|
+
function createCredentialBroker(config, deps = {}) {
|
|
27056
|
+
if (typeof config !== "object" || config === null || config.apiKeyFrom !== "job-metadata") {
|
|
27057
|
+
return null;
|
|
26822
27058
|
}
|
|
27059
|
+
const cfg = config;
|
|
27060
|
+
const keepApiUrl = (0, env_ref_1.resolveConfigStringOrEnv)(cfg, "keepApiUrl", "KEEP_API_URL");
|
|
27061
|
+
const clientId = (0, env_ref_1.resolveConfigStringOrEnv)(cfg, "keepClientId", "KEEP_CLIENT_ID");
|
|
27062
|
+
const clientSecret = (0, env_ref_1.resolveConfigStringOrEnv)(cfg, "keepClientSecret", "KEEP_CLIENT_SECRET");
|
|
27063
|
+
const stmFactory = deps.buildServiceTokenManager ?? ((c) => new keep_1.ServiceTokenManager(c));
|
|
27064
|
+
const stm = stmFactory({ keepApiUrl, clientId, clientSecret });
|
|
27065
|
+
const keepFactory = deps.buildKeepClient ?? ((c) => new keep_1.KeepClient(c));
|
|
26823
27066
|
return {
|
|
26824
|
-
|
|
26825
|
-
|
|
26826
|
-
|
|
26827
|
-
|
|
27067
|
+
async reveal({ name, principal }) {
|
|
27068
|
+
const resolver = (0, registry_1.getCredentialResolver)(name);
|
|
27069
|
+
if (!resolver)
|
|
27070
|
+
return null;
|
|
27071
|
+
const serviceToken = await stm.getToken();
|
|
27072
|
+
if (!serviceToken) {
|
|
27073
|
+
throw new Error("credential broker: Keep service-token exchange failed. Check KEEP_CLIENT_ID / KEEP_CLIENT_SECRET.");
|
|
27074
|
+
}
|
|
27075
|
+
const keep = keepFactory({ baseUrl: keepApiUrl, serviceToken });
|
|
27076
|
+
return resolver(keep, principal);
|
|
27077
|
+
}
|
|
26828
27078
|
};
|
|
26829
27079
|
}
|
|
26830
|
-
var globalLogger = createLogger({ level: "info", format: "pretty" });
|
|
26831
|
-
function setGlobalLogger(logger) {
|
|
26832
|
-
globalLogger = logger;
|
|
26833
|
-
}
|
|
26834
|
-
function getLogger() {
|
|
26835
|
-
return globalLogger;
|
|
26836
|
-
}
|
|
26837
27080
|
}
|
|
26838
27081
|
});
|
|
26839
27082
|
|
|
26840
|
-
// ../../packages/shuttle/dist/
|
|
26841
|
-
var
|
|
26842
|
-
"../../packages/shuttle/dist/
|
|
27083
|
+
// ../../packages/shuttle/dist/credentials/index.js
|
|
27084
|
+
var require_credentials = __commonJS({
|
|
27085
|
+
"../../packages/shuttle/dist/credentials/index.js"(exports2) {
|
|
27086
|
+
"use strict";
|
|
27087
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
27088
|
+
exports2.getCredentialResolver = exports2.registerCredentialResolver = exports2.createCredentialBroker = void 0;
|
|
27089
|
+
var broker_1 = require_broker();
|
|
27090
|
+
Object.defineProperty(exports2, "createCredentialBroker", { enumerable: true, get: function() {
|
|
27091
|
+
return broker_1.createCredentialBroker;
|
|
27092
|
+
} });
|
|
27093
|
+
var registry_1 = require_registry2();
|
|
27094
|
+
Object.defineProperty(exports2, "registerCredentialResolver", { enumerable: true, get: function() {
|
|
27095
|
+
return registry_1.registerCredentialResolver;
|
|
27096
|
+
} });
|
|
27097
|
+
Object.defineProperty(exports2, "getCredentialResolver", { enumerable: true, get: function() {
|
|
27098
|
+
return registry_1.getCredentialResolver;
|
|
27099
|
+
} });
|
|
27100
|
+
}
|
|
27101
|
+
});
|
|
27102
|
+
|
|
27103
|
+
// ../../packages/shuttle/dist/core/executor-choice.js
|
|
27104
|
+
var require_executor_choice = __commonJS({
|
|
27105
|
+
"../../packages/shuttle/dist/core/executor-choice.js"(exports2) {
|
|
26843
27106
|
"use strict";
|
|
26844
27107
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
26845
|
-
exports2.
|
|
26846
|
-
|
|
26847
|
-
|
|
26848
|
-
for (const executor of executors) {
|
|
26849
|
-
for (const strategy of executor.strategies)
|
|
26850
|
-
byStrategy.set(strategy, executor);
|
|
26851
|
-
}
|
|
27108
|
+
exports2.createExecutorChooser = createExecutorChooser;
|
|
27109
|
+
var loom_1 = require_dist();
|
|
27110
|
+
function createExecutorChooser(executors, pools) {
|
|
26852
27111
|
const byName = new Map(executors.map((e) => [e.capability.id, e]));
|
|
26853
|
-
const
|
|
27112
|
+
const legacyFirst = /* @__PURE__ */ new Map();
|
|
26854
27113
|
for (const pool of pools) {
|
|
26855
|
-
|
|
26856
|
-
if (!named)
|
|
27114
|
+
if (!pool.executor || !byName.has(pool.executor))
|
|
26857
27115
|
continue;
|
|
26858
27116
|
if (pool.id)
|
|
26859
|
-
|
|
27117
|
+
legacyFirst.set(`id:${pool.id}`, pool.executor);
|
|
26860
27118
|
if (pool.name)
|
|
26861
|
-
|
|
27119
|
+
legacyFirst.set(`name:${pool.name}`, pool.executor);
|
|
26862
27120
|
}
|
|
26863
|
-
|
|
26864
|
-
const
|
|
26865
|
-
|
|
27121
|
+
const orderFor = (pool) => {
|
|
27122
|
+
const first = (pool.id !== void 0 ? legacyFirst.get(`id:${pool.id}`) : void 0) ?? (pool.name !== void 0 ? legacyFirst.get(`name:${pool.name}`) : void 0);
|
|
27123
|
+
const head = first ? byName.get(first) : void 0;
|
|
27124
|
+
return head ? [head, ...executors.filter((e) => e !== head)] : [...executors];
|
|
27125
|
+
};
|
|
27126
|
+
return {
|
|
27127
|
+
accepts(tags) {
|
|
27128
|
+
const required = (0, loom_1.readRequiredExecutor)(tags);
|
|
27129
|
+
return required === null || byName.has(required);
|
|
27130
|
+
},
|
|
27131
|
+
choose({ pool, strategy, required }) {
|
|
27132
|
+
if (required !== null) {
|
|
27133
|
+
const named = byName.get(required);
|
|
27134
|
+
if (!named) {
|
|
27135
|
+
return { ok: false, reason: `this job requires the ${required} executor, which this runner does not have` };
|
|
27136
|
+
}
|
|
27137
|
+
if (!named.strategies.includes(strategy)) {
|
|
27138
|
+
return { ok: false, reason: `this job requires the ${required} executor, which does not run "${strategy}" jobs` };
|
|
27139
|
+
}
|
|
27140
|
+
return { ok: true, executors: [named], required };
|
|
27141
|
+
}
|
|
27142
|
+
const capable = orderFor(pool).filter((e) => e.strategies.includes(strategy));
|
|
27143
|
+
if (capable.length === 0)
|
|
27144
|
+
return { ok: false, reason: `no executor for shuttle strategy "${strategy}"` };
|
|
27145
|
+
return { ok: true, executors: capable, required: null };
|
|
27146
|
+
},
|
|
27147
|
+
orderFor
|
|
26866
27148
|
};
|
|
26867
27149
|
}
|
|
26868
27150
|
}
|
|
@@ -27378,9 +27660,8 @@ var require_shuttle = __commonJS({
|
|
|
27378
27660
|
var loom_1 = require_dist();
|
|
27379
27661
|
var chain_1 = require_chain();
|
|
27380
27662
|
var types_1 = require_types2();
|
|
27381
|
-
var
|
|
27663
|
+
var run_dispatch_1 = require_run_dispatch();
|
|
27382
27664
|
var credentials_1 = require_credentials();
|
|
27383
|
-
var output_gates_1 = require_output_gates();
|
|
27384
27665
|
var keep_1 = require_dist2();
|
|
27385
27666
|
var apply_1 = require_apply();
|
|
27386
27667
|
var environment_1 = require_environment();
|
|
@@ -27389,7 +27670,7 @@ var require_shuttle = __commonJS({
|
|
|
27389
27670
|
var logger_1 = require_logger();
|
|
27390
27671
|
var registry_1 = require_registry();
|
|
27391
27672
|
var claude_code_1 = require_claude_code();
|
|
27392
|
-
var
|
|
27673
|
+
var executor_choice_1 = require_executor_choice();
|
|
27393
27674
|
var codex_1 = require_codex();
|
|
27394
27675
|
var copilot_1 = require_copilot();
|
|
27395
27676
|
var http_api_1 = require_http_api();
|
|
@@ -27400,8 +27681,16 @@ var require_shuttle = __commonJS({
|
|
|
27400
27681
|
var audit_log_1 = require_audit_log();
|
|
27401
27682
|
var spend_tracker_1 = require_spend_tracker();
|
|
27402
27683
|
var store_1 = require_store();
|
|
27403
|
-
var GATE_REPAIR_BUDGET = 2;
|
|
27404
27684
|
var ENVIRONMENT_HOLD = "executor-environment";
|
|
27685
|
+
function requiredExecutor(dispatch, strategy) {
|
|
27686
|
+
if (strategy !== loom_1.PROMPT_EXECUTION_STRATEGY)
|
|
27687
|
+
return null;
|
|
27688
|
+
try {
|
|
27689
|
+
return (0, loom_1.readPromptExecutionSpec)(dispatch.inputs).requires?.executor ?? null;
|
|
27690
|
+
} catch {
|
|
27691
|
+
return null;
|
|
27692
|
+
}
|
|
27693
|
+
}
|
|
27405
27694
|
var RECHECK_INITIAL_MS = 15e3;
|
|
27406
27695
|
var RECHECK_MAX_MS = 3e5;
|
|
27407
27696
|
var KEEP_RETRY_INITIAL_MS = 2e3;
|
|
@@ -27458,36 +27747,6 @@ var require_shuttle = __commonJS({
|
|
|
27458
27747
|
function formatInstant(epochMs) {
|
|
27459
27748
|
return new Date(epochMs).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
27460
27749
|
}
|
|
27461
|
-
async function runOutputGates(dispatch, response, executor, signal, ctx) {
|
|
27462
|
-
let spec;
|
|
27463
|
-
try {
|
|
27464
|
-
spec = (0, loom_1.readPromptExecutionSpec)(dispatch.inputs);
|
|
27465
|
-
} catch {
|
|
27466
|
-
return { ok: true, response };
|
|
27467
|
-
}
|
|
27468
|
-
const gates = spec.gates;
|
|
27469
|
-
if (!gates || gates.length === 0)
|
|
27470
|
-
return { ok: true, response };
|
|
27471
|
-
let current = response;
|
|
27472
|
-
let result = (0, output_gates_1.evaluateOutputGates)(gates, current.parsed ?? {}, dispatch.inputs);
|
|
27473
|
-
let attempts = 0;
|
|
27474
|
-
while (!result.ok && attempts < GATE_REPAIR_BUDGET && current.continuation !== void 0 && typeof executor.continue === "function") {
|
|
27475
|
-
try {
|
|
27476
|
-
current = await executor.continue(current.continuation, (0, output_gates_1.renderRepairPrompt)(result.findings), signal, ctx);
|
|
27477
|
-
} catch {
|
|
27478
|
-
break;
|
|
27479
|
-
}
|
|
27480
|
-
result = (0, output_gates_1.evaluateOutputGates)(gates, current.parsed ?? {}, dispatch.inputs);
|
|
27481
|
-
attempts += 1;
|
|
27482
|
-
}
|
|
27483
|
-
if (result.ok)
|
|
27484
|
-
return { ok: true, response: current };
|
|
27485
|
-
const detail = result.findings.map((f) => `[${f.gate}] ${f.message}`).join(" | ");
|
|
27486
|
-
return {
|
|
27487
|
-
ok: false,
|
|
27488
|
-
reason: `output gate(s) failed${attempts > 0 ? ` after ${attempts} repair attempt(s)` : ""}: ${detail}`
|
|
27489
|
-
};
|
|
27490
|
-
}
|
|
27491
27750
|
var Shuttle = class {
|
|
27492
27751
|
brand;
|
|
27493
27752
|
config;
|
|
@@ -27511,8 +27770,15 @@ var require_shuttle = __commonJS({
|
|
|
27511
27770
|
lifetime = deferred();
|
|
27512
27771
|
/** Aborted by `stop()`: ends the startup waits and the readiness re-checks. */
|
|
27513
27772
|
stopping = new AbortController();
|
|
27514
|
-
/**
|
|
27515
|
-
|
|
27773
|
+
/**
|
|
27774
|
+
* The executors that cannot run jobs on this machine just now (signed out,
|
|
27775
|
+
* missing, out of plan), with why and since when. Empty while every one can.
|
|
27776
|
+
*/
|
|
27777
|
+
unwell = /* @__PURE__ */ new Map();
|
|
27778
|
+
/** Every configured executor, in the configured order. */
|
|
27779
|
+
executors = [];
|
|
27780
|
+
/** Whether claiming is paused because no executor can run jobs. */
|
|
27781
|
+
environmentHeld = false;
|
|
27516
27782
|
constructor(options) {
|
|
27517
27783
|
this.brand = options.brand;
|
|
27518
27784
|
this.config = options.config;
|
|
@@ -27596,7 +27862,8 @@ var require_shuttle = __commonJS({
|
|
|
27596
27862
|
const registry = new registry_1.ExecutorRegistry(this.brand.executorAllowlist);
|
|
27597
27863
|
registerBuiltInExecutors(registry, this.brand.executorAllowlist);
|
|
27598
27864
|
const executors = registry.build(mergeExecutorDefaults((0, environment_1.executorDefaultsFor)(this.brand, this.config.auth.jobsApiUrl), this.config.executors));
|
|
27599
|
-
|
|
27865
|
+
this.executors = executors;
|
|
27866
|
+
const chooser = (0, executor_choice_1.createExecutorChooser)(executors, this.config.pools);
|
|
27600
27867
|
const modelsByExecutor = await listExecutorModels(executors, this.stopping.signal);
|
|
27601
27868
|
if (this.stopping.signal.aborted)
|
|
27602
27869
|
return;
|
|
@@ -27621,12 +27888,31 @@ var require_shuttle = __commonJS({
|
|
|
27621
27888
|
const attendanceId = dispatch.attendanceId;
|
|
27622
27889
|
const startedAt = Date.now();
|
|
27623
27890
|
const strategy = (0, loom_1.readShuttleStrategy)(dispatch.inputs) ?? "";
|
|
27624
|
-
const
|
|
27625
|
-
|
|
27626
|
-
|
|
27627
|
-
|
|
27628
|
-
|
|
27891
|
+
const close = async (result) => {
|
|
27892
|
+
await observerChain.notify({
|
|
27893
|
+
kind: "attendance.closed",
|
|
27894
|
+
jobId,
|
|
27895
|
+
attendanceId,
|
|
27896
|
+
status: result.status === "completed" ? "completed" : "failed",
|
|
27897
|
+
...result.reason !== void 0 ? { reason: result.reason } : {},
|
|
27898
|
+
totalDurationMs: Date.now() - startedAt
|
|
27899
|
+
}, onObserverError);
|
|
27900
|
+
return result;
|
|
27901
|
+
};
|
|
27902
|
+
const choice = chooser.choose({ pool: dispatch.pool, strategy, required: requiredExecutor(dispatch, strategy) });
|
|
27903
|
+
if (!choice.ok)
|
|
27904
|
+
return close({ status: "failed", reason: choice.reason });
|
|
27905
|
+
if (choice.required !== null) {
|
|
27906
|
+
const fault = this.unwell.get(choice.required);
|
|
27907
|
+
if (fault) {
|
|
27908
|
+
return close({
|
|
27909
|
+
status: "failed",
|
|
27910
|
+
reason: `executor failed: ${choice.required} cannot run jobs on this machine (${fault.err.message}). To fix it, ${fault.err.remedy}.`
|
|
27911
|
+
});
|
|
27912
|
+
}
|
|
27629
27913
|
}
|
|
27914
|
+
const well = choice.executors.filter((e) => !this.unwell.has(e.capability.id));
|
|
27915
|
+
const candidates = well.length > 0 ? well : choice.executors;
|
|
27630
27916
|
await observerChain.notify({
|
|
27631
27917
|
kind: "job.claimed",
|
|
27632
27918
|
jobId,
|
|
@@ -27637,9 +27923,9 @@ var require_shuttle = __commonJS({
|
|
|
27637
27923
|
dispatch
|
|
27638
27924
|
}, onObserverError);
|
|
27639
27925
|
let estimate = {};
|
|
27640
|
-
if (
|
|
27926
|
+
if (candidates[0].estimate) {
|
|
27641
27927
|
try {
|
|
27642
|
-
estimate = await
|
|
27928
|
+
estimate = await candidates[0].estimate(dispatch);
|
|
27643
27929
|
} catch {
|
|
27644
27930
|
}
|
|
27645
27931
|
}
|
|
@@ -27647,85 +27933,80 @@ var require_shuttle = __commonJS({
|
|
|
27647
27933
|
await observerChain.notify({ kind: "spend.preflight", jobId, attendanceId, estimate });
|
|
27648
27934
|
} catch (err) {
|
|
27649
27935
|
const reason = err instanceof chain_1.SpendCapExceeded ? "refused_over_cap" : `preflight rejected: ${err instanceof Error ? err.message : String(err)}`;
|
|
27650
|
-
|
|
27651
|
-
|
|
27652
|
-
|
|
27653
|
-
|
|
27654
|
-
|
|
27655
|
-
|
|
27656
|
-
|
|
27657
|
-
|
|
27658
|
-
|
|
27659
|
-
|
|
27660
|
-
|
|
27661
|
-
|
|
27662
|
-
|
|
27663
|
-
|
|
27664
|
-
|
|
27665
|
-
|
|
27666
|
-
|
|
27667
|
-
|
|
27668
|
-
|
|
27669
|
-
|
|
27936
|
+
return close({ status: "failed", reason });
|
|
27937
|
+
}
|
|
27938
|
+
const runOn = async (executor) => {
|
|
27939
|
+
await observerChain.notify({ kind: "executor.dispatch.started", jobId, attendanceId, executor: executor.capability.id, strategy }, onObserverError);
|
|
27940
|
+
const dispatchStartedAt = Date.now();
|
|
27941
|
+
const outcome = await (0, run_dispatch_1.runDispatch)(dispatch, executor, {
|
|
27942
|
+
credentials: this.broker,
|
|
27943
|
+
signal,
|
|
27944
|
+
reportProgress: (channel, frames) => {
|
|
27945
|
+
void jobsClient.postProgress(jobId, { channel, frames }).then(() => activity.record()).catch(() => {
|
|
27946
|
+
});
|
|
27947
|
+
}
|
|
27948
|
+
});
|
|
27949
|
+
if (outcome.kind === "executor-failed") {
|
|
27950
|
+
const err = outcome.error;
|
|
27951
|
+
const reason = `executor failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
27952
|
+
if (this.broker === null && (0, types_1.isExecutorEnvironmentError)(err)) {
|
|
27953
|
+
this.markUnwell(executor, err, subscribeLogger);
|
|
27954
|
+
return { kind: "environment", reason };
|
|
27955
|
+
}
|
|
27956
|
+
if ((0, types_1.isExecutorModelUnavailableError)(err)) {
|
|
27957
|
+
return { kind: "result", result: { status: "failed", reason, failureCode: types_1.MODEL_UNAVAILABLE } };
|
|
27958
|
+
}
|
|
27959
|
+
return { kind: "result", result: { status: "failed", reason } };
|
|
27670
27960
|
}
|
|
27671
|
-
|
|
27672
|
-
|
|
27673
|
-
|
|
27674
|
-
|
|
27961
|
+
if (outcome.kind === "gate-failed") {
|
|
27962
|
+
return { kind: "result", result: { status: "failed", reason: outcome.reason } };
|
|
27963
|
+
}
|
|
27964
|
+
const response = outcome.response;
|
|
27965
|
+
await observerChain.notify({
|
|
27966
|
+
kind: "executor.dispatch.completed",
|
|
27967
|
+
jobId,
|
|
27968
|
+
attendanceId,
|
|
27969
|
+
executor: executor.capability.id,
|
|
27970
|
+
response: { rawText: response.rawText ?? "", parsed: response.parsed, usage: response.usage },
|
|
27971
|
+
durationMs: Date.now() - dispatchStartedAt
|
|
27972
|
+
}, onObserverError);
|
|
27973
|
+
const outputs = [...response.outputs];
|
|
27974
|
+
if (response.usage) {
|
|
27975
|
+
outputs.push({
|
|
27976
|
+
label: "usage",
|
|
27977
|
+
content: { ...response.usage, executor: executor.capability.id }
|
|
27675
27978
|
});
|
|
27676
|
-
},
|
|
27677
|
-
workspace: preparedWorkspace,
|
|
27678
|
-
credentials: this.broker
|
|
27679
|
-
};
|
|
27680
|
-
let response;
|
|
27681
|
-
try {
|
|
27682
|
-
response = await executor.execute(dispatch, signal, executionCtx);
|
|
27683
|
-
} catch (err) {
|
|
27684
|
-
const reason = `executor failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
27685
|
-
if (this.broker === null && (0, types_1.isExecutorEnvironmentError)(err)) {
|
|
27686
|
-
this.pauseForEnvironment(executor, err, subscribeLogger);
|
|
27687
27979
|
}
|
|
27688
|
-
|
|
27689
|
-
|
|
27690
|
-
|
|
27691
|
-
|
|
27692
|
-
|
|
27693
|
-
|
|
27694
|
-
|
|
27695
|
-
|
|
27696
|
-
|
|
27697
|
-
|
|
27698
|
-
|
|
27699
|
-
|
|
27700
|
-
|
|
27701
|
-
|
|
27702
|
-
|
|
27703
|
-
attendanceId,
|
|
27704
|
-
executor: executor.capability.id,
|
|
27705
|
-
response: { rawText: response.rawText ?? "", parsed: response.parsed, usage: response.usage },
|
|
27706
|
-
durationMs: Date.now() - dispatchStartedAt
|
|
27707
|
-
}, onObserverError);
|
|
27708
|
-
const outputs = [...response.outputs];
|
|
27709
|
-
if (response.usage) {
|
|
27710
|
-
outputs.push({
|
|
27711
|
-
label: "usage",
|
|
27712
|
-
content: { ...response.usage, executor: executor.capability.id }
|
|
27713
|
-
});
|
|
27714
|
-
}
|
|
27715
|
-
for (const output of outputs) {
|
|
27716
|
-
await observerChain.notify({ kind: "output.submitted", jobId, attendanceId, label: output.label, content: output.content }, onObserverError);
|
|
27717
|
-
}
|
|
27718
|
-
await observerChain.notify({ kind: "attendance.closed", jobId, attendanceId, status: "completed", totalDurationMs: Date.now() - startedAt }, onObserverError);
|
|
27719
|
-
return { status: "completed", outputs };
|
|
27980
|
+
for (const output of outputs) {
|
|
27981
|
+
await observerChain.notify({ kind: "output.submitted", jobId, attendanceId, label: output.label, content: output.content }, onObserverError);
|
|
27982
|
+
}
|
|
27983
|
+
return { kind: "result", result: { status: "completed", outputs } };
|
|
27984
|
+
};
|
|
27985
|
+
for (const [i, executor] of candidates.entries()) {
|
|
27986
|
+
const outcome = await runOn(executor);
|
|
27987
|
+
if (outcome.kind === "result")
|
|
27988
|
+
return close(outcome.result);
|
|
27989
|
+
const next = candidates[i + 1];
|
|
27990
|
+
if (!next)
|
|
27991
|
+
return close({ status: "failed", reason: outcome.reason });
|
|
27992
|
+
subscribeLogger.info(`${executor.capability.id} cannot run jobs on this machine, so job ${jobId} runs on ${next.capability.id} instead.`);
|
|
27993
|
+
}
|
|
27994
|
+
return close({ status: "failed", reason: `no executor for shuttle strategy "${strategy}"` });
|
|
27720
27995
|
};
|
|
27721
27996
|
const pools = this.config.pools.map((p) => p.id ? { id: p.id } : { name: p.name });
|
|
27722
|
-
const poolExecutors = new Map(pools.map((ref, i) => [ref, this.config.pools[i].executor]));
|
|
27723
27997
|
const poolMetadata = (ref) => {
|
|
27724
|
-
const
|
|
27725
|
-
|
|
27726
|
-
|
|
27998
|
+
const reported = chooser.orderFor(ref).map((e) => {
|
|
27999
|
+
const models = modelsByExecutor.get(e.capability.id) ?? [];
|
|
28000
|
+
return { id: e.capability.id, ...models.length > 0 ? { models } : {} };
|
|
28001
|
+
});
|
|
28002
|
+
const [first] = reported;
|
|
28003
|
+
if (!first)
|
|
27727
28004
|
return void 0;
|
|
27728
|
-
return {
|
|
28005
|
+
return {
|
|
28006
|
+
executors: reported,
|
|
28007
|
+
executor: first.id,
|
|
28008
|
+
...first.models ? { models: first.models } : {}
|
|
28009
|
+
};
|
|
27729
28010
|
};
|
|
27730
28011
|
const attemptedUpgrades = /* @__PURE__ */ new Set();
|
|
27731
28012
|
this.subscription = (0, jobs_1.subscribe)({
|
|
@@ -27747,6 +28028,9 @@ var require_shuttle = __commonJS({
|
|
|
27747
28028
|
poolMetadata
|
|
27748
28029
|
},
|
|
27749
28030
|
onJob,
|
|
28031
|
+
// Decline, at discovery, a job that requires an executor this runner
|
|
28032
|
+
// does not have; it stays queued for a member that has it (ADR 0118).
|
|
28033
|
+
accepts: (job) => chooser.accepts(job.tags),
|
|
27750
28034
|
onDirectives: async (directives) => {
|
|
27751
28035
|
const decommission = (0, decommission_1.readDecommissionDirective)(directives);
|
|
27752
28036
|
if (decommission) {
|
|
@@ -27831,20 +28115,31 @@ var require_shuttle = __commonJS({
|
|
|
27831
28115
|
this.subscription?.done().catch((err) => this.lifetime.reject(err));
|
|
27832
28116
|
}
|
|
27833
28117
|
/**
|
|
27834
|
-
*
|
|
27835
|
-
*
|
|
27836
|
-
*
|
|
27837
|
-
* a
|
|
28118
|
+
* Note that an executor cannot run jobs on this machine, and keep checking
|
|
28119
|
+
* until it can. While another executor can, jobs that do not require this
|
|
28120
|
+
* one run there; once none can, claiming pauses, so a signed-out laptop does
|
|
28121
|
+
* not burn a queue of reviews one failure at a time. One warning says why
|
|
28122
|
+
* and what to do; the re-checks stay at debug; one line says when it works
|
|
28123
|
+
* again. Idempotent: a second failing job on the same executor changes
|
|
28124
|
+
* nothing.
|
|
27838
28125
|
*/
|
|
27839
|
-
|
|
27840
|
-
|
|
28126
|
+
markUnwell(executor, err, logger) {
|
|
28127
|
+
const id = executor.capability.id;
|
|
28128
|
+
if (this.unwell.has(id) || !this.subscription)
|
|
27841
28129
|
return;
|
|
27842
|
-
this.
|
|
27843
|
-
this.
|
|
27844
|
-
|
|
28130
|
+
this.unwell.set(id, { since: Date.now(), err });
|
|
28131
|
+
const others = this.executors.filter((e) => !this.unwell.has(e.capability.id)).map((e) => e.capability.id);
|
|
28132
|
+
if (others.length === 0) {
|
|
28133
|
+
this.environmentHeld = true;
|
|
28134
|
+
this.subscription.pause(ENVIRONMENT_HOLD);
|
|
28135
|
+
logger.warn(`Claiming paused: ${id} cannot run jobs on this machine (${err.message}). To fix it, ${err.remedy}. The ${this.brand.product.title} checks again on its own and resumes claiming when it works.`);
|
|
28136
|
+
} else {
|
|
28137
|
+
logger.warn(`${id} cannot run jobs on this machine (${err.message}). To fix it, ${err.remedy}. Until then, jobs that do not require ${id} run on ${others.join(", ")}; the ${this.brand.product.title} checks ${id} again on its own.`);
|
|
28138
|
+
}
|
|
27845
28139
|
void this.recheckEnvironment(executor, logger);
|
|
27846
28140
|
}
|
|
27847
28141
|
async recheckEnvironment(executor, logger) {
|
|
28142
|
+
const id = executor.capability.id;
|
|
27848
28143
|
const signal = this.stopping.signal;
|
|
27849
28144
|
let delay = this.environmentRecheck.initialMs;
|
|
27850
28145
|
for (; ; ) {
|
|
@@ -27860,15 +28155,21 @@ var require_shuttle = __commonJS({
|
|
|
27860
28155
|
if (signal.aborted)
|
|
27861
28156
|
return;
|
|
27862
28157
|
if (readiness.ready) {
|
|
27863
|
-
const
|
|
27864
|
-
this.
|
|
27865
|
-
|
|
27866
|
-
|
|
28158
|
+
const since = this.unwell.get(id)?.since ?? Date.now();
|
|
28159
|
+
this.unwell.delete(id);
|
|
28160
|
+
const lasted = formatDuration(Date.now() - since);
|
|
28161
|
+
if (this.environmentHeld) {
|
|
28162
|
+
this.environmentHeld = false;
|
|
28163
|
+
this.subscription?.resume(ENVIRONMENT_HOLD);
|
|
28164
|
+
logger.info(`${id} can run jobs again; claiming resumed after ${lasted} paused.`);
|
|
28165
|
+
} else {
|
|
28166
|
+
logger.info(`${id} can run jobs again after ${lasted}.`);
|
|
28167
|
+
}
|
|
27867
28168
|
return;
|
|
27868
28169
|
}
|
|
27869
28170
|
delay = Math.min(delay * 2, this.environmentRecheck.maxMs);
|
|
27870
28171
|
logger.debug?.("executor still cannot run jobs", {
|
|
27871
|
-
executor:
|
|
28172
|
+
executor: id,
|
|
27872
28173
|
reason: readiness.reason,
|
|
27873
28174
|
nextCheckIn: formatDuration(delay)
|
|
27874
28175
|
});
|
|
@@ -28356,6 +28657,212 @@ var require_revoke = __commonJS({
|
|
|
28356
28657
|
}
|
|
28357
28658
|
});
|
|
28358
28659
|
|
|
28660
|
+
// ../../packages/shuttle/dist/config/executor-order.js
|
|
28661
|
+
var require_executor_order = __commonJS({
|
|
28662
|
+
"../../packages/shuttle/dist/config/executor-order.js"(exports2) {
|
|
28663
|
+
"use strict";
|
|
28664
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
28665
|
+
exports2.executorOrder = executorOrder;
|
|
28666
|
+
exports2.foldPoolExecutors = foldPoolExecutors;
|
|
28667
|
+
exports2.addExecutor = addExecutor;
|
|
28668
|
+
exports2.removeExecutor = removeExecutor;
|
|
28669
|
+
var yaml_1 = require_dist3();
|
|
28670
|
+
function executorOrder(doc) {
|
|
28671
|
+
const map = doc.get("executors", true);
|
|
28672
|
+
if (!(0, yaml_1.isMap)(map))
|
|
28673
|
+
return [];
|
|
28674
|
+
return map.items.flatMap((pair) => (0, yaml_1.isScalar)(pair.key) ? [String(pair.key.value)] : []);
|
|
28675
|
+
}
|
|
28676
|
+
function executorsMap(doc) {
|
|
28677
|
+
const existing = doc.get("executors", true);
|
|
28678
|
+
if ((0, yaml_1.isMap)(existing))
|
|
28679
|
+
return existing;
|
|
28680
|
+
const created = doc.createNode({});
|
|
28681
|
+
doc.set("executors", created);
|
|
28682
|
+
return created;
|
|
28683
|
+
}
|
|
28684
|
+
function indexOf(map, id) {
|
|
28685
|
+
return map.items.findIndex((pair) => (0, yaml_1.isScalar)(pair.key) && pair.key.value === id);
|
|
28686
|
+
}
|
|
28687
|
+
function foldPoolExecutors(doc) {
|
|
28688
|
+
const pools = doc.get("pools", true);
|
|
28689
|
+
if (!(0, yaml_1.isSeq)(pools))
|
|
28690
|
+
return null;
|
|
28691
|
+
let named = null;
|
|
28692
|
+
for (const pool of pools.items) {
|
|
28693
|
+
if (!(0, yaml_1.isMap)(pool))
|
|
28694
|
+
continue;
|
|
28695
|
+
const value = pool.get("executor");
|
|
28696
|
+
if (typeof value === "string" && named === null)
|
|
28697
|
+
named = value;
|
|
28698
|
+
pool.delete("executor");
|
|
28699
|
+
}
|
|
28700
|
+
if (named === null)
|
|
28701
|
+
return null;
|
|
28702
|
+
const map = executorsMap(doc);
|
|
28703
|
+
const at = indexOf(map, named);
|
|
28704
|
+
if (at > 0) {
|
|
28705
|
+
const [pair] = map.items.splice(at, 1);
|
|
28706
|
+
map.items.unshift(pair);
|
|
28707
|
+
}
|
|
28708
|
+
return named;
|
|
28709
|
+
}
|
|
28710
|
+
function addExecutor(doc, id, block, options = {}) {
|
|
28711
|
+
const map = executorsMap(doc);
|
|
28712
|
+
const at = indexOf(map, id);
|
|
28713
|
+
if (at >= 0) {
|
|
28714
|
+
if (!options.first || at === 0)
|
|
28715
|
+
return "unchanged";
|
|
28716
|
+
const [pair2] = map.items.splice(at, 1);
|
|
28717
|
+
map.items.unshift(pair2);
|
|
28718
|
+
return "moved";
|
|
28719
|
+
}
|
|
28720
|
+
const pair = doc.createPair(id, block);
|
|
28721
|
+
if (options.first)
|
|
28722
|
+
map.items.unshift(pair);
|
|
28723
|
+
else
|
|
28724
|
+
map.items.push(pair);
|
|
28725
|
+
return "added";
|
|
28726
|
+
}
|
|
28727
|
+
function removeExecutor(doc, id) {
|
|
28728
|
+
const map = executorsMap(doc);
|
|
28729
|
+
const at = indexOf(map, id);
|
|
28730
|
+
if (at < 0)
|
|
28731
|
+
return "absent";
|
|
28732
|
+
if (map.items.length === 1)
|
|
28733
|
+
return "last";
|
|
28734
|
+
map.items.splice(at, 1);
|
|
28735
|
+
return "removed";
|
|
28736
|
+
}
|
|
28737
|
+
}
|
|
28738
|
+
});
|
|
28739
|
+
|
|
28740
|
+
// ../../packages/shuttle/dist/cli/executors.js
|
|
28741
|
+
var require_executors = __commonJS({
|
|
28742
|
+
"../../packages/shuttle/dist/cli/executors.js"(exports2) {
|
|
28743
|
+
"use strict";
|
|
28744
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
28745
|
+
exports2.buildAddCommand = buildAddCommand;
|
|
28746
|
+
exports2.buildRemoveCommand = buildRemoveCommand;
|
|
28747
|
+
var fs_1 = require("fs");
|
|
28748
|
+
var commander_1 = require_commander();
|
|
28749
|
+
var yaml_1 = require_dist3();
|
|
28750
|
+
var apply_1 = require_apply();
|
|
28751
|
+
var loader_1 = require_loader();
|
|
28752
|
+
var executor_order_1 = require_executor_order();
|
|
28753
|
+
var preflight_1 = require_preflight();
|
|
28754
|
+
function target(brand, options) {
|
|
28755
|
+
const profile = (0, apply_1.resolveProfile)(brand, options.profile);
|
|
28756
|
+
try {
|
|
28757
|
+
const path = (0, loader_1.resolveConfigPath)({
|
|
28758
|
+
explicitPath: options.config,
|
|
28759
|
+
searchPaths: (0, apply_1.runConfigSearchPaths)(brand, profile),
|
|
28760
|
+
productId: brand.product.id
|
|
28761
|
+
});
|
|
28762
|
+
return { path, profile };
|
|
28763
|
+
} catch (err) {
|
|
28764
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
28765
|
+
console.error(`Run \`${brand.product.cliBinary} init\` first: it writes the config this edits.`);
|
|
28766
|
+
process.exit(1);
|
|
28767
|
+
}
|
|
28768
|
+
}
|
|
28769
|
+
function allowed(brand, id) {
|
|
28770
|
+
return brand.executorAllowlist[0] === "*" || brand.executorAllowlist.includes(id);
|
|
28771
|
+
}
|
|
28772
|
+
function orderLine(order) {
|
|
28773
|
+
return order.length === 1 ? `Every job runs on ${order[0]}.` : `A job that names no executor tries them in this order: ${order.join(", ")}. A job that names one runs on that one or fails.`;
|
|
28774
|
+
}
|
|
28775
|
+
function foldedLine(folded) {
|
|
28776
|
+
return folded === null ? [] : [`Your pools named ${folded} as their executor, a setting from before 0.34; it is first in the order instead now.`];
|
|
28777
|
+
}
|
|
28778
|
+
async function newFailures(brand, t, write, restore) {
|
|
28779
|
+
const paths = (0, apply_1.resolvePaths)(brand, t.profile);
|
|
28780
|
+
const run = () => (0, preflight_1.runPreflight)((0, preflight_1.createProbes)({
|
|
28781
|
+
brand,
|
|
28782
|
+
paths,
|
|
28783
|
+
configSearchPaths: (0, apply_1.runConfigSearchPaths)(brand, t.profile),
|
|
28784
|
+
explicitConfigPath: t.path
|
|
28785
|
+
}), { brand, paths, phase: "doctor", deep: false });
|
|
28786
|
+
const before = await run();
|
|
28787
|
+
write();
|
|
28788
|
+
try {
|
|
28789
|
+
const after = await run();
|
|
28790
|
+
const failedBefore = new Set(before.verdicts.filter((v) => v.status === "FAIL").map((v) => v.name));
|
|
28791
|
+
return after.verdicts.filter((v) => v.status === "FAIL" && !failedBefore.has(v.name));
|
|
28792
|
+
} catch (err) {
|
|
28793
|
+
restore();
|
|
28794
|
+
throw err;
|
|
28795
|
+
}
|
|
28796
|
+
}
|
|
28797
|
+
function buildAddCommand(brand) {
|
|
28798
|
+
const add = new commander_1.Command("add").description(`Add to this ${brand.product.title}'s setup`);
|
|
28799
|
+
add.command("executor <id>").description(`Add an executor this ${brand.product.title} may run jobs on`).option("--first", "Put it first in the order, so a job that names no executor tries it first").option("--tmp-dir <dir>", "Base directory for each job's throwaway checkout (agent executors)").option("--config <path>", "Path to the runtime YAML to edit").option("-p, --profile <name>", 'Config profile to edit (default "default")').action(async (id, options) => {
|
|
28800
|
+
if (!allowed(brand, id)) {
|
|
28801
|
+
console.error(`${id} is not an executor this build runs. It runs: ${brand.executorAllowlist.join(", ")}.`);
|
|
28802
|
+
process.exit(1);
|
|
28803
|
+
}
|
|
28804
|
+
const t = target(brand, options);
|
|
28805
|
+
const original = (0, fs_1.readFileSync)(t.path, "utf8");
|
|
28806
|
+
const doc = (0, yaml_1.parseDocument)(original);
|
|
28807
|
+
const folded = (0, executor_order_1.foldPoolExecutors)(doc);
|
|
28808
|
+
const block = brand.executorBlock?.(id, { ...options.tmpDir ? { tmpDir: options.tmpDir } : {} }) ?? { type: id };
|
|
28809
|
+
const outcome = (0, executor_order_1.addExecutor)(doc, id, block, { first: options.first === true });
|
|
28810
|
+
if (outcome === "unchanged" && folded === null) {
|
|
28811
|
+
console.log(`${id} is already set up. ${orderLine((0, executor_order_1.executorOrder)(doc))}`);
|
|
28812
|
+
return;
|
|
28813
|
+
}
|
|
28814
|
+
const write = () => (0, fs_1.writeFileSync)(t.path, doc.toString());
|
|
28815
|
+
const restore = () => (0, fs_1.writeFileSync)(t.path, original);
|
|
28816
|
+
if (outcome === "added") {
|
|
28817
|
+
const failures = await newFailures(brand, t, write, restore);
|
|
28818
|
+
if (failures.length > 0) {
|
|
28819
|
+
restore();
|
|
28820
|
+
(0, preflight_1.printReport)(failures, false);
|
|
28821
|
+
console.error("");
|
|
28822
|
+
console.error(`${id} was not added: it could not run jobs on this machine. Fix what is above, then run this again.`);
|
|
28823
|
+
process.exit(preflight_1.PREFLIGHT_EXIT_CODE);
|
|
28824
|
+
}
|
|
28825
|
+
} else {
|
|
28826
|
+
write();
|
|
28827
|
+
}
|
|
28828
|
+
const verb = outcome === "added" ? "Added" : outcome === "moved" ? "Moved" : "Kept";
|
|
28829
|
+
console.log(`${verb} ${id}${outcome === "moved" ? " to the front" : ""} in ${t.path}.`);
|
|
28830
|
+
for (const line of foldedLine(folded))
|
|
28831
|
+
console.log(line);
|
|
28832
|
+
console.log(orderLine((0, executor_order_1.executorOrder)(doc)));
|
|
28833
|
+
console.log(`Restart \`${brand.product.cliBinary} run\` for it to take effect.`);
|
|
28834
|
+
});
|
|
28835
|
+
return add;
|
|
28836
|
+
}
|
|
28837
|
+
function buildRemoveCommand(brand) {
|
|
28838
|
+
const remove = new commander_1.Command("remove").description(`Remove from this ${brand.product.title}'s setup`);
|
|
28839
|
+
remove.command("executor <id>").description(`Stop this ${brand.product.title} running jobs on an executor`).option("--config <path>", "Path to the runtime YAML to edit").option("-p, --profile <name>", 'Config profile to edit (default "default")').action((id, options) => {
|
|
28840
|
+
const t = target(brand, options);
|
|
28841
|
+
const doc = (0, yaml_1.parseDocument)((0, fs_1.readFileSync)(t.path, "utf8"));
|
|
28842
|
+
const folded = (0, executor_order_1.foldPoolExecutors)(doc);
|
|
28843
|
+
const outcome = (0, executor_order_1.removeExecutor)(doc, id);
|
|
28844
|
+
if (outcome === "last") {
|
|
28845
|
+
console.error(`${id} is the only executor set up, so it stays: with none, nothing could run.`);
|
|
28846
|
+
console.error(`Add another first with \`${brand.product.cliBinary} add executor <id>\`.`);
|
|
28847
|
+
process.exit(1);
|
|
28848
|
+
}
|
|
28849
|
+
if (outcome === "absent" && folded === null) {
|
|
28850
|
+
console.log(`${id} is not set up. ${orderLine((0, executor_order_1.executorOrder)(doc))}`);
|
|
28851
|
+
return;
|
|
28852
|
+
}
|
|
28853
|
+
(0, fs_1.writeFileSync)(t.path, doc.toString());
|
|
28854
|
+
if (outcome === "removed")
|
|
28855
|
+
console.log(`Removed ${id} from ${t.path}.`);
|
|
28856
|
+
for (const line of foldedLine(folded))
|
|
28857
|
+
console.log(line);
|
|
28858
|
+
console.log(orderLine((0, executor_order_1.executorOrder)(doc)));
|
|
28859
|
+
console.log(`Restart \`${brand.product.cliBinary} run\` for it to take effect.`);
|
|
28860
|
+
});
|
|
28861
|
+
return remove;
|
|
28862
|
+
}
|
|
28863
|
+
}
|
|
28864
|
+
});
|
|
28865
|
+
|
|
28359
28866
|
// ../../packages/shuttle/dist/cli.js
|
|
28360
28867
|
var require_cli = __commonJS({
|
|
28361
28868
|
"../../packages/shuttle/dist/cli.js"(exports2) {
|
|
@@ -28371,6 +28878,7 @@ var require_cli = __commonJS({
|
|
|
28371
28878
|
var caps_1 = require_caps();
|
|
28372
28879
|
var list_1 = require_list();
|
|
28373
28880
|
var revoke_1 = require_revoke();
|
|
28881
|
+
var executors_1 = require_executors();
|
|
28374
28882
|
function createCli2(brand) {
|
|
28375
28883
|
const program = new commander_1.Command();
|
|
28376
28884
|
program.name(brand.product.cliBinary).description(brand.product.description).version(brand.product.version);
|
|
@@ -28382,6 +28890,8 @@ var require_cli = __commonJS({
|
|
|
28382
28890
|
program.addCommand((0, caps_1.buildCapsCommand)(brand));
|
|
28383
28891
|
program.addCommand((0, list_1.buildListCommand)(brand));
|
|
28384
28892
|
program.addCommand((0, revoke_1.buildRevokeCommand)(brand));
|
|
28893
|
+
program.addCommand((0, executors_1.buildAddCommand)(brand));
|
|
28894
|
+
program.addCommand((0, executors_1.buildRemoveCommand)(brand));
|
|
28385
28895
|
return program;
|
|
28386
28896
|
}
|
|
28387
28897
|
}
|
|
@@ -28392,8 +28902,8 @@ var require_dist5 = __commonJS({
|
|
|
28392
28902
|
"../../packages/shuttle/dist/index.js"(exports2) {
|
|
28393
28903
|
"use strict";
|
|
28394
28904
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
28395
|
-
exports2.
|
|
28396
|
-
exports2.revokePairing = exports2.listPairings = exports2.PairingConfigStore = exports2.pair = exports2.scaffoldedConfigPath = exports2.planScaffold = exports2.DEFAULT_REFUSAL_MESSAGE = exports2.DEFAULT_MONTHLY_PERIOD = void 0;
|
|
28905
|
+
exports2.renderEnvironmentReport = exports2.isWorthReporting = exports2.hostOf = exports2.executorDefaultsFor = exports2.environmentReportJson = exports2.environmentPolledBy = exports2.applyEnvironment = exports2.renderTemplate = exports2.expandHome = exports2.resolvePaths = exports2.SpendStore = exports2.AuditLogStore = exports2.createSpendTrackerObserver = exports2.createAuditLogObserver = exports2.createLoggerObserver = exports2.SpendCapExceeded = exports2.ObserverChain = exports2.createCustomScriptExecutor = exports2.createWebhookExecutor = exports2.createHttpApiExecutor = exports2.createCopilotExecutor = exports2.createCodexExecutor = exports2.createClaudeCodeExecutor = exports2.MODEL_UNAVAILABLE = exports2.ExecutorModelUnavailableError = exports2.ExecutorEnvironmentError = exports2.ExecutorRegistry = exports2.AgentCredentialRevokedError = exports2.runPreflight = exports2.renderLines = exports2.renderJson = exports2.printReport = exports2.hasFailure = exports2.createProbes = exports2.checksFor = exports2.PREFLIGHT_FLOORS = exports2.PREFLIGHT_EXIT_CODE = exports2.CHECKS = exports2.readResponseLatestVersion = exports2.checkResponseMinVersion = exports2.compareSemver = exports2.UpgradeRequiredError = exports2.LATEST_VERSION_HEADER = exports2.MIN_VERSION_HEADER = exports2.loadConfig = exports2.GATE_REPAIR_BUDGET = exports2.mergeRepairedResponse = exports2.runDispatch = exports2.Shuttle = exports2.createCli = void 0;
|
|
28906
|
+
exports2.revokePairing = exports2.listPairings = exports2.PairingConfigStore = exports2.pair = exports2.scaffoldedConfigPath = exports2.planScaffold = exports2.DEFAULT_REFUSAL_MESSAGE = exports2.DEFAULT_MONTHLY_PERIOD = exports2.DEFAULT_DAILY_PERIOD = exports2.SUBSTRATE_BRAND = exports2.verificationJson = exports2.resolveEnvironment = exports2.renderVerificationLine = void 0;
|
|
28397
28907
|
var cli_1 = require_cli();
|
|
28398
28908
|
Object.defineProperty(exports2, "createCli", { enumerable: true, get: function() {
|
|
28399
28909
|
return cli_1.createCli;
|
|
@@ -28402,6 +28912,16 @@ var require_dist5 = __commonJS({
|
|
|
28402
28912
|
Object.defineProperty(exports2, "Shuttle", { enumerable: true, get: function() {
|
|
28403
28913
|
return shuttle_1.Shuttle;
|
|
28404
28914
|
} });
|
|
28915
|
+
var run_dispatch_1 = require_run_dispatch();
|
|
28916
|
+
Object.defineProperty(exports2, "runDispatch", { enumerable: true, get: function() {
|
|
28917
|
+
return run_dispatch_1.runDispatch;
|
|
28918
|
+
} });
|
|
28919
|
+
Object.defineProperty(exports2, "mergeRepairedResponse", { enumerable: true, get: function() {
|
|
28920
|
+
return run_dispatch_1.mergeRepairedResponse;
|
|
28921
|
+
} });
|
|
28922
|
+
Object.defineProperty(exports2, "GATE_REPAIR_BUDGET", { enumerable: true, get: function() {
|
|
28923
|
+
return run_dispatch_1.GATE_REPAIR_BUDGET;
|
|
28924
|
+
} });
|
|
28405
28925
|
var loader_1 = require_loader();
|
|
28406
28926
|
Object.defineProperty(exports2, "loadConfig", { enumerable: true, get: function() {
|
|
28407
28927
|
return loader_1.loadConfig;
|
|
@@ -28468,6 +28988,12 @@ var require_dist5 = __commonJS({
|
|
|
28468
28988
|
Object.defineProperty(exports2, "ExecutorEnvironmentError", { enumerable: true, get: function() {
|
|
28469
28989
|
return types_1.ExecutorEnvironmentError;
|
|
28470
28990
|
} });
|
|
28991
|
+
Object.defineProperty(exports2, "ExecutorModelUnavailableError", { enumerable: true, get: function() {
|
|
28992
|
+
return types_1.ExecutorModelUnavailableError;
|
|
28993
|
+
} });
|
|
28994
|
+
Object.defineProperty(exports2, "MODEL_UNAVAILABLE", { enumerable: true, get: function() {
|
|
28995
|
+
return types_1.MODEL_UNAVAILABLE;
|
|
28996
|
+
} });
|
|
28471
28997
|
var claude_code_1 = require_claude_code();
|
|
28472
28998
|
Object.defineProperty(exports2, "createClaudeCodeExecutor", { enumerable: true, get: function() {
|
|
28473
28999
|
return claude_code_1.createClaudeCodeExecutor;
|
|
@@ -28606,7 +29132,7 @@ var import_path = require("path");
|
|
|
28606
29132
|
var import_promises = require("fs/promises");
|
|
28607
29133
|
var import_yaml = __toESM(require_dist3());
|
|
28608
29134
|
var import_shuttle = __toESM(require_dist5());
|
|
28609
|
-
var buildVersion = true ? "0.
|
|
29135
|
+
var buildVersion = true ? "0.35.0" : pkg.version;
|
|
28610
29136
|
var AGENT_EXECUTORS = ["claude-code", "codex", "copilot"];
|
|
28611
29137
|
var sifterBrand = {
|
|
28612
29138
|
product: {
|
|
@@ -28635,6 +29161,8 @@ var sifterBrand = {
|
|
|
28635
29161
|
// sifter.yaml names one. The init pre-flight reads it too, to check git and
|
|
28636
29162
|
// claude before the pairing code is spent.
|
|
28637
29163
|
defaultExecutor: "claude-code",
|
|
29164
|
+
// The block a fresh executor gets, from `init` and from `add executor`.
|
|
29165
|
+
executorBlock: buildExecutorBlock,
|
|
28638
29166
|
// Floors the pre-flight enforces on the binaries the claude-code executor
|
|
28639
29167
|
// spawns. Both are deliberately conservative — below the floor FAILS, so a
|
|
28640
29168
|
// number chosen for tidiness rather than necessity would refuse a working
|
|
@@ -28778,7 +29306,8 @@ var sifterBrand = {
|
|
|
28778
29306
|
const executorBlock = plan.keptBlock !== void 0 ? {
|
|
28779
29307
|
...plan.keptBlock,
|
|
28780
29308
|
...AGENT_EXECUTORS.includes(executor) && ctx.setupOptions.tmpDir ? { tmpDir: ctx.setupOptions.tmpDir } : {}
|
|
28781
|
-
} :
|
|
29309
|
+
} : buildExecutorBlock(executor, { ...ctx.setupOptions.tmpDir ? { tmpDir: ctx.setupOptions.tmpDir } : {} });
|
|
29310
|
+
const { [executor]: _replaced, ...otherExecutors } = existingExecutors;
|
|
28782
29311
|
const doc = {
|
|
28783
29312
|
auth: {
|
|
28784
29313
|
jobsApiUrl: pairing.jobsApiUrl
|
|
@@ -28789,12 +29318,11 @@ var sifterBrand = {
|
|
|
28789
29318
|
},
|
|
28790
29319
|
pools: pairing.jobPools.map((p) => ({
|
|
28791
29320
|
id: p.id,
|
|
28792
|
-
name: p.name
|
|
28793
|
-
executor
|
|
29321
|
+
name: p.name
|
|
28794
29322
|
})),
|
|
28795
29323
|
executors: {
|
|
28796
|
-
|
|
28797
|
-
|
|
29324
|
+
[executor]: executorBlock,
|
|
29325
|
+
...otherExecutors
|
|
28798
29326
|
}
|
|
28799
29327
|
};
|
|
28800
29328
|
const pollIntervalMs = ctx.setupOptions.pollIntervalMs ?? existing.polling?.intervalMs;
|
|
@@ -28813,14 +29341,14 @@ var sifterBrand = {
|
|
|
28813
29341
|
function overlayOrigin(origin) {
|
|
28814
29342
|
return Object.fromEntries(AGENT_EXECUTORS.map((e) => [e, { overlayAllowedHosts: [origin] }]));
|
|
28815
29343
|
}
|
|
28816
|
-
|
|
29344
|
+
function buildExecutorBlock(executor, options) {
|
|
28817
29345
|
switch (executor) {
|
|
28818
29346
|
case "claude-code":
|
|
28819
29347
|
case "codex":
|
|
28820
29348
|
case "copilot": {
|
|
28821
29349
|
return {
|
|
28822
29350
|
type: executor,
|
|
28823
|
-
...
|
|
29351
|
+
...options.tmpDir ? { tmpDir: options.tmpDir } : {}
|
|
28824
29352
|
};
|
|
28825
29353
|
}
|
|
28826
29354
|
case "anthropic-api": {
|