claudish 14.15.1 → 14.16.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.
Files changed (2) hide show
  1. package/dist/index.js +535 -201
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -5491,7 +5491,7 @@ var init_onepassword_config = __esm(() => {
5491
5491
  });
5492
5492
 
5493
5493
  // src/version.ts
5494
- var VERSION = "14.15.1";
5494
+ var VERSION = "14.16.1";
5495
5495
 
5496
5496
  // src/redact.ts
5497
5497
  function isPlaceholder(value) {
@@ -49347,10 +49347,11 @@ var init_devin_request = __esm(() => {
49347
49347
  function unaryMetadata(apiKey) {
49348
49348
  return msg(bytes(1, "chisel"), bytes(2, DEVIN_CLI_VERSION), bytes(3, apiKey), bytes(4, "en"), bytes(5, process.platform), bytes(7, DEVIN_CLI_VERSION));
49349
49349
  }
49350
- async function postUnary(path, apiKey) {
49350
+ async function postDevinUnaryRaw(path, apiKey, opts = {}) {
49351
49351
  const url = `${readDevinServerUrl()}${path}`;
49352
+ let response;
49352
49353
  try {
49353
- const response = await fetch(url, {
49354
+ response = await fetch(url, {
49354
49355
  method: "POST",
49355
49356
  headers: {
49356
49357
  authorization: `Basic ${apiKey}-${apiKey}`,
@@ -49358,17 +49359,38 @@ async function postUnary(path, apiKey) {
49358
49359
  "connect-protocol-version": "1"
49359
49360
  },
49360
49361
  body: msg(bytes(1, unaryMetadata(apiKey))),
49361
- signal: AbortSignal.timeout(UNARY_TIMEOUT_MS)
49362
+ signal: opts.signal
49362
49363
  });
49363
- if (!response.ok) {
49364
- log(`[Devin] ${path} failed: HTTP ${response.status}`);
49365
- return null;
49366
- }
49367
- return new Uint8Array(await response.arrayBuffer());
49368
- } catch (err) {
49369
- log(`[Devin] ${path} error: ${err}`);
49364
+ } catch (error) {
49365
+ return { kind: "unreachable", url, error };
49366
+ }
49367
+ if (!response.ok) {
49368
+ return { kind: "answered", url, status: response.status, body: { kind: "unread" } };
49369
+ }
49370
+ try {
49371
+ const bytes = new Uint8Array(await response.arrayBuffer());
49372
+ return { kind: "answered", url, status: response.status, body: { kind: "bytes", bytes } };
49373
+ } catch (error) {
49374
+ return { kind: "answered", url, status: response.status, body: { kind: "read-failed", error } };
49375
+ }
49376
+ }
49377
+ async function postUnary(path, apiKey) {
49378
+ const raw = await postDevinUnaryRaw(path, apiKey, {
49379
+ signal: AbortSignal.timeout(UNARY_TIMEOUT_MS)
49380
+ });
49381
+ if (raw.kind === "unreachable") {
49382
+ log(`[Devin] ${path} error: ${raw.error}`);
49370
49383
  return null;
49371
49384
  }
49385
+ if (raw.status < 200 || raw.status >= 300) {
49386
+ log(`[Devin] ${path} failed: HTTP ${raw.status}`);
49387
+ return null;
49388
+ }
49389
+ if (raw.body.kind === "read-failed") {
49390
+ log(`[Devin] ${path} error: ${raw.body.error}`);
49391
+ return null;
49392
+ }
49393
+ return raw.body.kind === "bytes" ? raw.body.bytes : null;
49372
49394
  }
49373
49395
  function decodeModelDetails(payload) {
49374
49396
  let maxOutput = 0;
@@ -49496,13 +49518,17 @@ async function fetchDevinAllowedUids(apiKey) {
49496
49518
  const body = await postUnary(TEAM_SETTINGS_PATH, apiKey);
49497
49519
  if (!body)
49498
49520
  return [];
49521
+ const uids = decodeAllowedUids(body);
49522
+ log(`[Devin] GetCliTeamSettings: ${uids.length} allowed uids`);
49523
+ return uids;
49524
+ }
49525
+ function decodeAllowedUids(body) {
49499
49526
  const uids = [];
49500
49527
  for (const field of topLevelDelimited(body, 7)) {
49501
49528
  const uid = readString(field).trim();
49502
49529
  if (uid)
49503
49530
  uids.push(uid);
49504
49531
  }
49505
- log(`[Devin] GetCliTeamSettings: ${uids.length} allowed uids`);
49506
49532
  return uids;
49507
49533
  }
49508
49534
  async function getServedDevinModels(opts) {
@@ -53744,6 +53770,7 @@ data: ${JSON.stringify(data)}
53744
53770
  if (frame.flags === FRAME_FLAG_END_OF_STREAM) {
53745
53771
  const raw = new TextDecoder().decode(frame.payload).trim();
53746
53772
  if (!raw || raw === "{}") {
53773
+ opts.onEndOfStream?.();
53747
53774
  finalize("done");
53748
53775
  return;
53749
53776
  }
@@ -55921,6 +55948,27 @@ function startAllowanceFlight() {
55921
55948
  return () => {};
55922
55949
  }
55923
55950
  }
55951
+ function replaceUnsupportedParts(messages, types) {
55952
+ const replacePart = (part) => {
55953
+ if (part?.type === "tool_result" && Array.isArray(part.content)) {
55954
+ return { ...part, content: part.content.map(replacePart) };
55955
+ }
55956
+ if (!types.includes(part?.type))
55957
+ return part;
55958
+ const kind = part.type === "document" ? "document" : "image";
55959
+ return { type: "text", text: `[${kind} omitted: this model does not accept ${kind} input]` };
55960
+ };
55961
+ for (const msg of messages) {
55962
+ if (!Array.isArray(msg.content))
55963
+ continue;
55964
+ msg.content = msg.content.map(replacePart);
55965
+ if (msg.content.length === 1 && msg.content[0].type === "text") {
55966
+ msg.content = msg.content[0].text;
55967
+ } else if (msg.content.length === 0) {
55968
+ msg.content = "";
55969
+ }
55970
+ }
55971
+ }
55924
55972
  function extractAuthHeaders(c) {
55925
55973
  const headers = c.req.header();
55926
55974
  const auth = {};
@@ -56430,20 +56478,24 @@ class ComposedHandler {
56430
56478
  tools = tools.slice(0, maxToolCount);
56431
56479
  }
56432
56480
  if (!this.getModelSupportsVision()) {
56481
+ const isUnsupportedPart = (part) => part?.type === "image_url" || part?.type === "image" || part?.type === "document";
56433
56482
  const imageBlocks = [];
56483
+ let nestedImageCount = 0;
56434
56484
  for (let msgIdx = 0;msgIdx < messages.length; msgIdx++) {
56435
56485
  const msg = messages[msgIdx];
56436
56486
  if (Array.isArray(msg.content)) {
56437
56487
  for (let partIdx = 0;partIdx < msg.content.length; partIdx++) {
56438
56488
  const part = msg.content[partIdx];
56439
- if (part.type === "image_url" || part.type === "image" || part.type === "document") {
56489
+ if (isUnsupportedPart(part)) {
56440
56490
  imageBlocks.push({ msgIdx, partIdx, block: part });
56491
+ } else if (part?.type === "tool_result" && Array.isArray(part.content)) {
56492
+ nestedImageCount += part.content.filter(isUnsupportedPart).length;
56441
56493
  }
56442
56494
  }
56443
56495
  }
56444
56496
  }
56445
- if (imageBlocks.length > 0) {
56446
- log(`[ComposedHandler] Non-vision model received ${imageBlocks.length} image(s), calling vision proxy`);
56497
+ if (imageBlocks.length + nestedImageCount > 0) {
56498
+ log(`[ComposedHandler] Non-vision model received ${imageBlocks.length + nestedImageCount} image(s), calling vision proxy`);
56447
56499
  const openAIImageBlocks = imageBlocks.filter((b) => b.block.type === "image_url");
56448
56500
  let descriptions = null;
56449
56501
  if (openAIImageBlocks.length > 0) {
@@ -56459,28 +56511,10 @@ class ComposedHandler {
56459
56511
  };
56460
56512
  }
56461
56513
  log(`[ComposedHandler] Vision proxy described ${descriptions.length} image(s)`);
56462
- for (const msg of messages) {
56463
- if (Array.isArray(msg.content)) {
56464
- msg.content = msg.content.filter((part) => part.type !== "image" && part.type !== "document");
56465
- if (msg.content.length === 1 && msg.content[0].type === "text") {
56466
- msg.content = msg.content[0].text;
56467
- } else if (msg.content.length === 0) {
56468
- msg.content = "";
56469
- }
56470
- }
56471
- }
56514
+ replaceUnsupportedParts(messages, ["image", "document"]);
56472
56515
  } else {
56473
56516
  log("[ComposedHandler] Stripping image/document blocks (vision not supported)");
56474
- for (const msg of messages) {
56475
- if (Array.isArray(msg.content)) {
56476
- msg.content = msg.content.filter((part) => part.type !== "image_url" && part.type !== "image" && part.type !== "document");
56477
- if (msg.content.length === 1 && msg.content[0].type === "text") {
56478
- msg.content = msg.content[0].text;
56479
- } else if (msg.content.length === 0) {
56480
- msg.content = "";
56481
- }
56482
- }
56483
- }
56517
+ replaceUnsupportedParts(messages, ["image_url", "image", "document"]);
56484
56518
  }
56485
56519
  }
56486
56520
  }
@@ -94280,6 +94314,13 @@ ${h("SUBCOMMANDS")}
94280
94314
  Send the file's Gemini request once through the
94281
94315
  Antigravity login (generateContent, no retry, model
94282
94316
  ${dim("id unchanged); print the raw answer as one JSON line")}
94317
+ ${green("claudish subscription models devin")} ${yellow("--raw --json")}
94318
+ Print Devin's decoded GetCliModelConfigs rows and
94319
+ ${dim("allowed model uids as one JSON line (for models-index)")}
94320
+ ${green("claudish subscription probe devin")} ${yellow("--model <uid> --request-file <path> --raw --json")}
94321
+ Send the file's Anthropic Messages request once through
94322
+ the Devin login (GetChatMessage, no retry, uid unchanged);
94323
+ ${dim("print the decoded answer as one JSON line")}
94283
94324
  ${green("claudish update")} Check for updates and install the latest version
94284
94325
 
94285
94326
  ${bold("Profiles:")}
@@ -110404,6 +110445,94 @@ var init_subscription_antigravity_session = __esm(() => {
110404
110445
  TIMED_OUT = Symbol("timed-out");
110405
110446
  });
110406
110447
 
110448
+ // src/subscription-devin-models.ts
110449
+ var exports_subscription_devin_models = {};
110450
+ __export(exports_subscription_devin_models, {
110451
+ readDevinSecrets: () => readDevinSecrets,
110452
+ runDevinRawModelList: () => runDevinRawModelList
110453
+ });
110454
+ function readDevinSecrets(secrets) {
110455
+ const apiKey = readDevinApiKey();
110456
+ if (!apiKey)
110457
+ return;
110458
+ addSecret(secrets, apiKey);
110459
+ if (apiKey.startsWith(DEVIN_SESSION_TOKEN_PREFIX)) {
110460
+ addSecret(secrets, apiKey.slice(DEVIN_SESSION_TOKEN_PREFIX.length));
110461
+ }
110462
+ return apiKey;
110463
+ }
110464
+ async function postBounded(path, apiKey, timeoutMs) {
110465
+ const controller = new AbortController;
110466
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
110467
+ try {
110468
+ const raw = await postDevinUnaryRaw(path, apiKey, { signal: controller.signal });
110469
+ return { raw, timedOut: controller.signal.aborted };
110470
+ } finally {
110471
+ clearTimeout(timer);
110472
+ }
110473
+ }
110474
+ async function determineDevin(deps, secrets, facts) {
110475
+ const apiKey = readDevinSecrets(secrets);
110476
+ if (!apiKey) {
110477
+ return modelListFail(facts, modelListFailureOf("credential_missing", "devin_credential_absent"));
110478
+ }
110479
+ const configsCall = await postBounded(MODEL_CONFIGS_PATH, apiKey, deps.httpTimeoutMs);
110480
+ facts.sourceUrl = stripUserinfo(configsCall.raw.url);
110481
+ facts.clientVersion = DEVIN_CLI_VERSION;
110482
+ const configsNetwork = configsCall.timedOut ? "model_configs_timeout" : "model_configs_network_error";
110483
+ if (configsCall.raw.kind === "unreachable") {
110484
+ return modelListFail(facts, modelListFailureOf("network", configsNetwork));
110485
+ }
110486
+ facts.fetchedAt = new Date(deps.now()).toISOString();
110487
+ facts.httpStatus = configsCall.raw.status;
110488
+ if (configsCall.raw.status < 200 || configsCall.raw.status >= 300) {
110489
+ return { envelope: buildModelListEnvelope(facts), exitCode: EXIT.ok };
110490
+ }
110491
+ if (configsCall.raw.body.kind !== "bytes") {
110492
+ return modelListFail(facts, modelListFailureOf("network", configsNetwork, configsCall.raw.status));
110493
+ }
110494
+ const configs = decodeModelConfigs(configsCall.raw.body.bytes);
110495
+ if (configs.length === 0) {
110496
+ return modelListFail(facts, modelListFailureOf("list_incomplete", "configs_empty", configsCall.raw.status));
110497
+ }
110498
+ const teamCall = await postBounded(TEAM_SETTINGS_PATH, apiKey, deps.httpTimeoutMs);
110499
+ facts.teamSettingsUrl = stripUserinfo(teamCall.raw.url);
110500
+ const teamNetwork = teamCall.timedOut ? "team_settings_timeout" : "team_settings_network_error";
110501
+ if (teamCall.raw.kind === "unreachable") {
110502
+ return modelListFail(facts, modelListFailureOf("network", teamNetwork));
110503
+ }
110504
+ facts.teamSettingsHttpStatus = teamCall.raw.status;
110505
+ if (teamCall.raw.status < 200 || teamCall.raw.status >= 300) {
110506
+ return modelListFail(facts, modelListFailureOf("list_incomplete", "team_settings_http_error", teamCall.raw.status));
110507
+ }
110508
+ if (teamCall.raw.body.kind !== "bytes") {
110509
+ return modelListFail(facts, modelListFailureOf("network", teamNetwork, teamCall.raw.status));
110510
+ }
110511
+ const allowedModelUids = decodeAllowedUids(teamCall.raw.body.bytes);
110512
+ if (allowedModelUids.length === 0) {
110513
+ return modelListFail(facts, modelListFailureOf("list_incomplete", "allowed_uids_empty", teamCall.raw.status));
110514
+ }
110515
+ const body = JSON.stringify({ configs, allowedModelUids });
110516
+ return {
110517
+ envelope: buildModelListEnvelope(facts, undefined, body),
110518
+ exitCode: EXIT.ok,
110519
+ bodyText: body
110520
+ };
110521
+ }
110522
+ async function runDevinRawModelList(deps) {
110523
+ const secrets = newSecrets();
110524
+ const facts = { provider: "devin", tokenRefreshed: false };
110525
+ return runModelListWith(deps, facts, secrets, () => determineDevin(deps, secrets, facts));
110526
+ }
110527
+ var DEVIN_SESSION_TOKEN_PREFIX = "devin-session-token$";
110528
+ var init_subscription_devin_models = __esm(() => {
110529
+ init_devin_credentials();
110530
+ init_devin_models();
110531
+ init_devin_request();
110532
+ init_subscription_antigravity_session();
110533
+ init_subscription_models_command();
110534
+ });
110535
+
110407
110536
  // src/subscription-models-command.ts
110408
110537
  var exports_subscription_models_command = {};
110409
110538
  __export(exports_subscription_models_command, {
@@ -110413,11 +110542,15 @@ __export(exports_subscription_models_command, {
110413
110542
  SECRET_GUARD_MESSAGE: () => SECRET_GUARD_MESSAGE,
110414
110543
  SUBSCRIPTION_MODELS_USAGE: () => SUBSCRIPTION_MODELS_USAGE,
110415
110544
  SUBSCRIPTION_MODEL_LIST_SCHEMA: () => SUBSCRIPTION_MODEL_LIST_SCHEMA,
110545
+ buildModelListEnvelope: () => buildModelListEnvelope,
110416
110546
  defaultSubscriptionModelsDeps: () => defaultSubscriptionModelsDeps,
110417
110547
  exitCodeFor: () => exitCodeFor,
110548
+ modelListFail: () => modelListFail,
110549
+ modelListFailureOf: () => modelListFailureOf,
110418
110550
  parseSubscriptionModelsArgs: () => parseSubscriptionModelsArgs,
110419
110551
  reportSubscriptionInternalError: () => reportSubscriptionInternalError,
110420
110552
  runAntigravityRawModelList: () => runAntigravityRawModelList,
110553
+ runModelListWith: () => runModelListWith,
110421
110554
  subscriptionModelsCommand: () => subscriptionModelsCommand
110422
110555
  });
110423
110556
  function exitCodeFor(failure) {
@@ -110444,11 +110577,11 @@ function defaultSubscriptionModelsDeps() {
110444
110577
  function parseSubscriptionModelsArgs(argv) {
110445
110578
  const positionals = argv.filter((a) => !a.startsWith("-"));
110446
110579
  const flags = argv.filter((a) => a.startsWith("-"));
110447
- const positionalsOk = positionals.length === 2 && positionals[0] === "models" && positionals[1] === "antigravity";
110580
+ const positionalsOk = positionals.length === 2 && positionals[0] === "models" && MODEL_LIST_PROVIDERS.includes(positionals[1]);
110448
110581
  const flagsOk = flags.length === 2 && flags.includes("--raw") && flags.includes("--json");
110449
- return positionalsOk && flagsOk ? { ok: true, provider: "antigravity" } : { ok: false };
110582
+ return positionalsOk && flagsOk ? { ok: true, provider: positionals[1] } : { ok: false };
110450
110583
  }
110451
- function buildEnvelope(facts, failure, body) {
110584
+ function buildModelListEnvelope(facts, failure, body) {
110452
110585
  return {
110453
110586
  schema: SUBSCRIPTION_MODEL_LIST_SCHEMA,
110454
110587
  ...facts.provider !== undefined ? { provider: facts.provider } : {},
@@ -110459,25 +110592,27 @@ function buildEnvelope(facts, failure, body) {
110459
110592
  ...facts.clientVersionSource !== undefined ? { clientVersionSource: facts.clientVersionSource } : {},
110460
110593
  tokenRefreshed: facts.tokenRefreshed,
110461
110594
  ...facts.httpStatus !== undefined ? { httpStatus: facts.httpStatus } : {},
110595
+ ...facts.teamSettingsUrl !== undefined ? { teamSettingsUrl: facts.teamSettingsUrl } : {},
110596
+ ...facts.teamSettingsHttpStatus !== undefined ? { teamSettingsHttpStatus: facts.teamSettingsHttpStatus } : {},
110462
110597
  ...failure ? { failure } : {},
110463
110598
  ...body !== undefined ? { body } : {}
110464
110599
  };
110465
110600
  }
110466
- function failureOf3(cls, code, httpStatus) {
110601
+ function modelListFailureOf(cls, code, httpStatus) {
110467
110602
  return failureOf2(cls, code, httpStatus);
110468
110603
  }
110469
110604
  function listFailure(value, status) {
110470
110605
  const models = value !== null && typeof value === "object" && !Array.isArray(value) ? value.models : undefined;
110471
110606
  if (models === null || typeof models !== "object" || Array.isArray(models)) {
110472
- return failureOf3("list_incomplete", "models_absent", status);
110607
+ return modelListFailureOf("list_incomplete", "models_absent", status);
110473
110608
  }
110474
110609
  if (Object.keys(models).length === 0) {
110475
- return failureOf3("list_incomplete", "models_empty", status);
110610
+ return modelListFailureOf("list_incomplete", "models_empty", status);
110476
110611
  }
110477
110612
  return null;
110478
110613
  }
110479
- function fail(facts, failure) {
110480
- return { envelope: buildEnvelope(facts, failure), exitCode: exitCodeFor(failure) };
110614
+ function modelListFail(facts, failure) {
110615
+ return { envelope: buildModelListEnvelope(facts, failure), exitCode: exitCodeFor(failure) };
110481
110616
  }
110482
110617
  function lineOf(envelope) {
110483
110618
  return `${JSON.stringify(envelope)}
@@ -110489,15 +110624,16 @@ function safeStderr(deps, line) {
110489
110624
  } catch {}
110490
110625
  }
110491
110626
  async function writeInternalFailure(deps, facts, code, stderrLine, secrets) {
110492
- const failure = failureOf3("internal", code);
110627
+ const failure = modelListFailureOf("internal", code);
110493
110628
  safeStderr(deps, `${stderrLine}
110494
110629
  `);
110495
- const line = lineOf(buildEnvelope(facts, failure));
110496
- if (!secrets || !containsSecret(secrets, line)) {
110497
- try {
110498
- await deps.writeStdout(line);
110499
- } catch {}
110630
+ let line = lineOf(buildModelListEnvelope(facts, failure));
110631
+ if (secrets && containsSecret(secrets, line)) {
110632
+ line = lineOf(buildModelListEnvelope({ tokenRefreshed: facts.tokenRefreshed }, failure));
110500
110633
  }
110634
+ try {
110635
+ await deps.writeStdout(line);
110636
+ } catch {}
110501
110637
  return exitCodeFor(failure);
110502
110638
  }
110503
110639
  async function reportSubscriptionInternalError(deps) {
@@ -110516,34 +110652,35 @@ function classifyAvailableModels(facts, raw, timedOut) {
110516
110652
  facts.clientVersion = raw.clientVersion;
110517
110653
  facts.clientVersionSource = raw.clientVersionSource;
110518
110654
  const networkCode = timedOut ? "fetch_available_models_timeout" : "fetch_available_models_network_error";
110519
- if (raw.kind === "unreachable")
110520
- return fail(facts, failureOf3("network", networkCode));
110655
+ if (raw.kind === "unreachable") {
110656
+ return modelListFail(facts, modelListFailureOf("network", networkCode));
110657
+ }
110521
110658
  facts.fetchedAt = raw.fetchedAt;
110522
110659
  facts.httpStatus = raw.status;
110523
110660
  if (raw.status < 200 || raw.status >= 300) {
110524
- return { envelope: buildEnvelope(facts), exitCode: EXIT.ok };
110661
+ return { envelope: buildModelListEnvelope(facts), exitCode: EXIT.ok };
110525
110662
  }
110526
110663
  switch (raw.body.kind) {
110527
110664
  case "json": {
110528
110665
  const incomplete = listFailure(raw.body.value, raw.status);
110529
110666
  if (incomplete)
110530
- return fail(facts, incomplete);
110667
+ return modelListFail(facts, incomplete);
110531
110668
  return {
110532
- envelope: buildEnvelope(facts, undefined, raw.body.text),
110669
+ envelope: buildModelListEnvelope(facts, undefined, raw.body.text),
110533
110670
  exitCode: EXIT.ok,
110534
110671
  bodyText: raw.body.text
110535
110672
  };
110536
110673
  }
110537
110674
  case "not-json":
110538
- return fail(facts, failureOf3("list_incomplete", "body_not_json", raw.status));
110675
+ return modelListFail(facts, modelListFailureOf("list_incomplete", "body_not_json", raw.status));
110539
110676
  default:
110540
- return fail(facts, failureOf3("network", networkCode, raw.status));
110677
+ return modelListFail(facts, modelListFailureOf("network", networkCode, raw.status));
110541
110678
  }
110542
110679
  }
110543
- async function determine(deps, secrets, facts) {
110680
+ async function determineAntigravity(deps, secrets, facts) {
110544
110681
  const session = await establishAntigravitySession(deps, secrets, facts);
110545
110682
  if (!session.ok)
110546
- return fail(facts, session.failure);
110683
+ return modelListFail(facts, session.failure);
110547
110684
  const { accessToken, projectId } = session;
110548
110685
  const controller = new AbortController;
110549
110686
  const timer = setTimeout(() => controller.abort(), deps.httpTimeoutMs);
@@ -110557,14 +110694,12 @@ async function determine(deps, secrets, facts) {
110557
110694
  clearTimeout(timer);
110558
110695
  }
110559
110696
  }
110560
- async function runAntigravityRawModelList(deps) {
110561
- const secrets = newSecrets();
110562
- const facts = { provider: "antigravity", tokenRefreshed: false };
110697
+ async function runModelListWith(deps, facts, secrets, determine) {
110563
110698
  let line;
110564
110699
  let exitCode;
110565
110700
  let bodyText;
110566
110701
  try {
110567
- const result = await determine(deps, secrets, facts);
110702
+ const result = await determine();
110568
110703
  line = lineOf(result.envelope);
110569
110704
  exitCode = result.exitCode;
110570
110705
  bodyText = result.bodyText;
@@ -110583,27 +110718,53 @@ async function runAntigravityRawModelList(deps) {
110583
110718
  }
110584
110719
  return exitCode;
110585
110720
  }
110721
+ async function runAntigravityRawModelList(deps) {
110722
+ const secrets = newSecrets();
110723
+ const facts = { provider: "antigravity", tokenRefreshed: false };
110724
+ return runModelListWith(deps, facts, secrets, () => determineAntigravity(deps, secrets, facts));
110725
+ }
110586
110726
  async function subscriptionModelsCommand(argv, deps = defaultSubscriptionModelsDeps()) {
110587
- if (!parseSubscriptionModelsArgs(argv).ok) {
110727
+ const args = parseSubscriptionModelsArgs(argv);
110728
+ if (!args.ok) {
110588
110729
  return writeInternalFailure(deps, { tokenRefreshed: false }, "usage", SUBSCRIPTION_MODELS_USAGE);
110589
110730
  }
110731
+ if (args.provider === "devin") {
110732
+ let devin;
110733
+ try {
110734
+ devin = await Promise.resolve().then(() => (init_subscription_devin_models(), exports_subscription_devin_models));
110735
+ } catch {
110736
+ return writeInternalFailure(deps, { provider: args.provider, tokenRefreshed: false }, "internal_error", INTERNAL_ERROR_MESSAGE);
110737
+ }
110738
+ return devin.runDevinRawModelList(deps);
110739
+ }
110590
110740
  return runAntigravityRawModelList(deps);
110591
110741
  }
110592
- var SUBSCRIPTION_MODEL_LIST_SCHEMA = "claudish.subscription-model-list.v1", FAILURE_CODES, EXIT, SUBSCRIPTION_MODELS_USAGE = "usage: claudish subscription models antigravity --raw --json", SECRET_GUARD_MESSAGE = "[claudish subscription] refused: output contained a credential value", INTERNAL_ERROR_MESSAGE = "[claudish subscription] internal error";
110742
+ var SUBSCRIPTION_MODEL_LIST_SCHEMA = "claudish.subscription-model-list.v1", FAILURE_CODES, EXIT, SUBSCRIPTION_MODELS_USAGE = "usage: claudish subscription models antigravity|devin --raw --json", SECRET_GUARD_MESSAGE = "[claudish subscription] refused: output contained a credential value", INTERNAL_ERROR_MESSAGE = "[claudish subscription] internal error", MODEL_LIST_PROVIDERS;
110593
110743
  var init_subscription_models_command = __esm(() => {
110594
110744
  init_antigravity_token();
110595
110745
  init_antigravity_user();
110596
110746
  init_subscription_antigravity_session();
110597
110747
  FAILURE_CODES = {
110598
- credential_missing: SESSION_FAILURE_CODES.credential_missing,
110748
+ credential_missing: [...SESSION_FAILURE_CODES.credential_missing, "devin_credential_absent"],
110599
110749
  keychain_locked: SESSION_FAILURE_CODES.keychain_locked,
110600
110750
  mint_failed: SESSION_FAILURE_CODES.mint_failed,
110601
110751
  network: [
110602
110752
  ...SESSION_FAILURE_CODES.network,
110603
110753
  "fetch_available_models_network_error",
110604
- "fetch_available_models_timeout"
110754
+ "fetch_available_models_timeout",
110755
+ "model_configs_network_error",
110756
+ "model_configs_timeout",
110757
+ "team_settings_network_error",
110758
+ "team_settings_timeout"
110759
+ ],
110760
+ list_incomplete: [
110761
+ "models_absent",
110762
+ "models_empty",
110763
+ "body_not_json",
110764
+ "configs_empty",
110765
+ "team_settings_http_error",
110766
+ "allowed_uids_empty"
110605
110767
  ],
110606
- list_incomplete: ["models_absent", "models_empty", "body_not_json"],
110607
110768
  internal: ["usage", "secret_guard", "internal_error"]
110608
110769
  };
110609
110770
  EXIT = {
@@ -110616,6 +110777,7 @@ var init_subscription_models_command = __esm(() => {
110616
110777
  network: 6,
110617
110778
  list_incomplete: 7
110618
110779
  };
110780
+ MODEL_LIST_PROVIDERS = ["antigravity", "devin"];
110619
110781
  });
110620
110782
 
110621
110783
  // src/subscription-dispatch.ts
@@ -110643,6 +110805,232 @@ function probeLoadFailureLine() {
110643
110805
  var SUBSCRIPTION_PROBE_SCHEMA = "claudish.subscription-probe.v1";
110644
110806
  var init_subscription_dispatch = () => {};
110645
110807
 
110808
+ // src/subscription-secret-guard.ts
110809
+ import { readFile as readFile8, stat as stat2 } from "fs/promises";
110810
+ function redactSecretValues(text, secrets) {
110811
+ let out = text;
110812
+ const values = [...secrets.values].sort((a, b) => b.length - a.length);
110813
+ for (const value of values) {
110814
+ for (const form of new Set([value, value.replaceAll("/", "\\/")])) {
110815
+ if (out.includes(form))
110816
+ out = out.replaceAll(form, REDACTED2);
110817
+ }
110818
+ }
110819
+ return { text: out, redacted: out !== text };
110820
+ }
110821
+ function jsonUnescapedForms(text) {
110822
+ const forms = [];
110823
+ if (text === undefined)
110824
+ return { forms, complete: true };
110825
+ let current = text;
110826
+ for (let round = 0;round < MAX_UNESCAPE_ROUNDS; round++) {
110827
+ const next = current.replace(JSON_ESCAPE, (_match, hex, letter) => hex !== undefined ? String.fromCharCode(Number.parseInt(hex, 16)) : SIMPLE_ESCAPES[letter]);
110828
+ if (next === current)
110829
+ return { forms, complete: true };
110830
+ forms.push(next);
110831
+ current = next;
110832
+ }
110833
+ return { forms, complete: false };
110834
+ }
110835
+ async function readCapped(res, cap) {
110836
+ if (!res.body)
110837
+ return "";
110838
+ const reader = res.body.getReader();
110839
+ const chunks = [];
110840
+ let size = 0;
110841
+ for (;; ) {
110842
+ const { done, value } = await reader.read();
110843
+ if (done)
110844
+ break;
110845
+ size += value.byteLength;
110846
+ if (size > cap) {
110847
+ await reader.cancel().catch(() => {});
110848
+ return null;
110849
+ }
110850
+ chunks.push(value);
110851
+ }
110852
+ return Buffer.concat(chunks).toString("utf8");
110853
+ }
110854
+ async function defaultReadRequestFile(path) {
110855
+ const info = await stat2(path);
110856
+ if (!info.isFile())
110857
+ throw new Error("not a file");
110858
+ if (info.size > PROBE_REQUEST_FILE_CAP_BYTES)
110859
+ return null;
110860
+ return readFile8(path, "utf8");
110861
+ }
110862
+ async function readRequestFileChecked(read, path) {
110863
+ let text;
110864
+ try {
110865
+ text = await read(path);
110866
+ } catch {
110867
+ return { ok: false, code: "request_file_unreadable" };
110868
+ }
110869
+ if (text === null)
110870
+ return { ok: false, code: "request_file_invalid" };
110871
+ let value;
110872
+ try {
110873
+ value = JSON.parse(text);
110874
+ } catch {
110875
+ return { ok: false, code: "request_file_invalid" };
110876
+ }
110877
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
110878
+ return { ok: false, code: "request_file_invalid" };
110879
+ }
110880
+ return { ok: true, text, value };
110881
+ }
110882
+ var PROBE_BODY_CAP_BYTES, PROBE_REQUEST_FILE_CAP_BYTES, REDACTED2 = "[REDACTED]", JSON_ESCAPE, SIMPLE_ESCAPES, MAX_UNESCAPE_ROUNDS = 64;
110883
+ var init_subscription_secret_guard = __esm(() => {
110884
+ PROBE_BODY_CAP_BYTES = 512 * 1024;
110885
+ PROBE_REQUEST_FILE_CAP_BYTES = 8 * 1024 * 1024;
110886
+ JSON_ESCAPE = /\\(?:u([0-9a-fA-F]{4})|(["\\/bfnrt]))/g;
110887
+ SIMPLE_ESCAPES = {
110888
+ '"': '"',
110889
+ "\\": "\\",
110890
+ "/": "/",
110891
+ b: "\b",
110892
+ f: "\f",
110893
+ n: `
110894
+ `,
110895
+ r: "\r",
110896
+ t: "\t"
110897
+ };
110898
+ });
110899
+
110900
+ // src/subscription-devin-probe.ts
110901
+ var exports_subscription_devin_probe = {};
110902
+ __export(exports_subscription_devin_probe, {
110903
+ DEVIN_PROBE_REQUEST_FILE_MESSAGE: () => DEVIN_PROBE_REQUEST_FILE_MESSAGE,
110904
+ buildDevinProbePayload: () => buildDevinProbePayload,
110905
+ runDevinProbe: () => runDevinProbe
110906
+ });
110907
+ function buildDevinProbePayload(model, claudeRequest) {
110908
+ const adapter = new DevinAPIFormat(model);
110909
+ adapter.setResponseWireFormat("connect-proto");
110910
+ adapter.reset();
110911
+ const messages = adapter.convertMessages(claudeRequest, filterIdentity);
110912
+ const tools = adapter.convertTools(claudeRequest);
110913
+ const payload = adapter.buildPayload(claudeRequest, messages, tools);
110914
+ adapter.prepareRequest(payload, claudeRequest);
110915
+ payload.modelUid = model;
110916
+ delete payload.effort;
110917
+ return { payload, toolNameMap: adapter.getToolNameMap() };
110918
+ }
110919
+ async function decodeDevinAnswer(res, facts, model, toolNameMap) {
110920
+ const head = await sniffDevinStreamHead(res);
110921
+ if (head.kind !== "clean") {
110922
+ facts.streamError = { code: head.code, retryable: head.kind === "retryable" };
110923
+ return JSON.stringify({ error: { code: head.code, message: head.message } });
110924
+ }
110925
+ let apiError;
110926
+ let measured;
110927
+ let endOfStream = false;
110928
+ const sse = createDevinConnectStream({}, head.response, {
110929
+ modelName: model,
110930
+ toolNameMap,
110931
+ onTokenUpdate: (input, output) => {
110932
+ measured = { input_tokens: input, output_tokens: output };
110933
+ },
110934
+ onServedModel: (uid) => {
110935
+ facts.servedModel = uid;
110936
+ },
110937
+ onApiError: (code, message) => {
110938
+ apiError ??= { code, message };
110939
+ },
110940
+ onEndOfStream: () => {
110941
+ endOfStream = true;
110942
+ }
110943
+ });
110944
+ const collected = await collectSseMessage(sse, model);
110945
+ if (apiError) {
110946
+ facts.streamError = {
110947
+ code: apiError.code,
110948
+ retryable: classifyDevinStreamError(apiError.code, apiError.message) === "retryable"
110949
+ };
110950
+ } else if (collected.streamError || !endOfStream) {
110951
+ return null;
110952
+ }
110953
+ const { streamError: _internal, ...message } = collected;
110954
+ if (measured)
110955
+ message.usage = measured;
110956
+ return JSON.stringify(message);
110957
+ }
110958
+ async function determineDevin2(deps, secrets, facts, args) {
110959
+ const request = await readRequestFileChecked(deps.readRequestFile, args.requestFile);
110960
+ if (!request.ok)
110961
+ return probeFail(facts, probeFailureOf("internal", request.code));
110962
+ const apiKey = readDevinSecrets(secrets);
110963
+ if (!apiKey) {
110964
+ return probeFail(facts, probeFailureOf("credential_missing", "devin_credential_absent"));
110965
+ }
110966
+ const { payload, toolNameMap } = buildDevinProbePayload(args.model, request.value);
110967
+ const body = encodeDevinRequest(payload, { apiKey });
110968
+ const url = `${readDevinServerUrl()}${CHAT_PATH}`;
110969
+ facts.sourceUrl = stripUserinfo(url);
110970
+ facts.clientVersion = DEVIN_CLI_VERSION;
110971
+ const controller = new AbortController;
110972
+ const timer = setTimeout(() => controller.abort(), deps.requestTimeoutMs);
110973
+ const networkFailure = () => probeFailureOf("network", controller.signal.aborted ? "get_chat_message_timeout" : "get_chat_message_network_error", facts.httpStatus);
110974
+ try {
110975
+ let res;
110976
+ try {
110977
+ res = await fetch(url, {
110978
+ method: "POST",
110979
+ headers: { ...devinAuthHeaders(apiKey), "content-type": CHAT_CONTENT_TYPE2 },
110980
+ body,
110981
+ signal: controller.signal,
110982
+ redirect: "manual"
110983
+ });
110984
+ } catch {
110985
+ return probeFail(facts, networkFailure());
110986
+ }
110987
+ facts.fetchedAt = new Date(deps.now()).toISOString();
110988
+ facts.httpStatus = res.status;
110989
+ if (!res.ok) {
110990
+ let text;
110991
+ try {
110992
+ text = await readCapped(res, PROBE_BODY_CAP_BYTES);
110993
+ } catch {
110994
+ return probeFail(facts, networkFailure());
110995
+ }
110996
+ if (text === null) {
110997
+ return probeFail(facts, probeFailureOf("list_incomplete", "body_too_large", res.status));
110998
+ }
110999
+ return probeBodyResult(facts, text, secrets, res.status);
111000
+ }
111001
+ const text = await decodeDevinAnswer(res, facts, args.model, toolNameMap);
111002
+ if (text === null)
111003
+ return probeFail(facts, networkFailure());
111004
+ if (Buffer.byteLength(text, "utf8") > PROBE_BODY_CAP_BYTES) {
111005
+ return probeFail(facts, probeFailureOf("list_incomplete", "body_too_large", res.status));
111006
+ }
111007
+ return probeBodyResult(facts, text, secrets, res.status);
111008
+ } finally {
111009
+ clearTimeout(timer);
111010
+ }
111011
+ }
111012
+ async function runDevinProbe(deps, args) {
111013
+ const secrets = newSecrets();
111014
+ const facts = { provider: "devin", model: args.model, tokenRefreshed: false };
111015
+ return runProbeWith(deps, facts, secrets, DEVIN_PROBE_REQUEST_FILE_MESSAGE, () => determineDevin2(deps, secrets, facts, args));
111016
+ }
111017
+ var DEVIN_PROBE_REQUEST_FILE_MESSAGE = "[claudish subscription] the request file must hold one JSON object (an Anthropic Messages request)", CHAT_CONTENT_TYPE2 = "application/connect+proto";
111018
+ var init_subscription_devin_probe = __esm(() => {
111019
+ init_devin_api_format();
111020
+ init_devin_credential();
111021
+ init_collect_sse_message();
111022
+ init_devin_stream_head_sniffer();
111023
+ init_openai_compat();
111024
+ init_devin_connect();
111025
+ init_devin_credentials();
111026
+ init_devin_request();
111027
+ init_devin2();
111028
+ init_subscription_antigravity_session();
111029
+ init_subscription_devin_models();
111030
+ init_subscription_probe_command();
111031
+ init_subscription_secret_guard();
111032
+ });
111033
+
110646
111034
  // src/subscription-probe-command.ts
110647
111035
  var exports_subscription_probe_command = {};
110648
111036
  __export(exports_subscription_probe_command, {
@@ -110655,33 +111043,30 @@ __export(exports_subscription_probe_command, {
110655
111043
  REDACTED: () => REDACTED2,
110656
111044
  SUBSCRIPTION_PROBE_SCHEMA: () => SUBSCRIPTION_PROBE_SCHEMA,
110657
111045
  SUBSCRIPTION_PROBE_USAGE: () => SUBSCRIPTION_PROBE_USAGE,
111046
+ buildProbeEnvelope: () => buildProbeEnvelope,
110658
111047
  buildProbeEnvelopeBody: () => buildProbeEnvelopeBody,
110659
111048
  defaultSubscriptionProbeDeps: () => defaultSubscriptionProbeDeps,
110660
111049
  isSubscriptionProbeArgv: () => isSubscriptionProbeArgv,
110661
111050
  jsonUnescapedForms: () => jsonUnescapedForms,
110662
111051
  parseSubscriptionProbeArgs: () => parseSubscriptionProbeArgs,
111052
+ probeBodyResult: () => probeBodyResult,
110663
111053
  probeExitCodeFor: () => probeExitCodeFor,
111054
+ probeFail: () => probeFail,
111055
+ probeFailureOf: () => probeFailureOf,
111056
+ readCapped: () => readCapped,
110664
111057
  redactSecretValues: () => redactSecretValues,
110665
111058
  reportProbeInternalError: () => reportProbeInternalError,
110666
111059
  runAntigravityProbe: () => runAntigravityProbe,
111060
+ runProbeWith: () => runProbeWith,
110667
111061
  subscriptionProbeCommand: () => subscriptionProbeCommand
110668
111062
  });
110669
111063
  import { randomUUID as randomUUID12 } from "crypto";
110670
- import { readFile as readFile8, stat as stat2 } from "fs/promises";
110671
111064
  function probeExitCodeFor(failure) {
110672
111065
  if (failure.class === "internal") {
110673
111066
  return CALLER_CODES.includes(failure.code) ? PROBE_EXIT.usage : PROBE_EXIT.internal;
110674
111067
  }
110675
111068
  return PROBE_EXIT[failure.class];
110676
111069
  }
110677
- async function defaultReadRequestFile(path) {
110678
- const info = await stat2(path);
110679
- if (!info.isFile())
110680
- throw new Error("not a file");
110681
- if (info.size > PROBE_REQUEST_FILE_CAP_BYTES)
110682
- return null;
110683
- return readFile8(path, "utf8");
110684
- }
110685
111070
  function defaultSubscriptionProbeDeps() {
110686
111071
  return {
110687
111072
  platform: () => process.platform,
@@ -110725,15 +111110,20 @@ function parseSubscriptionProbeArgs(argv) {
110725
111110
  }
110726
111111
  const model = values.get("--model");
110727
111112
  const requestFile = values.get("--request-file");
110728
- if (positionals.length !== 2 || positionals[0] !== "probe" || positionals[1] !== "antigravity" || switches.size !== 2 || model === undefined || requestFile === undefined) {
111113
+ if (positionals.length !== 2 || positionals[0] !== "probe" || !PROBE_PROVIDERS.includes(positionals[1]) || switches.size !== 2 || model === undefined || requestFile === undefined) {
110729
111114
  return { ok: false };
110730
111115
  }
110731
- return { ok: true, provider: "antigravity", model, requestFile };
111116
+ return {
111117
+ ok: true,
111118
+ provider: positionals[1],
111119
+ model,
111120
+ requestFile
111121
+ };
110732
111122
  }
110733
- function failureOf4(cls, code, httpStatus) {
111123
+ function probeFailureOf(cls, code, httpStatus) {
110734
111124
  return failureOf2(cls, code, httpStatus);
110735
111125
  }
110736
- function buildEnvelope2(facts, failure, body) {
111126
+ function buildProbeEnvelope(facts, failure, body) {
110737
111127
  return {
110738
111128
  schema: SUBSCRIPTION_PROBE_SCHEMA,
110739
111129
  ...facts.provider !== undefined ? { provider: facts.provider } : {},
@@ -110745,12 +111135,27 @@ function buildEnvelope2(facts, failure, body) {
110745
111135
  ...facts.clientVersionSource !== undefined ? { clientVersionSource: facts.clientVersionSource } : {},
110746
111136
  tokenRefreshed: facts.tokenRefreshed,
110747
111137
  ...facts.httpStatus !== undefined ? { httpStatus: facts.httpStatus } : {},
111138
+ ...facts.servedModel !== undefined ? { servedModel: facts.servedModel } : {},
111139
+ ...facts.streamError !== undefined ? { streamError: facts.streamError } : {},
110748
111140
  ...failure ? { failure } : {},
110749
111141
  ...body ? { bodyRedacted: body.redacted, body: body.text } : {}
110750
111142
  };
110751
111143
  }
110752
- function fail2(facts, failure) {
110753
- return { envelope: buildEnvelope2(facts, failure), exitCode: probeExitCodeFor(failure) };
111144
+ function probeFail(facts, failure) {
111145
+ return { envelope: buildProbeEnvelope(facts, failure), exitCode: probeExitCodeFor(failure) };
111146
+ }
111147
+ function probeBodyResult(facts, text, secrets, status) {
111148
+ const body = redactSecretValues(text, secrets);
111149
+ const unescaped = jsonUnescapedForms(body.text);
111150
+ if (!unescaped.complete) {
111151
+ return probeFail(facts, probeFailureOf("list_incomplete", "body_unverifiable", status));
111152
+ }
111153
+ return {
111154
+ envelope: buildProbeEnvelope(facts, undefined, body),
111155
+ exitCode: PROBE_EXIT.ok,
111156
+ bodyText: body.text,
111157
+ bodyForms: unescaped.forms
111158
+ };
110754
111159
  }
110755
111160
  function lineOf2(envelope) {
110756
111161
  return `${JSON.stringify(envelope)}
@@ -110762,62 +111167,41 @@ function safeStderr2(deps, line) {
110762
111167
  } catch {}
110763
111168
  }
110764
111169
  async function writeInternalFailure2(deps, facts, code, stderrLine, secrets) {
110765
- const failure = failureOf4("internal", code);
111170
+ const failure = probeFailureOf("internal", code);
110766
111171
  safeStderr2(deps, `${stderrLine}
110767
111172
  `);
110768
- let line = lineOf2(buildEnvelope2(facts, failure));
111173
+ let line = lineOf2(buildProbeEnvelope(facts, failure));
110769
111174
  if (secrets && containsSecret(secrets, line)) {
110770
- line = lineOf2(buildEnvelope2({ tokenRefreshed: facts.tokenRefreshed }, failure));
111175
+ line = lineOf2(buildProbeEnvelope({ tokenRefreshed: facts.tokenRefreshed }, failure));
110771
111176
  }
110772
111177
  try {
110773
111178
  await deps.writeStdout(line);
110774
111179
  } catch {}
110775
111180
  return probeExitCodeFor(failure);
110776
111181
  }
110777
- function redactSecretValues(text, secrets) {
110778
- let out = text;
110779
- const values = [...secrets.values].sort((a, b) => b.length - a.length);
110780
- for (const value of values) {
110781
- for (const form of new Set([value, value.replaceAll("/", "\\/")])) {
110782
- if (out.includes(form))
110783
- out = out.replaceAll(form, REDACTED2);
110784
- }
110785
- }
110786
- return { text: out, redacted: out !== text };
110787
- }
110788
- function jsonUnescapedForms(text) {
110789
- const forms = [];
110790
- if (text === undefined)
110791
- return { forms, complete: true };
110792
- let current = text;
110793
- for (let round = 0;round < MAX_UNESCAPE_ROUNDS; round++) {
110794
- const next = current.replace(JSON_ESCAPE, (_match, hex, letter) => hex !== undefined ? String.fromCharCode(Number.parseInt(hex, 16)) : SIMPLE_ESCAPES[letter]);
110795
- if (next === current)
110796
- return { forms, complete: true };
110797
- forms.push(next);
110798
- current = next;
110799
- }
110800
- return { forms, complete: false };
110801
- }
110802
- async function readRequest(deps, path) {
110803
- let text;
111182
+ async function runProbeWith(deps, facts, secrets, requestFileMessage, determine) {
111183
+ let result;
110804
111184
  try {
110805
- text = await deps.readRequestFile(path);
111185
+ result = await determine();
110806
111186
  } catch {
110807
- return { ok: false, code: "request_file_unreadable" };
111187
+ return writeInternalFailure2(deps, { provider: facts.provider, model: facts.model, tokenRefreshed: facts.tokenRefreshed }, "internal_error", INTERNAL_ERROR_MESSAGE2, secrets);
111188
+ }
111189
+ if (result.envelope.failure?.code === "request_file_unreadable" || result.envelope.failure?.code === "request_file_invalid") {
111190
+ safeStderr2(deps, `${requestFileMessage}
111191
+ `);
111192
+ }
111193
+ const line = lineOf2(result.envelope);
111194
+ if (containsSecret(secrets, line, result.bodyText, ...result.bodyForms ?? [])) {
111195
+ return writeInternalFailure2(deps, facts, "secret_guard", SECRET_GUARD_MESSAGE2, secrets);
110808
111196
  }
110809
- if (text === null)
110810
- return { ok: false, code: "request_file_invalid" };
110811
- let value;
110812
111197
  try {
110813
- value = JSON.parse(text);
111198
+ await deps.writeStdout(line);
110814
111199
  } catch {
110815
- return { ok: false, code: "request_file_invalid" };
110816
- }
110817
- if (value === null || typeof value !== "object" || Array.isArray(value)) {
110818
- return { ok: false, code: "request_file_invalid" };
111200
+ safeStderr2(deps, `${INTERNAL_ERROR_MESSAGE2}
111201
+ `);
111202
+ return PROBE_EXIT.internal;
110819
111203
  }
110820
- return { ok: true, text };
111204
+ return result.exitCode;
110821
111205
  }
110822
111206
  function buildProbeEnvelopeBody(model, projectId, tierId, requestText, userPromptId = randomUUID12()) {
110823
111207
  const head = JSON.stringify({ model, project: projectId, user_prompt_id: userPromptId });
@@ -110827,32 +111211,13 @@ function buildProbeEnvelopeBody(model, projectId, tierId, requestText, userPromp
110827
111211
  function createActivityRequestId3() {
110828
111212
  return Math.random().toString(36).substring(7);
110829
111213
  }
110830
- async function readCapped(res, cap) {
110831
- if (!res.body)
110832
- return "";
110833
- const reader = res.body.getReader();
110834
- const chunks = [];
110835
- let size = 0;
110836
- for (;; ) {
110837
- const { done, value } = await reader.read();
110838
- if (done)
110839
- break;
110840
- size += value.byteLength;
110841
- if (size > cap) {
110842
- await reader.cancel().catch(() => {});
110843
- return null;
110844
- }
110845
- chunks.push(value);
110846
- }
110847
- return Buffer.concat(chunks).toString("utf8");
110848
- }
110849
- async function determine2(deps, secrets, facts, args) {
110850
- const request = await readRequest(deps, args.requestFile);
111214
+ async function determineAntigravity2(deps, secrets, facts, args) {
111215
+ const request = await readRequestFileChecked(deps.readRequestFile, args.requestFile);
110851
111216
  if (!request.ok)
110852
- return fail2(facts, failureOf4("internal", request.code));
111217
+ return probeFail(facts, probeFailureOf("internal", request.code));
110853
111218
  const session = await establishAntigravitySession(deps, secrets, facts);
110854
111219
  if (!session.ok)
110855
- return fail2(facts, session.failure);
111220
+ return probeFail(facts, session.failure);
110856
111221
  const url = `${antigravityHost()}/v1internal:generateContent`;
110857
111222
  const version = resolveAntigravityClientVersion();
110858
111223
  facts.sourceUrl = stripUserinfo(url);
@@ -110860,7 +111225,7 @@ async function determine2(deps, secrets, facts, args) {
110860
111225
  facts.clientVersionSource = version.source;
110861
111226
  const controller = new AbortController;
110862
111227
  const timer = setTimeout(() => controller.abort(), deps.requestTimeoutMs);
110863
- const networkFailure = () => failureOf4("network", controller.signal.aborted ? "generate_content_timeout" : "generate_content_network_error", facts.httpStatus);
111228
+ const networkFailure = () => probeFailureOf("network", controller.signal.aborted ? "generate_content_timeout" : "generate_content_network_error", facts.httpStatus);
110864
111229
  try {
110865
111230
  let res;
110866
111231
  try {
@@ -110877,7 +111242,7 @@ async function determine2(deps, secrets, facts, args) {
110877
111242
  redirect: "manual"
110878
111243
  });
110879
111244
  } catch {
110880
- return fail2(facts, networkFailure());
111245
+ return probeFail(facts, networkFailure());
110881
111246
  }
110882
111247
  facts.fetchedAt = new Date(deps.now()).toISOString();
110883
111248
  facts.httpStatus = res.status;
@@ -110885,28 +111250,18 @@ async function determine2(deps, secrets, facts, args) {
110885
111250
  try {
110886
111251
  text = await readCapped(res, PROBE_BODY_CAP_BYTES);
110887
111252
  } catch {
110888
- return fail2(facts, networkFailure());
111253
+ return probeFail(facts, networkFailure());
110889
111254
  }
110890
111255
  if (text === null)
110891
- return fail2(facts, failureOf4("list_incomplete", "body_too_large", res.status));
111256
+ return probeFail(facts, probeFailureOf("list_incomplete", "body_too_large", res.status));
110892
111257
  if (res.ok) {
110893
111258
  try {
110894
111259
  JSON.parse(text);
110895
111260
  } catch {
110896
- return fail2(facts, failureOf4("list_incomplete", "body_not_json", res.status));
111261
+ return probeFail(facts, probeFailureOf("list_incomplete", "body_not_json", res.status));
110897
111262
  }
110898
111263
  }
110899
- const body = redactSecretValues(text, secrets);
110900
- const unescaped = jsonUnescapedForms(body.text);
110901
- if (!unescaped.complete) {
110902
- return fail2(facts, failureOf4("list_incomplete", "body_unverifiable", res.status));
110903
- }
110904
- return {
110905
- envelope: buildEnvelope2(facts, undefined, body),
110906
- exitCode: PROBE_EXIT.ok,
110907
- bodyText: body.text,
110908
- bodyForms: unescaped.forms
110909
- };
111264
+ return probeBodyResult(facts, text, secrets, res.status);
110910
111265
  } finally {
110911
111266
  clearTimeout(timer);
110912
111267
  }
@@ -110914,28 +111269,7 @@ async function determine2(deps, secrets, facts, args) {
110914
111269
  async function runAntigravityProbe(deps, args) {
110915
111270
  const secrets = newSecrets();
110916
111271
  const facts = { provider: "antigravity", model: args.model, tokenRefreshed: false };
110917
- let result;
110918
- try {
110919
- result = await determine2(deps, secrets, facts, args);
110920
- } catch {
110921
- return writeInternalFailure2(deps, { provider: facts.provider, model: facts.model, tokenRefreshed: facts.tokenRefreshed }, "internal_error", INTERNAL_ERROR_MESSAGE2, secrets);
110922
- }
110923
- if (result.envelope.failure?.code === "request_file_unreadable" || result.envelope.failure?.code === "request_file_invalid") {
110924
- safeStderr2(deps, `${PROBE_REQUEST_FILE_MESSAGE}
110925
- `);
110926
- }
110927
- const line = lineOf2(result.envelope);
110928
- if (containsSecret(secrets, line, result.bodyText, ...result.bodyForms ?? [])) {
110929
- return writeInternalFailure2(deps, facts, "secret_guard", SECRET_GUARD_MESSAGE2, secrets);
110930
- }
110931
- try {
110932
- await deps.writeStdout(line);
110933
- } catch {
110934
- safeStderr2(deps, `${INTERNAL_ERROR_MESSAGE2}
110935
- `);
110936
- return PROBE_EXIT.internal;
110937
- }
110938
- return result.exitCode;
111272
+ return runProbeWith(deps, facts, secrets, PROBE_REQUEST_FILE_MESSAGE, () => determineAntigravity2(deps, secrets, facts, args));
110939
111273
  }
110940
111274
  async function reportProbeInternalError(deps) {
110941
111275
  let resolved;
@@ -110953,23 +111287,36 @@ async function subscriptionProbeCommand(argv, deps = defaultSubscriptionProbeDep
110953
111287
  if (!args.ok) {
110954
111288
  return writeInternalFailure2(deps, { tokenRefreshed: false }, "usage", SUBSCRIPTION_PROBE_USAGE);
110955
111289
  }
111290
+ if (args.provider === "devin") {
111291
+ let devin;
111292
+ try {
111293
+ devin = await Promise.resolve().then(() => (init_subscription_devin_probe(), exports_subscription_devin_probe));
111294
+ } catch {
111295
+ return writeInternalFailure2(deps, { provider: args.provider, model: args.model, tokenRefreshed: false }, "internal_error", INTERNAL_ERROR_MESSAGE2);
111296
+ }
111297
+ return devin.runDevinProbe(deps, args);
111298
+ }
110956
111299
  return runAntigravityProbe(deps, args);
110957
111300
  }
110958
- var PROBE_FAILURE_CODES, PROBE_EXIT, CALLER_CODES, PROBE_BODY_CAP_BYTES, PROBE_REQUEST_FILE_CAP_BYTES, REDACTED2 = "[REDACTED]", SUBSCRIPTION_PROBE_USAGE = "usage: claudish subscription probe antigravity --model <wire-model-id> --request-file <path> --raw --json", PROBE_REQUEST_FILE_MESSAGE = "[claudish subscription] the request file must hold one JSON object (the inner Gemini request)", SECRET_GUARD_MESSAGE2 = "[claudish subscription] refused: output contained a credential value", INTERNAL_ERROR_MESSAGE2 = "[claudish subscription] internal error", JSON_ESCAPE, SIMPLE_ESCAPES, MAX_UNESCAPE_ROUNDS = 64;
111301
+ var PROBE_FAILURE_CODES, PROBE_EXIT, CALLER_CODES, SUBSCRIPTION_PROBE_USAGE = "usage: claudish subscription probe antigravity|devin --model <wire-model-id> --request-file <path> --raw --json", PROBE_REQUEST_FILE_MESSAGE = "[claudish subscription] the request file must hold one JSON object (the inner Gemini request)", SECRET_GUARD_MESSAGE2 = "[claudish subscription] refused: output contained a credential value", INTERNAL_ERROR_MESSAGE2 = "[claudish subscription] internal error", PROBE_PROVIDERS;
110959
111302
  var init_subscription_probe_command = __esm(() => {
110960
111303
  init_antigravity_token();
110961
111304
  init_antigravity_user();
110962
111305
  init_subscription_antigravity_session();
110963
111306
  init_subscription_dispatch();
111307
+ init_subscription_secret_guard();
110964
111308
  init_subscription_dispatch();
111309
+ init_subscription_secret_guard();
110965
111310
  PROBE_FAILURE_CODES = {
110966
- credential_missing: SESSION_FAILURE_CODES.credential_missing,
111311
+ credential_missing: [...SESSION_FAILURE_CODES.credential_missing, "devin_credential_absent"],
110967
111312
  keychain_locked: SESSION_FAILURE_CODES.keychain_locked,
110968
111313
  mint_failed: SESSION_FAILURE_CODES.mint_failed,
110969
111314
  network: [
110970
111315
  ...SESSION_FAILURE_CODES.network,
110971
111316
  "generate_content_network_error",
110972
- "generate_content_timeout"
111317
+ "generate_content_timeout",
111318
+ "get_chat_message_network_error",
111319
+ "get_chat_message_timeout"
110973
111320
  ],
110974
111321
  list_incomplete: ["body_too_large", "body_not_json", "body_unverifiable"],
110975
111322
  internal: [
@@ -110995,20 +111342,7 @@ var init_subscription_probe_command = __esm(() => {
110995
111342
  "request_file_unreadable",
110996
111343
  "request_file_invalid"
110997
111344
  ];
110998
- PROBE_BODY_CAP_BYTES = 512 * 1024;
110999
- PROBE_REQUEST_FILE_CAP_BYTES = 8 * 1024 * 1024;
111000
- JSON_ESCAPE = /\\(?:u([0-9a-fA-F]{4})|(["\\/bfnrt]))/g;
111001
- SIMPLE_ESCAPES = {
111002
- '"': '"',
111003
- "\\": "\\",
111004
- "/": "/",
111005
- b: "\b",
111006
- f: "\f",
111007
- n: `
111008
- `,
111009
- r: "\r",
111010
- t: "\t"
111011
- };
111345
+ PROBE_PROVIDERS = ["antigravity", "devin"];
111012
111346
  });
111013
111347
 
111014
111348
  // src/account-forecast-render.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "14.15.1",
3
+ "version": "14.16.1",
4
4
  "description": "Run Claude Code with any model - OpenRouter, Ollama, LM Studio & local models",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -71,10 +71,10 @@
71
71
  "ai"
72
72
  ],
73
73
  "optionalDependencies": {
74
- "@claudish/magmux-darwin-arm64": "14.15.1",
75
- "@claudish/magmux-darwin-x64": "14.15.1",
76
- "@claudish/magmux-linux-arm64": "14.15.1",
77
- "@claudish/magmux-linux-x64": "14.15.1"
74
+ "@claudish/magmux-darwin-arm64": "14.16.1",
75
+ "@claudish/magmux-darwin-x64": "14.16.1",
76
+ "@claudish/magmux-linux-arm64": "14.16.1",
77
+ "@claudish/magmux-linux-x64": "14.16.1"
78
78
  },
79
79
  "author": "Jack Rudenko <i@madappgang.com>",
80
80
  "license": "MIT",