@whittlelabs/sifter 0.37.1 → 0.38.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin.js +53 -38
- package/bin.js.map +4 -4
- package/package.json +1 -1
package/bin.js
CHANGED
|
@@ -10632,6 +10632,26 @@ var require_workspace_telemetry = __commonJS({
|
|
|
10632
10632
|
}
|
|
10633
10633
|
});
|
|
10634
10634
|
|
|
10635
|
+
// ../../packages/shuttle/dist/executors/model-providers.js
|
|
10636
|
+
var require_model_providers = __commonJS({
|
|
10637
|
+
"../../packages/shuttle/dist/executors/model-providers.js"(exports2) {
|
|
10638
|
+
"use strict";
|
|
10639
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
10640
|
+
exports2.MODEL_PROVIDER_ENV = void 0;
|
|
10641
|
+
exports2.requireModelProvider = requireModelProvider;
|
|
10642
|
+
exports2.MODEL_PROVIDER_ENV = {
|
|
10643
|
+
anthropic: "ANTHROPIC_API_KEY"
|
|
10644
|
+
};
|
|
10645
|
+
function requireModelProvider(executor, accepts, credential) {
|
|
10646
|
+
const provider = credential.provider;
|
|
10647
|
+
if (!provider || !accepts.includes(provider)) {
|
|
10648
|
+
throw new Error(`The ${executor} executor runs ${accepts.join(" or ")} models, and this customer's model key is ${provider ? `for ${provider}` : "for an unstated provider"}.`);
|
|
10649
|
+
}
|
|
10650
|
+
return provider;
|
|
10651
|
+
}
|
|
10652
|
+
}
|
|
10653
|
+
});
|
|
10654
|
+
|
|
10635
10655
|
// ../../packages/shuttle/dist/executors/cli-version.js
|
|
10636
10656
|
var require_cli_version = __commonJS({
|
|
10637
10657
|
"../../packages/shuttle/dist/executors/cli-version.js"(exports2) {
|
|
@@ -10736,6 +10756,8 @@ var require_claude_code = __commonJS({
|
|
|
10736
10756
|
var json_answer_1 = require_json_answer();
|
|
10737
10757
|
var models_1 = require_models();
|
|
10738
10758
|
var workspace_telemetry_1 = require_workspace_telemetry();
|
|
10759
|
+
var model_providers_1 = require_model_providers();
|
|
10760
|
+
var CLAUDE_CODE_PROVIDERS = ["anthropic"];
|
|
10739
10761
|
var cli_version_1 = require_cli_version();
|
|
10740
10762
|
var apply_1 = require_apply();
|
|
10741
10763
|
var version_check_1 = require_version_check();
|
|
@@ -10849,18 +10871,22 @@ var require_claude_code = __commonJS({
|
|
|
10849
10871
|
async execute(dispatch, signal, ctx) {
|
|
10850
10872
|
const { prompt, spec } = (0, loom_1.renderPromptExecution)(dispatch.inputs);
|
|
10851
10873
|
const workspace = ctx?.workspace ?? null;
|
|
10852
|
-
let
|
|
10874
|
+
let modelEnv = null;
|
|
10853
10875
|
if (ctx?.credentials) {
|
|
10854
10876
|
const hints = (0, loom_1.pickProviderHints)(spec, "anthropic-api");
|
|
10855
10877
|
const customerId = typeof hints.customerId === "string" ? hints.customerId : void 0;
|
|
10856
10878
|
if (!customerId) {
|
|
10857
10879
|
throw new Error("claude-code dynamic-key mode requires providerHints.anthropicApi.customerId on every job");
|
|
10858
10880
|
}
|
|
10859
|
-
|
|
10881
|
+
const credential = await ctx.credentials.reveal({ name: "model-credential", principal: customerId });
|
|
10882
|
+
if (credential) {
|
|
10883
|
+
const provider = (0, model_providers_1.requireModelProvider)("claude-code", CLAUDE_CODE_PROVIDERS, credential);
|
|
10884
|
+
modelEnv = { [model_providers_1.MODEL_PROVIDER_ENV[provider]]: credential.secret };
|
|
10885
|
+
}
|
|
10860
10886
|
}
|
|
10861
10887
|
let jobScratch = null;
|
|
10862
10888
|
let configDir;
|
|
10863
|
-
if (
|
|
10889
|
+
if (modelEnv) {
|
|
10864
10890
|
jobScratch = await fs_1.promises.mkdtemp(path_1.default.join(os_1.default.tmpdir(), "shuttle-cc-"));
|
|
10865
10891
|
configDir = path_1.default.join(jobScratch, "claude-config");
|
|
10866
10892
|
await fs_1.promises.mkdir(configDir);
|
|
@@ -10869,7 +10895,7 @@ var require_claude_code = __commonJS({
|
|
|
10869
10895
|
let promptOnlyScratch = null;
|
|
10870
10896
|
const reporter = spec.progressChannel && ctx?.reportProgress ? new progress_1.ProgressReporter((frames) => ctx.reportProgress(spec.progressChannel, frames)) : null;
|
|
10871
10897
|
try {
|
|
10872
|
-
const childEnv = buildChildEnv(
|
|
10898
|
+
const childEnv = buildChildEnv(modelEnv, configDir);
|
|
10873
10899
|
const claudeHints = (0, loom_1.pickProviderHints)(spec, "claude-code");
|
|
10874
10900
|
const hintedModel = typeof claudeHints.model === "string" && claudeHints.model.length > 0 ? claudeHints.model : void 0;
|
|
10875
10901
|
const effort = (0, models_1.hintedEffort)(claudeHints);
|
|
@@ -10890,7 +10916,7 @@ var require_claude_code = __commonJS({
|
|
|
10890
10916
|
// Local mode is the operator's own login: a failure of THAT is the
|
|
10891
10917
|
// machine's, and the runner pauses on it. With a revealed key it is one
|
|
10892
10918
|
// customer's, and only their job fails.
|
|
10893
|
-
|
|
10919
|
+
modelEnv === null,
|
|
10894
10920
|
effort
|
|
10895
10921
|
);
|
|
10896
10922
|
if (workspace) {
|
|
@@ -11163,8 +11189,8 @@ var require_claude_code = __commonJS({
|
|
|
11163
11189
|
}
|
|
11164
11190
|
return scoped;
|
|
11165
11191
|
}
|
|
11166
|
-
function buildChildEnv(
|
|
11167
|
-
if (!
|
|
11192
|
+
function buildChildEnv(modelEnv, configDir) {
|
|
11193
|
+
if (!modelEnv && !configDir)
|
|
11168
11194
|
return void 0;
|
|
11169
11195
|
const env = {};
|
|
11170
11196
|
for (const name of HOSTED_ENV_PASSTHROUGH) {
|
|
@@ -11173,7 +11199,7 @@ var require_claude_code = __commonJS({
|
|
|
11173
11199
|
}
|
|
11174
11200
|
return {
|
|
11175
11201
|
...env,
|
|
11176
|
-
...
|
|
11202
|
+
...modelEnv ?? {},
|
|
11177
11203
|
...configDir ? { CLAUDE_CONFIG_DIR: configDir } : {}
|
|
11178
11204
|
};
|
|
11179
11205
|
}
|
|
@@ -12706,31 +12732,18 @@ var require_client = __commonJS({
|
|
|
12706
12732
|
ttlSeconds: request.ttlSeconds
|
|
12707
12733
|
});
|
|
12708
12734
|
}
|
|
12709
|
-
// ──
|
|
12735
|
+
// ── Hosted Sifter ───────────────────────────────────────────────
|
|
12710
12736
|
/**
|
|
12711
|
-
* Reveal a
|
|
12712
|
-
*
|
|
12713
|
-
* `keep:managed-sifter-key-material:read`
|
|
12714
|
-
* `whittle-hosted-sifter` service identity.
|
|
12737
|
+
* Reveal a person's model-provider key for one hosted dispatch, with the
|
|
12738
|
+
* provider it is for (ADR-0127). Service-token only; requires
|
|
12739
|
+
* `keep:managed-sifter-key-material:read` at that user, granted only to the
|
|
12740
|
+
* `whittle-hosted-sifter` service identity. Keep refuses unless the person
|
|
12741
|
+
* holds the hosted tier. Name `provider` when they may hold more than one.
|
|
12715
12742
|
*
|
|
12716
|
-
*
|
|
12717
|
-
* and drop it from memory afterwards. Keep stamps `last_used_at` on
|
|
12718
|
-
* every call and is the audit-of-record for who decrypted whose key
|
|
12719
|
-
* when.
|
|
12720
|
-
*/
|
|
12721
|
-
async revealManagedSifterKey(userId) {
|
|
12722
|
-
return this.request("POST", `/api/managed-sifters/${encodeURIComponent(userId)}/reveal-key`);
|
|
12723
|
-
}
|
|
12724
|
-
/**
|
|
12725
|
-
* Read a user's hosted-Sifter opt-in status. Returns `{enabled:
|
|
12726
|
-
* false}` for users who never opted in (no row) and users who
|
|
12727
|
-
* opted in then disabled. Service-to-service only; requires the
|
|
12728
|
-
* `keep:managed-sifter-enrollments:read` scope, which is distinct
|
|
12729
|
-
* from `keep:managed-sifter-key-material:read` so a service identity
|
|
12730
|
-
* can hold one without the other.
|
|
12743
|
+
* Use the credential for the dispatch and drop it from memory afterwards.
|
|
12731
12744
|
*/
|
|
12732
|
-
async
|
|
12733
|
-
return this.request("
|
|
12745
|
+
async revealModelCredential(userId, options = {}) {
|
|
12746
|
+
return this.request("POST", `/api/users/${encodeURIComponent(userId)}/model-credential`, options.provider ? { provider: options.provider } : {});
|
|
12734
12747
|
}
|
|
12735
12748
|
// ── GitHub OAuth token ──────────────────────────────────────────
|
|
12736
12749
|
/**
|
|
@@ -13358,6 +13371,7 @@ var require_anthropic_api = __commonJS({
|
|
|
13358
13371
|
var keep_1 = require_dist2();
|
|
13359
13372
|
var env_ref_1 = require_env_ref();
|
|
13360
13373
|
var validate_output_1 = require_validate_output();
|
|
13374
|
+
var model_providers_1 = require_model_providers();
|
|
13361
13375
|
var types_1 = require_types2();
|
|
13362
13376
|
var models_1 = require_models();
|
|
13363
13377
|
var DEFAULT_BASE_URL = "https://api.anthropic.com/v1/messages";
|
|
@@ -13605,8 +13619,9 @@ var require_anthropic_api = __commonJS({
|
|
|
13605
13619
|
throw new Error("AnthropicApiExecutor dynamic-key mode failed to exchange a Keep service token. Check KEEP_CLIENT_ID / KEEP_CLIENT_SECRET.");
|
|
13606
13620
|
}
|
|
13607
13621
|
const keep = keepClientFactory({ baseUrl: keepApiUrl, serviceToken });
|
|
13608
|
-
const reveal = await keep.
|
|
13609
|
-
|
|
13622
|
+
const reveal = await keep.revealModelCredential(customerId);
|
|
13623
|
+
(0, model_providers_1.requireModelProvider)("anthropic-api", ["anthropic"], { secret: reveal.credential, provider: reveal.provider });
|
|
13624
|
+
return reveal.credential;
|
|
13610
13625
|
};
|
|
13611
13626
|
}
|
|
13612
13627
|
function safeJsonParse(s) {
|
|
@@ -26642,7 +26657,7 @@ var require_git = __commonJS({
|
|
|
26642
26657
|
let gitToken = null;
|
|
26643
26658
|
if (ref && typeof ref.name === "string" && typeof ref.principal === "string" && options.credentials) {
|
|
26644
26659
|
try {
|
|
26645
|
-
gitToken = await options.credentials.reveal(ref);
|
|
26660
|
+
gitToken = (await options.credentials.reveal(ref))?.secret ?? null;
|
|
26646
26661
|
} catch {
|
|
26647
26662
|
gitToken = null;
|
|
26648
26663
|
}
|
|
@@ -27249,14 +27264,14 @@ var require_registry2 = __commonJS({
|
|
|
27249
27264
|
function getCredentialResolver(name) {
|
|
27250
27265
|
return resolvers.get(name);
|
|
27251
27266
|
}
|
|
27252
|
-
registerCredentialResolver("
|
|
27253
|
-
const reveal = await keep.
|
|
27254
|
-
return reveal.
|
|
27267
|
+
registerCredentialResolver("model-credential", async (keep, principal) => {
|
|
27268
|
+
const reveal = await keep.revealModelCredential(principal);
|
|
27269
|
+
return { secret: reveal.credential, provider: reveal.provider };
|
|
27255
27270
|
});
|
|
27256
27271
|
registerCredentialResolver("github-user-token", async (keep, principal) => {
|
|
27257
27272
|
try {
|
|
27258
27273
|
const reveal = await keep.getUserGithubToken(principal);
|
|
27259
|
-
return reveal.access_token;
|
|
27274
|
+
return { secret: reveal.access_token, provider: "github" };
|
|
27260
27275
|
} catch {
|
|
27261
27276
|
return null;
|
|
27262
27277
|
}
|
|
@@ -29388,7 +29403,7 @@ var import_path = require("path");
|
|
|
29388
29403
|
var import_promises = require("fs/promises");
|
|
29389
29404
|
var import_yaml = __toESM(require_dist3());
|
|
29390
29405
|
var import_shuttle = __toESM(require_dist5());
|
|
29391
|
-
var buildVersion = true ? "0.
|
|
29406
|
+
var buildVersion = true ? "0.38.1" : pkg.version;
|
|
29392
29407
|
var AGENT_EXECUTORS = ["claude-code", "codex", "copilot"];
|
|
29393
29408
|
var sifterBrand = {
|
|
29394
29409
|
product: {
|