@meistrari/tela-cli 0.7.27 → 0.7.29

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 +182 -20
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1415,6 +1415,7 @@ var require_auth2 = __commonJS({
1415
1415
  "../../packages/agent/dist/auth.js"(exports2) {
1416
1416
  "use strict";
1417
1417
  Object.defineProperty(exports2, "__esModule", { value: true });
1418
+ exports2.resolveAgentApiDataToken = resolveAgentApiDataToken;
1418
1419
  exports2.buildAgentApiHeaders = buildAgentApiHeaders;
1419
1420
  var tela_local_config_1 = require_dist();
1420
1421
  var errors_1 = require_errors();
@@ -1456,18 +1457,14 @@ var require_auth2 = __commonJS({
1456
1457
  }
1457
1458
  return dataToken;
1458
1459
  }
1459
- async function buildAgentApiHeaders(config, options = {}) {
1460
+ async function resolveAgentApiDataToken(config, options = {}) {
1460
1461
  const fetchFn = options.fetchFn ?? fetch;
1461
1462
  const credentialRef = config.credentialRef;
1462
1463
  const credentials = config.credentials;
1463
1464
  const resolvedEnvironment = config.resolvedEnvironment;
1464
1465
  let credential = config.credential;
1465
1466
  if (!credential && config.auth?.session.accessToken) {
1466
- const dataToken2 = await exchangeDataToken(config, config.auth.session.accessToken, fetchFn);
1467
- return {
1468
- "x-data-token": dataToken2,
1469
- Accept: "application/json"
1470
- };
1467
+ return await exchangeDataToken(config, config.auth.session.accessToken, fetchFn);
1471
1468
  }
1472
1469
  if (!credential) {
1473
1470
  throw (0, errors_1.createUserFacingError)({
@@ -1477,10 +1474,7 @@ var require_auth2 = __commonJS({
1477
1474
  });
1478
1475
  }
1479
1476
  if (credential.kind === "data-token" && credential.dataToken) {
1480
- return {
1481
- "x-data-token": credential.dataToken,
1482
- Accept: "application/json"
1483
- };
1477
+ return credential.dataToken;
1484
1478
  }
1485
1479
  if (credential.kind === "user-session") {
1486
1480
  if (!credentialRef || !credentials || !resolvedEnvironment) {
@@ -1500,7 +1494,10 @@ var require_auth2 = __commonJS({
1500
1494
  fixes: ["Sign in with Dock or choose a user-session context before running agent commands."]
1501
1495
  });
1502
1496
  }
1503
- const dataToken = await exchangeDataToken(config, credential.accessToken, fetchFn);
1497
+ return await exchangeDataToken(config, credential.accessToken, fetchFn);
1498
+ }
1499
+ async function buildAgentApiHeaders(config, options = {}) {
1500
+ const dataToken = await resolveAgentApiDataToken(config, options);
1504
1501
  return {
1505
1502
  "x-data-token": dataToken,
1506
1503
  Accept: "application/json"
@@ -1515,6 +1512,7 @@ var require_agent_api = __commonJS({
1515
1512
  "use strict";
1516
1513
  Object.defineProperty(exports2, "__esModule", { value: true });
1517
1514
  exports2.AgentApiError = void 0;
1515
+ exports2.fetchOpenRouterModels = fetchOpenRouterModels;
1518
1516
  exports2.listOrganizations = listOrganizations;
1519
1517
  exports2.provisionForgejoUser = provisionForgejoUser;
1520
1518
  exports2.fetchRepositoryLookup = fetchRepositoryLookup;
@@ -1593,6 +1591,37 @@ var require_agent_api = __commonJS({
1593
1591
  }
1594
1592
  };
1595
1593
  exports2.AgentApiError = AgentApiError;
1594
+ function isOpenRouterModelPricingSummary(value) {
1595
+ if (!value || typeof value !== "object") {
1596
+ return false;
1597
+ }
1598
+ const candidate = value;
1599
+ return typeof candidate.prompt_per_million === "number" && typeof candidate.completion_per_million === "number" && (candidate.input_cache_read_per_million === void 0 || typeof candidate.input_cache_read_per_million === "number");
1600
+ }
1601
+ function isOpenRouterModelSummary(value) {
1602
+ if (!value || typeof value !== "object") {
1603
+ return false;
1604
+ }
1605
+ const candidate = value;
1606
+ return typeof candidate.id === "string" && typeof candidate.name === "string" && typeof candidate.context_length === "number" && (candidate.max_completion_tokens === null || typeof candidate.max_completion_tokens === "number") && isOpenRouterModelPricingSummary(candidate.pricing);
1607
+ }
1608
+ async function fetchOpenRouterModels(config, fetchFn = fetch, options = {}) {
1609
+ const headers = options.headers ?? await (0, auth_1.buildAgentApiHeaders)(config, { fetchFn });
1610
+ const response = await fetchFn(joinUrl2(config.agentApiUrl, "/v3/openrouter/models"), {
1611
+ method: "GET",
1612
+ headers,
1613
+ signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS)
1614
+ });
1615
+ const responseText = await response.text();
1616
+ const payload = parseJsonBody(responseText);
1617
+ if (!response.ok) {
1618
+ throw new AgentApiError(payload?.error ?? `Agent API OpenRouter model lookup failed with status ${response.status}`, response.status, responseText);
1619
+ }
1620
+ if (!payload || payload.object !== "list" || !Array.isArray(payload.data) || !payload.data.every(isOpenRouterModelSummary)) {
1621
+ throw new AgentApiError("Agent API OpenRouter model lookup returned an invalid payload", response.status, responseText);
1622
+ }
1623
+ return payload.data;
1624
+ }
1596
1625
  async function listOrganizations(config, fetchFn = fetch) {
1597
1626
  const headers = await (0, auth_1.buildAgentApiHeaders)(config, { fetchFn });
1598
1627
  const response = await fetchFn(joinUrl2(config.agentApiUrl, "/v3/organizations"), {
@@ -3232,6 +3261,22 @@ ${error.result.stderr}`.toLowerCase();
3232
3261
  }
3233
3262
  });
3234
3263
 
3264
+ // ../../packages/agent/dist/shell.js
3265
+ var require_shell = __commonJS({
3266
+ "../../packages/agent/dist/shell.js"(exports2) {
3267
+ "use strict";
3268
+ Object.defineProperty(exports2, "__esModule", { value: true });
3269
+ exports2.shellSingleQuote = shellSingleQuote;
3270
+ exports2.shellJoinCommand = shellJoinCommand;
3271
+ function shellSingleQuote(value) {
3272
+ return `'${value.replace(/'/g, `'"'"'`)}'`;
3273
+ }
3274
+ function shellJoinCommand(command) {
3275
+ return command.map((argument) => shellSingleQuote(argument)).join(" ");
3276
+ }
3277
+ }
3278
+ });
3279
+
3235
3280
  // ../../packages/agent/dist/commands/run.js
3236
3281
  var require_run = __commonJS({
3237
3282
  "../../packages/agent/dist/commands/run.js"(exports2) {
@@ -3239,7 +3284,9 @@ var require_run = __commonJS({
3239
3284
  Object.defineProperty(exports2, "__esModule", { value: true });
3240
3285
  exports2.readLocalAgentRunConfig = readLocalAgentRunConfig;
3241
3286
  exports2.updateLocalAgentRunMode = updateLocalAgentRunMode;
3287
+ exports2.updateLocalAgentRunModel = updateLocalAgentRunModel;
3242
3288
  exports2.buildLocalAgentClaudeCommand = buildLocalAgentClaudeCommand;
3289
+ exports2.buildLocalAgentClaudeLaunchCommand = buildLocalAgentClaudeLaunchCommand;
3243
3290
  exports2.prepareLocalAgentRun = prepareLocalAgentRun;
3244
3291
  exports2.parseRunInputAssignment = parseRunInputAssignment;
3245
3292
  exports2.parseRunInputAssignments = parseRunInputAssignments;
@@ -3258,10 +3305,14 @@ var require_run = __commonJS({
3258
3305
  var promises_1 = require("node:fs/promises");
3259
3306
  var node_os_1 = require("node:os");
3260
3307
  var node_path_1 = require("node:path");
3308
+ var agent_api_1 = require_agent_api();
3309
+ var auth_1 = require_auth2();
3261
3310
  var claude_1 = require_claude();
3262
3311
  var git_1 = require_git();
3263
3312
  var errors_1 = require_errors();
3264
3313
  var process_1 = require_process();
3314
+ var config_1 = require_config2();
3315
+ var shell_1 = require_shell();
3265
3316
  var ui_1 = require_ui();
3266
3317
  var INITIAL_PROMPT = "Follow the instructions and return the result.";
3267
3318
  var REQUIRED_AGENT_FILES = [
@@ -4250,6 +4301,27 @@ ${detail.errors.join("\n")}` : summary);
4250
4301
  isMultiturn: options.mode === "chat"
4251
4302
  };
4252
4303
  await (0, promises_1.writeFile)(agentConfig.path, `${JSON.stringify(updated, null, 2)}
4304
+ `);
4305
+ return parseAgentConfig("agent.config.json", JSON.stringify(updated));
4306
+ }
4307
+ async function updateLocalAgentRunModel(options) {
4308
+ const repoRoot = await resolveRepositoryRoot(options.cwd ?? process.cwd());
4309
+ const agentConfig = await readAgentConfigFile(repoRoot);
4310
+ const parsed = parseJsonObjectFile("agent.config.json", agentConfig.content, "agent.config.json must be a valid JSON object.");
4311
+ const model = options.model.trim();
4312
+ parseAgentConfig("agent.config.json", agentConfig.content);
4313
+ if (!model || !isOpenRouterModelId(model)) {
4314
+ throw (0, errors_1.createUserFacingError)({
4315
+ code: "run_openrouter_model_invalid",
4316
+ summary: "Choose an OpenRouter model id.",
4317
+ fixes: ["Use a provider-qualified OpenRouter model id, for example `openai/gpt-5.4`."]
4318
+ });
4319
+ }
4320
+ const updated = {
4321
+ ...parsed,
4322
+ model
4323
+ };
4324
+ await (0, promises_1.writeFile)(agentConfig.path, `${JSON.stringify(updated, null, 2)}
4253
4325
  `);
4254
4326
  return parseAgentConfig("agent.config.json", JSON.stringify(updated));
4255
4327
  }
@@ -4281,6 +4353,89 @@ ${detail.errors.join("\n")}` : summary);
4281
4353
  verbose: mode === "one-shot"
4282
4354
  });
4283
4355
  }
4356
+ function isOpenRouterModelId(model) {
4357
+ return Boolean(model && model.includes("/"));
4358
+ }
4359
+ function buildOpenRouterProxyBaseUrl(agentApiUrl) {
4360
+ return new URL("/v3/openrouter", agentApiUrl.endsWith("/") ? agentApiUrl : `${agentApiUrl}/`).toString().replace(/\/$/, "");
4361
+ }
4362
+ function buildOpenRouterClaudeEnvironmentOverrides(model, dataToken, agentApiUrl) {
4363
+ const proxyBaseUrl = buildOpenRouterProxyBaseUrl(agentApiUrl);
4364
+ return {
4365
+ ANTHROPIC_BASE_URL: proxyBaseUrl,
4366
+ ANTHROPIC_AUTH_TOKEN: dataToken,
4367
+ ANTHROPIC_API_KEY: "",
4368
+ ANTHROPIC_DEFAULT_OPUS_MODEL: model,
4369
+ ANTHROPIC_DEFAULT_SONNET_MODEL: model,
4370
+ ANTHROPIC_DEFAULT_HAIKU_MODEL: model,
4371
+ CLAUDE_CODE_SUBAGENT_MODEL: model
4372
+ };
4373
+ }
4374
+ function redactClaudeEnvironmentOverrides(overrides) {
4375
+ return {
4376
+ ...overrides,
4377
+ ANTHROPIC_AUTH_TOKEN: overrides.ANTHROPIC_AUTH_TOKEN === void 0 ? void 0 : "<redacted>"
4378
+ };
4379
+ }
4380
+ function buildRedactedClaudeShellCommand(command, environmentOverrides) {
4381
+ const unsetArgs = (0, claude_1.getProjectScopedClaudeEnvDenylist)().map((key) => `-u ${key}`);
4382
+ const setArgs = Object.entries(environmentOverrides).filter((entry) => entry[1] !== void 0).map(([key, value]) => `${key}=${(0, shell_1.shellSingleQuote)(value)}`);
4383
+ return ["env", ...unsetArgs, ...setArgs, (0, shell_1.shellJoinCommand)(command)].join(" ");
4384
+ }
4385
+ async function ensureOpenRouterModelAvailable(model, models) {
4386
+ if (models.some((candidate) => candidate.id === model)) {
4387
+ return;
4388
+ }
4389
+ throw (0, errors_1.createUserFacingError)({
4390
+ code: "run_openrouter_model_unavailable",
4391
+ summary: `OpenRouter model is not available through Tela: ${model}`,
4392
+ fixes: [
4393
+ "Use a model returned by `GET /v3/openrouter/models`.",
4394
+ "Update `agent.config.json` to a supported OpenRouter model id, for example `openai/gpt-5.4`."
4395
+ ]
4396
+ });
4397
+ }
4398
+ async function buildLocalAgentClaudeLaunchCommand(prepared, mode, options = {}) {
4399
+ const command = buildLocalAgentClaudeCommand(prepared, mode);
4400
+ const baseEnv = (0, claude_1.buildProjectScopedClaudeEnvironment)(options.baseEnv);
4401
+ const model = prepared.config.model;
4402
+ if (!isOpenRouterModelId(model)) {
4403
+ return {
4404
+ command,
4405
+ env: baseEnv,
4406
+ environmentOverrides: {},
4407
+ redactedEnvironmentOverrides: {},
4408
+ redactedCommand: buildRedactedClaudeShellCommand(command, {}),
4409
+ provider: "anthropic",
4410
+ model
4411
+ };
4412
+ }
4413
+ const resolveConfigFn = options.resolveAgentConfig ?? config_1.resolveAgentConfig;
4414
+ const resolveDataTokenFn = options.resolveAgentApiDataToken ?? auth_1.resolveAgentApiDataToken;
4415
+ const fetchModelsFn = options.fetchOpenRouterModels ?? agent_api_1.fetchOpenRouterModels;
4416
+ const config = await resolveConfigFn();
4417
+ const dataToken = await resolveDataTokenFn(config, { fetchFn: options.fetch });
4418
+ const headers = {
4419
+ "x-data-token": dataToken,
4420
+ Accept: "application/json"
4421
+ };
4422
+ const models = await fetchModelsFn(config, options.fetch, { headers });
4423
+ await ensureOpenRouterModelAvailable(model, models);
4424
+ const environmentOverrides = buildOpenRouterClaudeEnvironmentOverrides(model, dataToken, config.agentApiUrl);
4425
+ const redactedEnvironmentOverrides = redactClaudeEnvironmentOverrides(environmentOverrides);
4426
+ return {
4427
+ command,
4428
+ env: {
4429
+ ...baseEnv,
4430
+ ...environmentOverrides
4431
+ },
4432
+ environmentOverrides,
4433
+ redactedEnvironmentOverrides,
4434
+ redactedCommand: buildRedactedClaudeShellCommand(command, redactedEnvironmentOverrides),
4435
+ provider: "openrouter",
4436
+ model
4437
+ };
4438
+ }
4284
4439
  async function resolveRepositoryRoot(cwd) {
4285
4440
  try {
4286
4441
  return await (0, git_1.getRepositoryRoot)(cwd);
@@ -4999,7 +5154,7 @@ Input folder: ${comparableInputRoot}`,
4999
5154
  inputs
5000
5155
  };
5001
5156
  }
5002
- async function runInteractiveAgent(prepared, runInteractiveCommandFn, options) {
5157
+ async function runInteractiveAgent(prepared, claudeLaunch, runInteractiveCommandFn, options) {
5003
5158
  if (options.surface === "json") {
5004
5159
  throw (0, errors_1.createUserFacingError)({
5005
5160
  code: "run_multiturn_json_unsupported",
@@ -5019,12 +5174,12 @@ Input folder: ${comparableInputRoot}`,
5019
5174
  if (options.surface === "plain") {
5020
5175
  writeLine2(options.writeStdout, "Launching Claude in interactive chat mode. Tela will resume after Claude exits.");
5021
5176
  }
5022
- await runInteractiveCommandFn(buildLocalAgentClaudeCommand(prepared, "chat"), {
5177
+ await runInteractiveCommandFn(claudeLaunch.command, {
5023
5178
  cwd: prepared.repoRoot,
5024
- env: (0, claude_1.buildProjectScopedClaudeEnvironment)()
5179
+ env: claudeLaunch.env
5025
5180
  });
5026
5181
  }
5027
- async function runOneShotAgent(prepared, options, tracker) {
5182
+ async function runOneShotAgent(prepared, options, tracker, claudeLaunch) {
5028
5183
  const plainRenderer = new PlainTranscriptRenderer();
5029
5184
  const runStreamingCommandFn = options.runStreamingCommand ?? process_1.runStreamingCommand;
5030
5185
  const spawnStreamingCommandFn = options.spawnStreamingCommand ?? ((command2, spawnOptions) => ({
@@ -5042,10 +5197,10 @@ Input folder: ${comparableInputRoot}`,
5042
5197
  writeLine2(options.writeStdout, "Streaming Claude execution in one-shot mode.");
5043
5198
  }
5044
5199
  let cancelled = false;
5045
- const command = buildLocalAgentClaudeCommand(prepared, "one-shot");
5200
+ const command = claudeLaunch.command;
5046
5201
  const handle = spawnStreamingCommandFn(command, {
5047
5202
  cwd: prepared.repoRoot,
5048
- env: (0, claude_1.buildProjectScopedClaudeEnvironment)(),
5203
+ env: claudeLaunch.env,
5049
5204
  allowFailure: true,
5050
5205
  onStdoutLine: async (line) => {
5051
5206
  const trimmed = line.trim();
@@ -5132,26 +5287,32 @@ Input folder: ${comparableInputRoot}`,
5132
5287
  isMultiturn: options.mode === "chat"
5133
5288
  }
5134
5289
  } : preparedBase;
5290
+ const mode = prepared.config.isMultiturn ? "chat" : "one-shot";
5291
+ const claudeLaunch = await buildLocalAgentClaudeLaunchCommand(prepared, mode, {
5292
+ resolveAgentConfig: options.resolveAgentConfig,
5293
+ fetchOpenRouterModels: options.fetchOpenRouterModels,
5294
+ resolveAgentApiDataToken: options.resolveAgentApiDataToken,
5295
+ fetch: options.fetch
5296
+ });
5135
5297
  const inputs = await prepareLocalAgentRunInputsForLaunch(prepared, {
5136
5298
  cwd: options.cwd,
5137
5299
  inputAssignments: options.inputAssignments,
5138
5300
  stagedInputs: options.stagedInputs,
5139
5301
  resolveInputConflict: options.resolveInputConflict
5140
5302
  });
5141
- const mode = prepared.config.isMultiturn ? "chat" : "one-shot";
5142
5303
  const tracker = new RunStateTracker(prepared, mode);
5143
5304
  const agentRunsRoot = options.agentRunsRoot ?? getDefaultAgentRunsRoot();
5144
5305
  let snapshot = tracker.snapshot();
5145
5306
  effectiveOptions.onSnapshot?.(snapshot);
5146
5307
  try {
5147
5308
  if (prepared.config.isMultiturn) {
5148
- await runInteractiveAgent(prepared, options.runInteractiveCommand ?? process_1.runInteractiveCommand, effectiveOptions);
5309
+ await runInteractiveAgent(prepared, claudeLaunch, options.runInteractiveCommand ?? process_1.runInteractiveCommand, effectiveOptions);
5149
5310
  snapshot = tracker.finalize("success", {
5150
5311
  summary: "Claude chat exited. Reading result artifact\u2026"
5151
5312
  });
5152
5313
  effectiveOptions.onSnapshot?.(snapshot);
5153
5314
  } else {
5154
- snapshot = await runOneShotAgent(prepared, effectiveOptions, tracker);
5315
+ snapshot = await runOneShotAgent(prepared, effectiveOptions, tracker, claudeLaunch);
5155
5316
  }
5156
5317
  } catch (error) {
5157
5318
  let terminalSnapshot = tracker.snapshot();
@@ -6641,6 +6802,7 @@ var require_dist2 = __commonJS({
6641
6802
  __exportStar(require_git(), exports2);
6642
6803
  __exportStar(require_process(), exports2);
6643
6804
  __exportStar(require_setup(), exports2);
6805
+ __exportStar(require_shell(), exports2);
6644
6806
  __exportStar(require_types2(), exports2);
6645
6807
  }
6646
6808
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meistrari/tela-cli",
3
- "version": "0.7.27",
3
+ "version": "0.7.29",
4
4
  "description": "Tela command line tools for local state and agent workflows.",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {