@gethmy/agent 1.46.0 → 1.47.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.
Files changed (3) hide show
  1. package/dist/cli.js +128 -17
  2. package/dist/index.js +128 -17
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -3566,12 +3566,12 @@ var init_types = __esm(() => {
3566
3566
  postSummary: true
3567
3567
  },
3568
3568
  claude: {
3569
- model: "claude-opus-5",
3569
+ model: "claude-opus-5-5",
3570
3570
  escalateModel: "claude-fable-5-1",
3571
3571
  escalateAfterAttempts: 2,
3572
3572
  tiers: {
3573
3573
  simple: "claude-sonnet-5",
3574
- advanced: "claude-opus-5",
3574
+ advanced: "claude-opus-5-5",
3575
3575
  research: "claude-fable-5-1"
3576
3576
  },
3577
3577
  scoreBands: DEFAULT_SCORE_BANDS,
@@ -11595,6 +11595,15 @@ function resolveEffectiveAgentConfig(cfg, ws) {
11595
11595
  const withWorkspace = ws ? mergeAgentConfig(DEFAULT_AGENT_CONFIG, workspaceConfigToPartial(ws)) : DEFAULT_AGENT_CONFIG;
11596
11596
  return mergeAgentConfig(mergeAgentConfig(withWorkspace, cfg.agentOverrides), cfg.repoAgentOverrides);
11597
11597
  }
11598
+ function withdrawnMapFrom(models) {
11599
+ const withdrawn = {};
11600
+ for (const m of models) {
11601
+ if (m.status === "withdrawn" && m.replaced_by) {
11602
+ withdrawn[m.id] = m.replaced_by;
11603
+ }
11604
+ }
11605
+ return withdrawn;
11606
+ }
11598
11607
  var init_workspace_model_config = __esm(() => {
11599
11608
  init_config_merge();
11600
11609
  init_types();
@@ -14085,16 +14094,7 @@ class Pool {
14085
14094
  const { config: wsConfig, platformDefaults } = await client.getWorkspaceModelConfig(workspaceId);
14086
14095
  return layerPlatformDefaults(platformDefaults, wsConfig);
14087
14096
  }) : undefined;
14088
- const modelCatalog = daemonConfig ? new WorkspaceModelCache(async () => {
14089
- const { models } = await client.getModelCatalog();
14090
- const withdrawn = {};
14091
- for (const m of models) {
14092
- if (m.status === "withdrawn" && m.replaced_by) {
14093
- withdrawn[m.id] = m.replaced_by;
14094
- }
14095
- }
14096
- return withdrawn;
14097
- }) : undefined;
14097
+ const modelCatalog = daemonConfig ? new WorkspaceModelCache(async () => withdrawnMapFrom((await client.getModelCatalog()).models)) : undefined;
14098
14098
  const reportedConfig = daemonConfig ? new ReportedConfigCache(client, effectiveModelReport(config)) : undefined;
14099
14099
  for (let i = 0;i < config.poolSize; i++) {
14100
14100
  this.implWorkers.push(new Worker(i, config, client, this.identity, () => {
@@ -16230,6 +16230,93 @@ var init_reconcile = __esm(() => {
16230
16230
  init_types();
16231
16231
  });
16232
16232
 
16233
+ // src/startup-model.ts
16234
+ function describeStartupModel(config, layers, withdrawn) {
16235
+ const workspace = layers?.workspace ?? null;
16236
+ const platform = layers?.platform ?? null;
16237
+ const database = layerPlatformDefaults(platform, workspace);
16238
+ const claude = resolveEffectiveAgentConfig(config, database).claude;
16239
+ const pinned = ownObject(config.agentOverrides, "claude");
16240
+ const pinnedTiers = ownObject(pinned, "tiers");
16241
+ const pinnedModel = ownString(pinned, "model");
16242
+ let source = "built-in default";
16243
+ if (pinnedModel)
16244
+ source = "config.json";
16245
+ else if (workspace?.implement_model)
16246
+ source = "workspace";
16247
+ else if (platform?.implement_model)
16248
+ source = "platform";
16249
+ const warnings = [];
16250
+ const pins = [
16251
+ ["claude.model", pinnedModel, database?.implement_model],
16252
+ [
16253
+ "claude.escalateModel",
16254
+ ownString(pinned, "escalateModel"),
16255
+ database?.escalate_model
16256
+ ],
16257
+ ...TIERS.map((tier) => [
16258
+ `claude.tiers.${tier}`,
16259
+ ownString(pinnedTiers, tier),
16260
+ database?.tiers?.[tier]
16261
+ ])
16262
+ ];
16263
+ for (const [key, local, db] of pins) {
16264
+ if (local && db && local !== db) {
16265
+ warnings.push(`config.json pins ${key} to "${local}", which overrides the database default "${db}" — remove it from config.json to follow the app's model settings`);
16266
+ }
16267
+ }
16268
+ const effective = [
16269
+ ["claude.model", claude.model],
16270
+ ["claude.escalateModel", claude.escalateModel],
16271
+ ...TIERS.map((tier) => [`claude.tiers.${tier}`, claude.tiers[tier]])
16272
+ ];
16273
+ for (const [key, id] of effective) {
16274
+ const replacement = withdrawn?.[id];
16275
+ if (replacement) {
16276
+ warnings.push(`${key} resolves to "${id}", which is withdrawn in the model catalog — runs use its replacement "${replacement}"; update the setting to match`);
16277
+ }
16278
+ }
16279
+ return {
16280
+ model: claude.model,
16281
+ escalateModel: claude.escalateModel,
16282
+ reviewModel: config.agent.claude.reviewModel,
16283
+ source,
16284
+ resolved: layers !== null && withdrawn !== null,
16285
+ warnings
16286
+ };
16287
+ }
16288
+ async function resolveStartupModel(config, client) {
16289
+ const [layers, withdrawn] = await Promise.all([
16290
+ client.getWorkspaceModelConfig(config.workspaceId).then(({ config: workspace, platformDefaults }) => ({
16291
+ workspace,
16292
+ platform: platformDefaults ?? null
16293
+ })).catch(() => null),
16294
+ client.getModelCatalog().then(({ models }) => withdrawnMapFrom(models)).catch(() => null)
16295
+ ]);
16296
+ return describeStartupModel(config, layers, withdrawn);
16297
+ }
16298
+ function ownObject(source, key) {
16299
+ if (typeof source !== "object" || source === null)
16300
+ return {};
16301
+ const value = own(source, key);
16302
+ return typeof value === "object" && value !== null ? value : {};
16303
+ }
16304
+ function ownString(source, key) {
16305
+ const value = own(source, key);
16306
+ return typeof value === "string" && value !== "" ? value : undefined;
16307
+ }
16308
+ function startupModelLine(m) {
16309
+ const models = m.model === m.escalateModel ? m.model : `${m.model} → ${m.escalateModel} on retry/high · review ${m.reviewModel}`;
16310
+ const origin = m.resolved ? `from ${m.source}` : `from ${m.source}; database model settings unreachable, a pickup may resolve differently`;
16311
+ return `${models} (${origin})`;
16312
+ }
16313
+ var TIERS;
16314
+ var init_startup_model = __esm(() => {
16315
+ init_src();
16316
+ init_workspace_model_config();
16317
+ TIERS = ["simple", "advanced", "research"];
16318
+ });
16319
+
16233
16320
  // src/startup-banner.ts
16234
16321
  var exports_startup_banner = {};
16235
16322
  __export(exports_startup_banner, {
@@ -16245,6 +16332,7 @@ function prettyBanner(config, version) {
16245
16332
  let projectName;
16246
16333
  let gitProvider;
16247
16334
  let httpPort;
16335
+ let model;
16248
16336
  let failed = false;
16249
16337
  let rendered = false;
16250
16338
  return {
@@ -16257,6 +16345,9 @@ function prettyBanner(config, version) {
16257
16345
  setHttpPort(port) {
16258
16346
  httpPort = port;
16259
16347
  },
16348
+ setModel(resolved) {
16349
+ model = resolved;
16350
+ },
16260
16351
  check(message) {
16261
16352
  checks.push({ kind: "ok", message });
16262
16353
  },
@@ -16278,6 +16369,7 @@ function prettyBanner(config, version) {
16278
16369
  projectName,
16279
16370
  gitProvider,
16280
16371
  httpPort,
16372
+ model,
16281
16373
  checks,
16282
16374
  readyMessage: message
16283
16375
  });
@@ -16287,12 +16379,13 @@ function prettyBanner(config, version) {
16287
16379
  }
16288
16380
  function jsonBanner(config, version) {
16289
16381
  log45.info(TAG41, `Harmony Agent Daemon v${version} starting...`);
16290
- log45.info(TAG41, `Project: ${config.projectId} | Pool: ${config.agent.poolSize} | Model: ${config.agent.claude.model} | Runner: ${config.agent.runner} | Pickup: ${config.agent.pickupColumns.join(", ")}`);
16382
+ log45.info(TAG41, `Project: ${config.projectId} | Pool: ${config.agent.poolSize} | Runner: ${config.agent.runner} | Pickup: ${config.agent.pickupColumns.join(", ")}`);
16291
16383
  log45.info(TAG41, `Config: ${contextSourceLine(config)}`);
16292
16384
  if (config.agent.review.enabled) {
16293
16385
  log45.info(TAG41, `Review: enabled | Columns: ${config.agent.review.pickupColumns.join(", ")} | → ${config.agent.review.moveToColumn} / ${config.agent.review.failColumn}`);
16294
16386
  }
16295
16387
  let failed = false;
16388
+ let modelLogged = false;
16296
16389
  return {
16297
16390
  setProjectName(_name) {},
16298
16391
  setGitProvider(provider) {
@@ -16301,6 +16394,10 @@ function jsonBanner(config, version) {
16301
16394
  setHttpPort(port) {
16302
16395
  log45.info(TAG41, `HTTP server on port ${port}`);
16303
16396
  },
16397
+ setModel(resolved) {
16398
+ modelLogged = true;
16399
+ log45.info(TAG41, `Model: ${startupModelLine(resolved)}`);
16400
+ },
16304
16401
  check(message) {
16305
16402
  log45.info(TAG41, message);
16306
16403
  },
@@ -16313,6 +16410,8 @@ function jsonBanner(config, version) {
16313
16410
  async ready(message) {
16314
16411
  if (failed)
16315
16412
  return;
16413
+ if (!modelLogged)
16414
+ log45.info(TAG41, `Model: ${localModelLine(config)}`);
16316
16415
  log45.info(TAG41, message);
16317
16416
  }
16318
16417
  };
@@ -16324,6 +16423,7 @@ function renderPretty(input) {
16324
16423
  projectName,
16325
16424
  gitProvider,
16326
16425
  httpPort,
16426
+ model,
16327
16427
  checks,
16328
16428
  readyMessage
16329
16429
  } = input;
@@ -16331,7 +16431,7 @@ function renderPretty(input) {
16331
16431
  lines.push("");
16332
16432
  lines.push(titleRule(`Harmony Agent Daemon v${version}`));
16333
16433
  lines.push("");
16334
- for (const row of configRows(config, projectName, gitProvider, httpPort)) {
16434
+ for (const row of configRows(config, projectName, gitProvider, httpPort, model)) {
16335
16435
  lines.push(` ${dim(row.label.padEnd(9))} ${row.value}`);
16336
16436
  }
16337
16437
  lines.push("");
@@ -16345,7 +16445,7 @@ function renderPretty(input) {
16345
16445
  return lines.join(`
16346
16446
  `);
16347
16447
  }
16348
- function configRows(config, projectName, gitProvider, httpPort) {
16448
+ function configRows(config, projectName, gitProvider, httpPort, model) {
16349
16449
  const rows = [];
16350
16450
  const projectLabel = projectName ? `${projectName} (${shortenId(config.projectId)})` : shortenId(config.projectId);
16351
16451
  rows.push({ label: "Project", value: projectLabel });
@@ -16354,8 +16454,7 @@ function configRows(config, projectName, gitProvider, httpPort) {
16354
16454
  const reviewEnabled = config.agent.review.enabled;
16355
16455
  const poolDesc = reviewEnabled ? `Pool ${config.agent.poolSize} impl + ${config.agent.review.poolSize} review` : `Pool ${config.agent.poolSize} impl`;
16356
16456
  const flowDesc = reviewEnabled ? `Pickup ${config.agent.pickupColumns[0]} → ${config.agent.completion.moveToColumn} → ${config.agent.review.moveToColumn}` : `Pickup ${config.agent.pickupColumns.join(", ")}`;
16357
- const { model, escalateModel, reviewModel } = config.agent.claude;
16358
- const modelDesc = model === escalateModel ? model : `${model} → ${escalateModel} on retry/high · review ${reviewModel}`;
16457
+ const modelDesc = model ? startupModelLine(model) : localModelLine(config);
16359
16458
  rows.push({
16360
16459
  label: "Model",
16361
16460
  value: `${modelDesc} · ${poolDesc} · ${flowDesc}`
@@ -16389,6 +16488,11 @@ function titleRule(title) {
16389
16488
  const suffix = "─".repeat(Math.max(3, RULE_WIDTH - prefix.length - title.length - surround.length));
16390
16489
  return dim(`${prefix}${title}${surround}${suffix}`);
16391
16490
  }
16491
+ function localModelLine(config) {
16492
+ const { model, escalateModel, reviewModel } = config.agent.claude;
16493
+ const models = model === escalateModel ? model : `${model} → ${escalateModel} on retry/high · review ${reviewModel}`;
16494
+ return `${models} (local config only; database model settings not read)`;
16495
+ }
16392
16496
  function runnerDesc(runner) {
16393
16497
  return runner === "sdk" ? "sdk (Agent SDK)" : "cli (Claude CLI)";
16394
16498
  }
@@ -16409,6 +16513,7 @@ function yellow(s) {
16409
16513
  var TAG41 = "daemon", RULE_WIDTH = 70, ANSI;
16410
16514
  var init_startup_banner = __esm(() => {
16411
16515
  init_port_registry();
16516
+ init_startup_model();
16412
16517
  ANSI = {
16413
16518
  reset: "\x1B[0m",
16414
16519
  dim: "\x1B[2m",
@@ -17766,6 +17871,11 @@ async function main() {
17766
17871
  } catch (err) {
17767
17872
  log50.warn(TAG46, `Could not report model config: ${err instanceof Error ? err.message : String(err)}`);
17768
17873
  }
17874
+ const startupModel = await resolveStartupModel(config, client);
17875
+ banner.setModel(startupModel);
17876
+ for (const warning of startupModel.warnings) {
17877
+ banner.warn(warning);
17878
+ }
17769
17879
  migrateConfigDir();
17770
17880
  try {
17771
17881
  migrateLegacyStateFile({
@@ -18088,6 +18198,7 @@ var init_src2 = __esm(() => {
18088
18198
  init_recovery();
18089
18199
  init_review_worktree();
18090
18200
  init_startup_banner();
18201
+ init_startup_model();
18091
18202
  init_state_migration();
18092
18203
  init_state_store();
18093
18204
  init_stream_parser_selftest();
package/dist/index.js CHANGED
@@ -3565,12 +3565,12 @@ var init_types = __esm(() => {
3565
3565
  postSummary: true
3566
3566
  },
3567
3567
  claude: {
3568
- model: "claude-opus-5",
3568
+ model: "claude-opus-5-5",
3569
3569
  escalateModel: "claude-fable-5-1",
3570
3570
  escalateAfterAttempts: 2,
3571
3571
  tiers: {
3572
3572
  simple: "claude-sonnet-5",
3573
- advanced: "claude-opus-5",
3573
+ advanced: "claude-opus-5-5",
3574
3574
  research: "claude-fable-5-1"
3575
3575
  },
3576
3576
  scoreBands: DEFAULT_SCORE_BANDS,
@@ -11594,6 +11594,15 @@ function resolveEffectiveAgentConfig(cfg, ws) {
11594
11594
  const withWorkspace = ws ? mergeAgentConfig(DEFAULT_AGENT_CONFIG, workspaceConfigToPartial(ws)) : DEFAULT_AGENT_CONFIG;
11595
11595
  return mergeAgentConfig(mergeAgentConfig(withWorkspace, cfg.agentOverrides), cfg.repoAgentOverrides);
11596
11596
  }
11597
+ function withdrawnMapFrom(models) {
11598
+ const withdrawn = {};
11599
+ for (const m of models) {
11600
+ if (m.status === "withdrawn" && m.replaced_by) {
11601
+ withdrawn[m.id] = m.replaced_by;
11602
+ }
11603
+ }
11604
+ return withdrawn;
11605
+ }
11597
11606
  var init_workspace_model_config = __esm(() => {
11598
11607
  init_config_merge();
11599
11608
  init_types();
@@ -14084,16 +14093,7 @@ class Pool {
14084
14093
  const { config: wsConfig, platformDefaults } = await client.getWorkspaceModelConfig(workspaceId);
14085
14094
  return layerPlatformDefaults(platformDefaults, wsConfig);
14086
14095
  }) : undefined;
14087
- const modelCatalog = daemonConfig ? new WorkspaceModelCache(async () => {
14088
- const { models } = await client.getModelCatalog();
14089
- const withdrawn = {};
14090
- for (const m of models) {
14091
- if (m.status === "withdrawn" && m.replaced_by) {
14092
- withdrawn[m.id] = m.replaced_by;
14093
- }
14094
- }
14095
- return withdrawn;
14096
- }) : undefined;
14096
+ const modelCatalog = daemonConfig ? new WorkspaceModelCache(async () => withdrawnMapFrom((await client.getModelCatalog()).models)) : undefined;
14097
14097
  const reportedConfig = daemonConfig ? new ReportedConfigCache(client, effectiveModelReport(config)) : undefined;
14098
14098
  for (let i = 0;i < config.poolSize; i++) {
14099
14099
  this.implWorkers.push(new Worker(i, config, client, this.identity, () => {
@@ -16229,6 +16229,93 @@ var init_reconcile = __esm(() => {
16229
16229
  init_types();
16230
16230
  });
16231
16231
 
16232
+ // src/startup-model.ts
16233
+ function describeStartupModel(config, layers, withdrawn) {
16234
+ const workspace = layers?.workspace ?? null;
16235
+ const platform = layers?.platform ?? null;
16236
+ const database = layerPlatformDefaults(platform, workspace);
16237
+ const claude = resolveEffectiveAgentConfig(config, database).claude;
16238
+ const pinned = ownObject(config.agentOverrides, "claude");
16239
+ const pinnedTiers = ownObject(pinned, "tiers");
16240
+ const pinnedModel = ownString(pinned, "model");
16241
+ let source = "built-in default";
16242
+ if (pinnedModel)
16243
+ source = "config.json";
16244
+ else if (workspace?.implement_model)
16245
+ source = "workspace";
16246
+ else if (platform?.implement_model)
16247
+ source = "platform";
16248
+ const warnings = [];
16249
+ const pins = [
16250
+ ["claude.model", pinnedModel, database?.implement_model],
16251
+ [
16252
+ "claude.escalateModel",
16253
+ ownString(pinned, "escalateModel"),
16254
+ database?.escalate_model
16255
+ ],
16256
+ ...TIERS.map((tier) => [
16257
+ `claude.tiers.${tier}`,
16258
+ ownString(pinnedTiers, tier),
16259
+ database?.tiers?.[tier]
16260
+ ])
16261
+ ];
16262
+ for (const [key, local, db] of pins) {
16263
+ if (local && db && local !== db) {
16264
+ warnings.push(`config.json pins ${key} to "${local}", which overrides the database default "${db}" — remove it from config.json to follow the app's model settings`);
16265
+ }
16266
+ }
16267
+ const effective = [
16268
+ ["claude.model", claude.model],
16269
+ ["claude.escalateModel", claude.escalateModel],
16270
+ ...TIERS.map((tier) => [`claude.tiers.${tier}`, claude.tiers[tier]])
16271
+ ];
16272
+ for (const [key, id] of effective) {
16273
+ const replacement = withdrawn?.[id];
16274
+ if (replacement) {
16275
+ warnings.push(`${key} resolves to "${id}", which is withdrawn in the model catalog — runs use its replacement "${replacement}"; update the setting to match`);
16276
+ }
16277
+ }
16278
+ return {
16279
+ model: claude.model,
16280
+ escalateModel: claude.escalateModel,
16281
+ reviewModel: config.agent.claude.reviewModel,
16282
+ source,
16283
+ resolved: layers !== null && withdrawn !== null,
16284
+ warnings
16285
+ };
16286
+ }
16287
+ async function resolveStartupModel(config, client) {
16288
+ const [layers, withdrawn] = await Promise.all([
16289
+ client.getWorkspaceModelConfig(config.workspaceId).then(({ config: workspace, platformDefaults }) => ({
16290
+ workspace,
16291
+ platform: platformDefaults ?? null
16292
+ })).catch(() => null),
16293
+ client.getModelCatalog().then(({ models }) => withdrawnMapFrom(models)).catch(() => null)
16294
+ ]);
16295
+ return describeStartupModel(config, layers, withdrawn);
16296
+ }
16297
+ function ownObject(source, key) {
16298
+ if (typeof source !== "object" || source === null)
16299
+ return {};
16300
+ const value = own(source, key);
16301
+ return typeof value === "object" && value !== null ? value : {};
16302
+ }
16303
+ function ownString(source, key) {
16304
+ const value = own(source, key);
16305
+ return typeof value === "string" && value !== "" ? value : undefined;
16306
+ }
16307
+ function startupModelLine(m) {
16308
+ const models = m.model === m.escalateModel ? m.model : `${m.model} → ${m.escalateModel} on retry/high · review ${m.reviewModel}`;
16309
+ const origin = m.resolved ? `from ${m.source}` : `from ${m.source}; database model settings unreachable, a pickup may resolve differently`;
16310
+ return `${models} (${origin})`;
16311
+ }
16312
+ var TIERS;
16313
+ var init_startup_model = __esm(() => {
16314
+ init_src();
16315
+ init_workspace_model_config();
16316
+ TIERS = ["simple", "advanced", "research"];
16317
+ });
16318
+
16232
16319
  // src/startup-banner.ts
16233
16320
  var exports_startup_banner = {};
16234
16321
  __export(exports_startup_banner, {
@@ -16244,6 +16331,7 @@ function prettyBanner(config, version) {
16244
16331
  let projectName;
16245
16332
  let gitProvider;
16246
16333
  let httpPort;
16334
+ let model;
16247
16335
  let failed = false;
16248
16336
  let rendered = false;
16249
16337
  return {
@@ -16256,6 +16344,9 @@ function prettyBanner(config, version) {
16256
16344
  setHttpPort(port) {
16257
16345
  httpPort = port;
16258
16346
  },
16347
+ setModel(resolved) {
16348
+ model = resolved;
16349
+ },
16259
16350
  check(message) {
16260
16351
  checks.push({ kind: "ok", message });
16261
16352
  },
@@ -16277,6 +16368,7 @@ function prettyBanner(config, version) {
16277
16368
  projectName,
16278
16369
  gitProvider,
16279
16370
  httpPort,
16371
+ model,
16280
16372
  checks,
16281
16373
  readyMessage: message
16282
16374
  });
@@ -16286,12 +16378,13 @@ function prettyBanner(config, version) {
16286
16378
  }
16287
16379
  function jsonBanner(config, version) {
16288
16380
  log45.info(TAG41, `Harmony Agent Daemon v${version} starting...`);
16289
- log45.info(TAG41, `Project: ${config.projectId} | Pool: ${config.agent.poolSize} | Model: ${config.agent.claude.model} | Runner: ${config.agent.runner} | Pickup: ${config.agent.pickupColumns.join(", ")}`);
16381
+ log45.info(TAG41, `Project: ${config.projectId} | Pool: ${config.agent.poolSize} | Runner: ${config.agent.runner} | Pickup: ${config.agent.pickupColumns.join(", ")}`);
16290
16382
  log45.info(TAG41, `Config: ${contextSourceLine(config)}`);
16291
16383
  if (config.agent.review.enabled) {
16292
16384
  log45.info(TAG41, `Review: enabled | Columns: ${config.agent.review.pickupColumns.join(", ")} | → ${config.agent.review.moveToColumn} / ${config.agent.review.failColumn}`);
16293
16385
  }
16294
16386
  let failed = false;
16387
+ let modelLogged = false;
16295
16388
  return {
16296
16389
  setProjectName(_name) {},
16297
16390
  setGitProvider(provider) {
@@ -16300,6 +16393,10 @@ function jsonBanner(config, version) {
16300
16393
  setHttpPort(port) {
16301
16394
  log45.info(TAG41, `HTTP server on port ${port}`);
16302
16395
  },
16396
+ setModel(resolved) {
16397
+ modelLogged = true;
16398
+ log45.info(TAG41, `Model: ${startupModelLine(resolved)}`);
16399
+ },
16303
16400
  check(message) {
16304
16401
  log45.info(TAG41, message);
16305
16402
  },
@@ -16312,6 +16409,8 @@ function jsonBanner(config, version) {
16312
16409
  async ready(message) {
16313
16410
  if (failed)
16314
16411
  return;
16412
+ if (!modelLogged)
16413
+ log45.info(TAG41, `Model: ${localModelLine(config)}`);
16315
16414
  log45.info(TAG41, message);
16316
16415
  }
16317
16416
  };
@@ -16323,6 +16422,7 @@ function renderPretty(input) {
16323
16422
  projectName,
16324
16423
  gitProvider,
16325
16424
  httpPort,
16425
+ model,
16326
16426
  checks,
16327
16427
  readyMessage
16328
16428
  } = input;
@@ -16330,7 +16430,7 @@ function renderPretty(input) {
16330
16430
  lines.push("");
16331
16431
  lines.push(titleRule(`Harmony Agent Daemon v${version}`));
16332
16432
  lines.push("");
16333
- for (const row of configRows(config, projectName, gitProvider, httpPort)) {
16433
+ for (const row of configRows(config, projectName, gitProvider, httpPort, model)) {
16334
16434
  lines.push(` ${dim(row.label.padEnd(9))} ${row.value}`);
16335
16435
  }
16336
16436
  lines.push("");
@@ -16344,7 +16444,7 @@ function renderPretty(input) {
16344
16444
  return lines.join(`
16345
16445
  `);
16346
16446
  }
16347
- function configRows(config, projectName, gitProvider, httpPort) {
16447
+ function configRows(config, projectName, gitProvider, httpPort, model) {
16348
16448
  const rows = [];
16349
16449
  const projectLabel = projectName ? `${projectName} (${shortenId(config.projectId)})` : shortenId(config.projectId);
16350
16450
  rows.push({ label: "Project", value: projectLabel });
@@ -16353,8 +16453,7 @@ function configRows(config, projectName, gitProvider, httpPort) {
16353
16453
  const reviewEnabled = config.agent.review.enabled;
16354
16454
  const poolDesc = reviewEnabled ? `Pool ${config.agent.poolSize} impl + ${config.agent.review.poolSize} review` : `Pool ${config.agent.poolSize} impl`;
16355
16455
  const flowDesc = reviewEnabled ? `Pickup ${config.agent.pickupColumns[0]} → ${config.agent.completion.moveToColumn} → ${config.agent.review.moveToColumn}` : `Pickup ${config.agent.pickupColumns.join(", ")}`;
16356
- const { model, escalateModel, reviewModel } = config.agent.claude;
16357
- const modelDesc = model === escalateModel ? model : `${model} → ${escalateModel} on retry/high · review ${reviewModel}`;
16456
+ const modelDesc = model ? startupModelLine(model) : localModelLine(config);
16358
16457
  rows.push({
16359
16458
  label: "Model",
16360
16459
  value: `${modelDesc} · ${poolDesc} · ${flowDesc}`
@@ -16388,6 +16487,11 @@ function titleRule(title) {
16388
16487
  const suffix = "─".repeat(Math.max(3, RULE_WIDTH - prefix.length - title.length - surround.length));
16389
16488
  return dim(`${prefix}${title}${surround}${suffix}`);
16390
16489
  }
16490
+ function localModelLine(config) {
16491
+ const { model, escalateModel, reviewModel } = config.agent.claude;
16492
+ const models = model === escalateModel ? model : `${model} → ${escalateModel} on retry/high · review ${reviewModel}`;
16493
+ return `${models} (local config only; database model settings not read)`;
16494
+ }
16391
16495
  function runnerDesc(runner) {
16392
16496
  return runner === "sdk" ? "sdk (Agent SDK)" : "cli (Claude CLI)";
16393
16497
  }
@@ -16408,6 +16512,7 @@ function yellow(s) {
16408
16512
  var TAG41 = "daemon", RULE_WIDTH = 70, ANSI;
16409
16513
  var init_startup_banner = __esm(() => {
16410
16514
  init_port_registry();
16515
+ init_startup_model();
16411
16516
  ANSI = {
16412
16517
  reset: "\x1B[0m",
16413
16518
  dim: "\x1B[2m",
@@ -17765,6 +17870,11 @@ async function main() {
17765
17870
  } catch (err) {
17766
17871
  log50.warn(TAG46, `Could not report model config: ${err instanceof Error ? err.message : String(err)}`);
17767
17872
  }
17873
+ const startupModel = await resolveStartupModel(config, client);
17874
+ banner.setModel(startupModel);
17875
+ for (const warning of startupModel.warnings) {
17876
+ banner.warn(warning);
17877
+ }
17768
17878
  migrateConfigDir();
17769
17879
  try {
17770
17880
  migrateLegacyStateFile({
@@ -18087,6 +18197,7 @@ var init_src2 = __esm(() => {
18087
18197
  init_recovery();
18088
18198
  init_review_worktree();
18089
18199
  init_startup_banner();
18200
+ init_startup_model();
18090
18201
  init_state_migration();
18091
18202
  init_state_store();
18092
18203
  init_stream_parser_selftest();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gethmy/agent",
3
- "version": "1.46.0",
3
+ "version": "1.47.0",
4
4
  "description": "Push-based agent daemon for Harmony — picks up assigned cards, builds them in isolated git worktrees, and opens PRs. It runs where you put it.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",