very-happy-cli 0.2.128 → 0.2.129

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 (45) hide show
  1. package/dist/{AcpBackend-D7987ody.mjs → AcpBackend-MAU4POiE.mjs} +16 -4
  2. package/dist/{AcpBackend-BYU6J2n0.cjs → AcpBackend-kU2VqiYx.cjs} +16 -4
  3. package/dist/{AcpSessionManager-artXJgqb.cjs → AcpSessionManager-BWasT5jq.cjs} +1 -1
  4. package/dist/{AcpSessionManager-BwrjVZyn.mjs → AcpSessionManager-uSGDDRqF.mjs} +1 -1
  5. package/dist/{agentGuidance-B1xYgHx6.cjs → agentGuidance-B1PsijGg.cjs} +1 -1
  6. package/dist/{agentGuidance-BPGPaNlo.mjs → agentGuidance-DlZ5s0Om.mjs} +1 -1
  7. package/dist/codex/happyMcpStdioBridge.cjs +2 -2
  8. package/dist/codex/happyMcpStdioBridge.mjs +2 -2
  9. package/dist/{config-Dmkzs3o4.cjs → config-DswZvA8V.cjs} +4 -4
  10. package/dist/{config-DSBE0Az0.mjs → config-_DKtp9qs.mjs} +4 -4
  11. package/dist/{index-35FahgEU.mjs → index-1QwKRLYG.mjs} +4 -4
  12. package/dist/{index-D_YVlpsW.cjs → index-BdZ7Dlg0.cjs} +184 -86
  13. package/dist/{index-m0Dnccc_.mjs → index-FMMrmSa2.mjs} +115 -32
  14. package/dist/{index-vyTJsT_R.cjs → index-dqKLs4dZ.cjs} +114 -31
  15. package/dist/{index-CJmXLSQc.cjs → index-lwOIU7K9.cjs} +4 -4
  16. package/dist/{index-CfM6ewd8.mjs → index-tr2Fqhby.mjs} +177 -83
  17. package/dist/index.cjs +4 -4
  18. package/dist/index.mjs +4 -4
  19. package/dist/{installTerminalHooks-ClrFe2fA.mjs → installTerminalHooks-B3a0ugvz.mjs} +4 -4
  20. package/dist/{installTerminalHooks-C1zwiJJ2.cjs → installTerminalHooks-CV2LAKXO.cjs} +4 -4
  21. package/dist/lib.cjs +2 -2
  22. package/dist/lib.d.cts +5 -0
  23. package/dist/lib.d.mts +5 -0
  24. package/dist/lib.mjs +2 -2
  25. package/dist/{limits-CrwtFbi8.cjs → limits-B5wJ5Slz.cjs} +7 -7
  26. package/dist/{limits-BNTLh2lw.mjs → limits-C41sn_OJ.mjs} +7 -7
  27. package/dist/{mcp-Bc_mmJt8.cjs → mcp-B7lwVQT8.cjs} +4 -4
  28. package/dist/{mcp-BsohER5A.mjs → mcp-BHNVwrwS.mjs} +4 -4
  29. package/dist/{runGemini-B9S85Vms.mjs → runGemini-FNZrH8yX.mjs} +6 -6
  30. package/dist/{runGemini-B2GesRWm.cjs → runGemini-gbflWQ3_.cjs} +6 -6
  31. package/dist/{runOpenClaw-Byhq-B1y.mjs → runOpenClaw-3EF_Rqv_.mjs} +5 -5
  32. package/dist/{runOpenClaw-DCK-R8qe.cjs → runOpenClaw-CmhYI7OB.cjs} +5 -5
  33. package/dist/{send-DQS1zNWp.mjs → send-DV7IeBAv.mjs} +4 -4
  34. package/dist/{send-CPdT1nOg.cjs → send-DqedYZtc.cjs} +4 -4
  35. package/dist/{sessions-DC0IKaD9.cjs → sessions-Bz243hZ9.cjs} +4 -4
  36. package/dist/{sessions-DIOdWnPe.mjs → sessions-ieB0bLb5.mjs} +4 -4
  37. package/dist/{spawn-DrnCW2QK.cjs → spawn-BXwwueEs.cjs} +4 -4
  38. package/dist/{spawn-DV4pIAHZ.mjs → spawn-CcqzmjhT.mjs} +4 -4
  39. package/dist/{teams-CwXEJs9I.cjs → teams-BtI6h4Dw.cjs} +4 -4
  40. package/dist/{teams-DlTHOiCk.mjs → teams-Bx79Wr9-.mjs} +4 -4
  41. package/dist/{todo-DrME15xq.cjs → todo-B-Kj9lXl.cjs} +3 -3
  42. package/dist/{todo-BwXURAbQ.mjs → todo-CGRuBaiH.mjs} +3 -3
  43. package/dist/{types-DfatCoQL.cjs → types-Ba9u0uZL.cjs} +19 -5
  44. package/dist/{types-CFs8FmiY.mjs → types-BvYEAHds.mjs} +19 -5
  45. package/package.json +7 -7
@@ -3,13 +3,13 @@
3
3
  var chalk = require('chalk');
4
4
  var os = require('node:os');
5
5
  var node_crypto = require('node:crypto');
6
- var api = require('./types-DfatCoQL.cjs');
7
- var persistence = require('./limits-CrwtFbi8.cjs');
6
+ var api = require('./types-Ba9u0uZL.cjs');
7
+ var persistence = require('./limits-B5wJ5Slz.cjs');
8
8
  var spawn = require('cross-spawn');
9
9
  var path = require('node:path');
10
10
  var node_readline = require('node:readline');
11
11
  var node_fs = require('node:fs');
12
- var agentGuidance = require('./agentGuidance-B1xYgHx6.cjs');
12
+ var agentGuidance = require('./agentGuidance-B1PsijGg.cjs');
13
13
  var promises = require('node:fs/promises');
14
14
  var fs = require('fs/promises');
15
15
  var ink = require('ink');
@@ -2068,6 +2068,20 @@ async function claudeRemote(opts) {
2068
2068
  prompt: messages,
2069
2069
  options: sdkOptions
2070
2070
  });
2071
+ let models;
2072
+ if (typeof response.supportedModels === "function") {
2073
+ try {
2074
+ models = (await response.supportedModels()).map((model) => ({
2075
+ code: model.value,
2076
+ value: model.displayName,
2077
+ description: model.description,
2078
+ resolvedModel: model.resolvedModel,
2079
+ ...model.supportsEffort === false ? { reasoningEfforts: [] } : model.supportedEffortLevels ? { reasoningEfforts: model.supportedEffortLevels } : {}
2080
+ }));
2081
+ } catch (error) {
2082
+ persistence.logger.debug("[claudeRemote] Model capability discovery unavailable");
2083
+ }
2084
+ }
2071
2085
  if (opts.onQueryReady) {
2072
2086
  opts.onQueryReady({
2073
2087
  setPermissionMode: (mode2) => response.setPermissionMode(mode2),
@@ -2119,6 +2133,7 @@ async function claudeRemote(opts) {
2119
2133
  const systemInit = message;
2120
2134
  if (opts.onSDKMetadata) {
2121
2135
  opts.onSDKMetadata({
2136
+ models,
2122
2137
  tools: systemInit.tools,
2123
2138
  slashCommands: systemInit.slash_commands,
2124
2139
  mcpServers: systemInit.mcp_servers?.map((s) => ({ name: s.name, status: s.status })),
@@ -3692,6 +3707,7 @@ function stripAttachmentManifest(text) {
3692
3707
  function applyClaudeSdkMetadata(current, update) {
3693
3708
  return {
3694
3709
  ...current,
3710
+ ...update.models ? { models: update.models } : {},
3695
3711
  tools: update.tools,
3696
3712
  slashCommands: update.slashCommands,
3697
3713
  mcpServers: update.mcpServers,
@@ -5293,6 +5309,11 @@ ${typeLabels[type] || type}:`));
5293
5309
  console.log(chalk.green("\n\u2705 Doctor diagnosis complete!\n"));
5294
5310
  }
5295
5311
 
5312
+ function sanitizeSpawnModel(value) {
5313
+ if (typeof value !== "string") return null;
5314
+ return /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}(\[1m\])?$/i.test(value) ? value : null;
5315
+ }
5316
+
5296
5317
  const SPAWN_AGENTS = ["claude", "codex", "gemini", "openclaw", "pi"];
5297
5318
  function isSpawnAgent(value) {
5298
5319
  return typeof value === "string" && SPAWN_AGENTS.includes(value);
@@ -7055,6 +7076,12 @@ function parsePiRunnerArgs(args) {
7055
7076
  parsed.verbose = true;
7056
7077
  continue;
7057
7078
  }
7079
+ if (arg === "--model") {
7080
+ const model = sanitizeSpawnModel(args[++i]);
7081
+ if (!model) throw new Error("Invalid --model identifier");
7082
+ parsed.model = model;
7083
+ continue;
7084
+ }
7058
7085
  if (arg === "--permission-mode") {
7059
7086
  const mode = normalizeAcpPermissionMode(args[++i]);
7060
7087
  if (mode) parsed.permissionMode = mode;
@@ -7677,7 +7704,7 @@ function parseJsonObject(text) {
7677
7704
  return null;
7678
7705
  }
7679
7706
  }
7680
- function resolveSdkClaudeBinary(platform = process.platform, arch = process.arch, resolver = (s) => node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-D_YVlpsW.cjs', document.baseURI).href))).resolve(s)) {
7707
+ function resolveSdkClaudeBinary(platform = process.platform, arch = process.arch, resolver = (s) => node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-BdZ7Dlg0.cjs', document.baseURI).href))).resolve(s)) {
7681
7708
  const platformArch = `${platform}-${arch}`;
7682
7709
  const candidates = [
7683
7710
  `@anthropic-ai/claude-agent-sdk-${platformArch}/claude`,
@@ -9945,6 +9972,7 @@ async function startDaemon() {
9945
9972
  const currentCliAvailability = () => apiMachineRef?.getCLIAvailability() ?? startupCliAvailability;
9946
9973
  const spawnSessionImpl = async (options) => {
9947
9974
  persistence.logger.debugLargeJson("[DAEMON RUN] Spawning session", api.summarizeSpawnSessionForLog(options));
9975
+ const spawnModel = options.agent === "pi" ? sanitizeSpawnModel(options.model) : null;
9948
9976
  const spawnPermissionMode = sanitizeSpawnPermissionMode(options.permissionMode);
9949
9977
  if (options.permissionMode !== void 0 && spawnPermissionMode === null) {
9950
9978
  persistence.logger.warn("[DAEMON RUN] Ignoring invalid permissionMode in spawn request");
@@ -10169,7 +10197,8 @@ async function startDaemon() {
10169
10197
  const resumeId = agent === "claude" ? options.resumeClaudeSessionId : agent === "codex" ? options.resumeCodexThreadId : void 0;
10170
10198
  const resumeFragment = resumeId ? ` --resume ${api.shellescape(resumeId)}` : "";
10171
10199
  const permissionModeFragment = spawnPermissionMode ? ` --permission-mode ${api.shellescape(spawnPermissionMode)}` : "";
10172
- const fullCommand = `node --no-warnings --no-deprecation ${cliPath} ${agent} --happy-starting-mode remote --started-by daemon${resumeFragment}${permissionModeFragment}`;
10200
+ const modelFragment = spawnModel ? ` --model ${api.shellescape(spawnModel)}` : "";
10201
+ const fullCommand = `node --no-warnings --no-deprecation ${cliPath} ${agent} --happy-starting-mode remote --started-by daemon${resumeFragment}${permissionModeFragment}${modelFragment}`;
10173
10202
  const windowName = `happy-${Date.now()}-${agent}`;
10174
10203
  const tmuxEnv = {};
10175
10204
  for (const [key, value] of Object.entries(process.env)) {
@@ -10262,6 +10291,7 @@ async function startDaemon() {
10262
10291
  if (options.resumeCodexThreadId && agentCommand === "codex") {
10263
10292
  args.push("--resume", options.resumeCodexThreadId);
10264
10293
  }
10294
+ if (spawnModel) args.push("--model", spawnModel);
10265
10295
  if (spawnPermissionMode) {
10266
10296
  args.push("--permission-mode", spawnPermissionMode);
10267
10297
  }
@@ -12045,7 +12075,7 @@ function registerSideQuestionHandler(rpc, deps) {
12045
12075
  const retainMs = deps.retainMs ?? SIDE_QUESTION_RETAIN_MS;
12046
12076
  const maxRunMs = deps.maxRunMs ?? SIDE_QUESTION_MAX_RUN_MS;
12047
12077
  const run = deps.run ?? (async (input) => {
12048
- const { query } = await Promise.resolve().then(function () { return require('./index-CJmXLSQc.cjs'); });
12078
+ const { query } = await Promise.resolve().then(function () { return require('./index-lwOIU7K9.cjs'); });
12049
12079
  return runSideQuestion(query, input);
12050
12080
  });
12051
12081
  const slots = /* @__PURE__ */ new Map();
@@ -12147,7 +12177,7 @@ const MAX_TITLE_CHARS = 60;
12147
12177
  const GENERATION_TIMEOUT_MS = 3e4;
12148
12178
  function resolveClaudeBinary() {
12149
12179
  try {
12150
- const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-D_YVlpsW.cjs', document.baseURI).href)));
12180
+ const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-BdZ7Dlg0.cjs', document.baseURI).href)));
12151
12181
  const utilsPath = path.resolve(path.join(api.projectPath(), "scripts", "claude_version_utils.cjs"));
12152
12182
  const { getClaudeCliPath } = require$1(utilsPath);
12153
12183
  const path$1 = getClaudeCliPath();
@@ -14365,9 +14395,9 @@ function resolveLocalSignupBootstrap(configuredMode, configuredInviteCodes, gene
14365
14395
  };
14366
14396
  }
14367
14397
 
14368
- const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-D_YVlpsW.cjs', document.baseURI).href)));
14398
+ const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-BdZ7Dlg0.cjs', document.baseURI).href)));
14369
14399
  const __dirname$1 = path.dirname(__filename$1);
14370
- const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-D_YVlpsW.cjs', document.baseURI).href)));
14400
+ const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-BdZ7Dlg0.cjs', document.baseURI).href)));
14371
14401
  const PRISMA_QUERY_ENGINE_FILES = {
14372
14402
  "arm64-darwin": "libquery_engine-darwin-arm64.dylib.node",
14373
14403
  "x64-darwin": "libquery_engine-darwin.dylib.node",
@@ -14789,6 +14819,23 @@ async function ensureDaemonRunning() {
14789
14819
  persistence.logger.debug(`Happy background service did not become ready within ${DAEMON_READY_TIMEOUT_MS}ms; continuing anyway`);
14790
14820
  }
14791
14821
 
14822
+ function registerAgentAttachmentDownloads(session) {
14823
+ session.onFileEvent((fileEvent) => {
14824
+ const attachment = fileEvent.content.data.ev;
14825
+ const download = (async () => {
14826
+ try {
14827
+ const data = await session.downloadAndDecryptAttachment(attachment.ref);
14828
+ if (!data) throw new Error("Attachment decryption failed");
14829
+ return { data, mimeType: attachment.mimeType ?? "image/jpeg", name: attachment.name };
14830
+ } catch {
14831
+ session.sendSessionEvent({ type: "message", message: `Could not download attachment: ${attachment.name}. Please attach it again.` });
14832
+ return null;
14833
+ }
14834
+ })();
14835
+ session.trackAttachmentDownload(download);
14836
+ });
14837
+ }
14838
+
14792
14839
  class BasePermissionHandler {
14793
14840
  pendingRequests = /* @__PURE__ */ new Map();
14794
14841
  session;
@@ -15428,6 +15475,11 @@ function createOfflineSessionStub(sessionTag) {
15428
15475
  },
15429
15476
  onUserMessage: () => {
15430
15477
  },
15478
+ onFileEvent: () => {
15479
+ },
15480
+ trackAttachmentDownload: () => {
15481
+ },
15482
+ drainAttachmentsForUserMessage: async () => [],
15431
15483
  rpcHandlerManager: {
15432
15484
  registerHandler: () => {
15433
15485
  }
@@ -15478,8 +15530,8 @@ function resolveCodexExecutionPolicy(permissionMode, sandboxManagedByHappy) {
15478
15530
  return "never";
15479
15531
  // Never ask, read-only enforced by sandbox
15480
15532
  case "safe-yolo":
15481
- return "on-failure";
15482
- // Auto-run, ask only on failure
15533
+ return "on-request";
15534
+ // Workspace auto-run; request approval for escalation (0.153 removed on-failure)
15483
15535
  case "yolo":
15484
15536
  return "never";
15485
15537
  // Full YOLO: never interrupt for approvals
@@ -16075,10 +16127,10 @@ function isCodexClearText(text) {
16075
16127
  }
16076
16128
  function enqueueCodexUserText(opts) {
16077
16129
  if (isCodexClearText(opts.text)) {
16078
- opts.queue.pushIsolateAndClear(opts.text, opts.mode, void 0, opts.sourceId);
16130
+ opts.queue.pushIsolateAndClear(opts.text, opts.mode, opts.attachments, opts.sourceId);
16079
16131
  return "clear";
16080
16132
  }
16081
- opts.queue.push(opts.text, opts.mode, void 0, opts.sourceId);
16133
+ opts.queue.push(opts.text, opts.mode, opts.attachments, opts.sourceId);
16082
16134
  return "queued";
16083
16135
  }
16084
16136
 
@@ -16202,6 +16254,7 @@ async function runCodex(opts) {
16202
16254
  ...forkedFromSessionId ? { parentSessionId: forkedFromSessionId } : {},
16203
16255
  ...forkedFromMessageId ? { forkedFromMessageId } : {}
16204
16256
  });
16257
+ metadata.attachmentKinds = [...CLAUDE_ATTACHMENT_KINDS];
16205
16258
  const reconnectSessionId = process.env.HAPPY_RECONNECT_SESSION_ID;
16206
16259
  const reconnectKeyBase64 = process.env.HAPPY_RECONNECT_ENCRYPTION_KEY;
16207
16260
  const reconnectVariant = process.env.HAPPY_RECONNECT_ENCRYPTION_VARIANT;
@@ -16309,76 +16362,88 @@ async function runCodex(opts) {
16309
16362
  "safe-yolo",
16310
16363
  "yolo"
16311
16364
  ];
16365
+ let discoveredModels = [];
16312
16366
  const VALID_REMOTE_EFFORTS = [
16313
16367
  "none",
16314
16368
  "minimal",
16315
16369
  "low",
16316
16370
  "medium",
16317
16371
  "high",
16318
- "xhigh"
16372
+ "xhigh",
16373
+ "max"
16319
16374
  ];
16375
+ registerAgentAttachmentDownloads(session);
16376
+ let userMessageDelivery = Promise.resolve();
16320
16377
  session.onUserMessage((message) => {
16321
- let messagePermissionMode = currentPermissionMode;
16322
- if (message.meta?.permissionMode) {
16323
- const incoming = message.meta.permissionMode;
16324
- if (VALID_REMOTE_PERMISSION_MODES.includes(incoming)) {
16325
- messagePermissionMode = incoming;
16326
- currentPermissionMode = messagePermissionMode;
16327
- persistence.logger.debug("[Codex] Valid permission mode override applied");
16378
+ const downloads = session.drainAttachmentsForUserMessage();
16379
+ userMessageDelivery = userMessageDelivery.then(async () => {
16380
+ const attachments = await downloads;
16381
+ let messagePermissionMode = currentPermissionMode;
16382
+ if (message.meta?.permissionMode) {
16383
+ const incoming = message.meta.permissionMode;
16384
+ if (VALID_REMOTE_PERMISSION_MODES.includes(incoming)) {
16385
+ messagePermissionMode = incoming;
16386
+ currentPermissionMode = messagePermissionMode;
16387
+ persistence.logger.debug("[Codex] Valid permission mode override applied");
16388
+ } else {
16389
+ persistence.logger.debug("[Codex] Ignoring invalid permission mode override", logValueMetadata(message.meta.permissionMode));
16390
+ }
16328
16391
  } else {
16329
- persistence.logger.debug("[Codex] Ignoring invalid permission mode override", logValueMetadata(message.meta.permissionMode));
16392
+ persistence.logger.debug("[Codex] User message received without a permission mode override");
16330
16393
  }
16331
- } else {
16332
- persistence.logger.debug("[Codex] User message received without a permission mode override");
16333
- }
16334
- let messageModel = currentModel;
16335
- if (message.meta?.hasOwnProperty("model")) {
16336
- messageModel = message.meta.model || void 0;
16337
- currentModel = messageModel;
16338
- persistence.logger.debug("[Codex] Model override updated", logValueMetadata(message.meta.model));
16339
- } else {
16340
- persistence.logger.debug("[Codex] User message received without a model override");
16341
- }
16342
- let messageEffort = currentEffort;
16343
- if (message.meta?.hasOwnProperty("effort")) {
16344
- const incoming = message.meta.effort;
16345
- if (incoming === null || incoming === void 0) {
16346
- messageEffort = void 0;
16347
- currentEffort = void 0;
16348
- persistence.logger.debug(`[Codex] Effort reset to default`);
16349
- } else if (typeof incoming === "string" && VALID_REMOTE_EFFORTS.includes(incoming)) {
16350
- messageEffort = incoming;
16351
- currentEffort = messageEffort;
16352
- persistence.logger.debug("[Codex] Valid effort override applied");
16394
+ let messageModel = currentModel;
16395
+ if (message.meta?.hasOwnProperty("model")) {
16396
+ messageModel = message.meta.model || void 0;
16397
+ currentModel = messageModel;
16398
+ persistence.logger.debug("[Codex] Model override updated", logValueMetadata(message.meta.model));
16399
+ } else {
16400
+ persistence.logger.debug("[Codex] User message received without a model override");
16401
+ }
16402
+ let messageEffort = currentEffort;
16403
+ if (message.meta?.hasOwnProperty("effort")) {
16404
+ const incoming = message.meta.effort;
16405
+ if (incoming === null || incoming === void 0) {
16406
+ messageEffort = void 0;
16407
+ currentEffort = void 0;
16408
+ persistence.logger.debug(`[Codex] Effort reset to default`);
16409
+ } else if (typeof incoming === "string") {
16410
+ messageEffort = incoming;
16411
+ currentEffort = messageEffort;
16412
+ persistence.logger.debug("[Codex] Valid effort override applied");
16413
+ } else {
16414
+ persistence.logger.debug("[Codex] Ignoring invalid effort override", logValueMetadata(incoming));
16415
+ }
16353
16416
  } else {
16354
- persistence.logger.debug("[Codex] Ignoring invalid effort override", logValueMetadata(incoming));
16417
+ persistence.logger.debug("[Codex] User message received without an effort override");
16355
16418
  }
16356
- } else {
16357
- persistence.logger.debug("[Codex] User message received without an effort override");
16358
- }
16359
- let messageAppendSystemPrompt = currentAppendSystemPrompt;
16360
- if (message.meta?.hasOwnProperty("appendSystemPrompt")) {
16361
- messageAppendSystemPrompt = message.meta.appendSystemPrompt || void 0;
16362
- currentAppendSystemPrompt = messageAppendSystemPrompt;
16363
- persistence.logger.debug("[Codex] Append system prompt override updated", logValueMetadata(message.meta.appendSystemPrompt));
16364
- } else {
16365
- persistence.logger.debug("[Codex] User message received without an append system prompt override");
16366
- }
16367
- const enhancedMode = {
16368
- permissionMode: messagePermissionMode || "default",
16369
- model: messageModel,
16370
- appendSystemPrompt: messageAppendSystemPrompt,
16371
- effort: messageEffort
16372
- };
16373
- const enqueueResult = enqueueCodexUserText({
16374
- text: message.content.text,
16375
- mode: enhancedMode,
16376
- queue: messageQueue,
16377
- sourceId: message.localKey
16419
+ let messageAppendSystemPrompt = currentAppendSystemPrompt;
16420
+ if (message.meta?.hasOwnProperty("appendSystemPrompt")) {
16421
+ messageAppendSystemPrompt = message.meta.appendSystemPrompt || void 0;
16422
+ currentAppendSystemPrompt = messageAppendSystemPrompt;
16423
+ persistence.logger.debug("[Codex] Append system prompt override updated", logValueMetadata(message.meta.appendSystemPrompt));
16424
+ } else {
16425
+ persistence.logger.debug("[Codex] User message received without an append system prompt override");
16426
+ }
16427
+ const enhancedMode = {
16428
+ permissionMode: messagePermissionMode || "default",
16429
+ model: messageModel,
16430
+ appendSystemPrompt: messageAppendSystemPrompt,
16431
+ effort: messageEffort
16432
+ };
16433
+ const enqueueResult = enqueueCodexUserText({
16434
+ text: message.content.text,
16435
+ mode: enhancedMode,
16436
+ queue: messageQueue,
16437
+ attachments,
16438
+ sourceId: message.localKey
16439
+ });
16440
+ if (enqueueResult === "clear") {
16441
+ persistence.logger.debug("[Codex] /clear command pushed to isolated queue");
16442
+ }
16443
+ }).catch((error) => {
16444
+ persistence.logger.warn("[Codex] Failed to prepare user attachments", safeCodexErrorMetadata(error));
16445
+ session.sendSessionEvent({ type: "message", message: "Could not prepare this message. Please send it again." });
16378
16446
  });
16379
- if (enqueueResult === "clear") {
16380
- persistence.logger.debug("[Codex] /clear command pushed to isolated queue");
16381
- }
16382
16447
  });
16383
16448
  let thinking = false;
16384
16449
  let currentTurnId = null;
@@ -16654,6 +16719,24 @@ async function runCodex(opts) {
16654
16719
  persistence.logger.debug("[codex]: client.connect begin");
16655
16720
  await client.connect();
16656
16721
  persistence.logger.debug("[codex]: client.connect done");
16722
+ try {
16723
+ discoveredModels = await client.listModels();
16724
+ if (discoveredModels.length > 0) {
16725
+ session.updateMetadata((metadata2) => ({
16726
+ ...metadata2,
16727
+ models: discoveredModels.map((model) => ({
16728
+ code: model.model,
16729
+ value: model.displayName,
16730
+ description: model.description,
16731
+ reasoningEfforts: model.supportedReasoningEfforts.map((option) => option.reasoningEffort),
16732
+ defaultReasoningEffort: model.defaultReasoningEffort
16733
+ })),
16734
+ defaultModelCode: discoveredModels.find((model) => model.isDefault)?.model
16735
+ }));
16736
+ }
16737
+ } catch (error) {
16738
+ persistence.logger.debug("[Codex] Model discovery unavailable; using compatibility fallback", safeCodexErrorMetadata(error));
16739
+ }
16657
16740
  if (opts.resumeThreadId) {
16658
16741
  await resumeExistingThread({
16659
16742
  client,
@@ -16742,6 +16825,11 @@ async function runCodex(opts) {
16742
16825
  message.mode.permissionMode,
16743
16826
  sandboxManagedByHappy
16744
16827
  );
16828
+ const selectedModel = discoveredModels.find((model) => message.mode.model ? model.model === message.mode.model : model.isDefault);
16829
+ const supportedEfforts = selectedModel?.supportedReasoningEfforts.map((option) => option.reasoningEffort) ?? VALID_REMOTE_EFFORTS;
16830
+ if (message.mode.effort && !supportedEfforts.includes(message.mode.effort)) {
16831
+ throw new Error(`Reasoning effort "${message.mode.effort}" is not supported by ${message.mode.model ?? "the default model"}. Choose a supported level.`);
16832
+ }
16745
16833
  if (!client.hasActiveThread()) {
16746
16834
  const startedThread = await client.startThread({
16747
16835
  model: message.mode.model,
@@ -16764,7 +16852,12 @@ async function runCodex(opts) {
16764
16852
  includeAppendSystemPrompt,
16765
16853
  includeTitleInstruction: first
16766
16854
  });
16767
- const result = await client.sendTurnAndWait(turnPrompt, {
16855
+ const staged = message.attachments?.length ? await stageClaudeAttachments(message.attachments, {
16856
+ happyHomeDir: persistence.configuration.happyHomeDir,
16857
+ sessionId: session.sessionId
16858
+ }) : [];
16859
+ const result = await client.sendTurnAndWait(appendStagedAttachmentsToPrompt(turnPrompt, staged), {
16860
+ images: staged.filter((file) => ["image/jpeg", "image/png", "image/gif", "image/webp"].includes(file.mimeType)).map((file) => file.path),
16768
16861
  model: message.mode.model,
16769
16862
  approvalPolicy: executionPolicy.approvalPolicy,
16770
16863
  sandbox: executionPolicy.sandbox,
@@ -16999,7 +17092,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
16999
17092
  process.exit(0);
17000
17093
  } else if (subcommand === "install-terminal-hooks") {
17001
17094
  try {
17002
- const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-C1zwiJJ2.cjs'); });
17095
+ const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-CV2LAKXO.cjs'); });
17003
17096
  const command = parseTerminalHooksArgs(args.slice(1));
17004
17097
  if (command.action === "help") {
17005
17098
  console.log(TERMINAL_HOOKS_HELP);
@@ -17016,7 +17109,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17016
17109
  }
17017
17110
  } else if (subcommand === "spawn") {
17018
17111
  try {
17019
- const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-DrnCW2QK.cjs'); });
17112
+ const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-BXwwueEs.cjs'); });
17020
17113
  await handleSpawnCommand(args.slice(1));
17021
17114
  } catch (error) {
17022
17115
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -17028,7 +17121,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17028
17121
  return;
17029
17122
  } else if (subcommand === "sessions") {
17030
17123
  try {
17031
- const { handleSessionsCommand } = await Promise.resolve().then(function () { return require('./sessions-DC0IKaD9.cjs'); });
17124
+ const { handleSessionsCommand } = await Promise.resolve().then(function () { return require('./sessions-Bz243hZ9.cjs'); });
17032
17125
  await handleSessionsCommand(args.slice(1));
17033
17126
  } catch (error) {
17034
17127
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -17040,7 +17133,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17040
17133
  return;
17041
17134
  } else if (subcommand === "send") {
17042
17135
  try {
17043
- const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-CPdT1nOg.cjs'); });
17136
+ const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-DqedYZtc.cjs'); });
17044
17137
  await handleSendCommand(args.slice(1));
17045
17138
  } catch (error) {
17046
17139
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -17146,9 +17239,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17146
17239
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
17147
17240
  const projectId = args[3];
17148
17241
  try {
17149
- const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-Dmkzs3o4.cjs'); });
17150
- const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./limits-CrwtFbi8.cjs'); }).then(function (n) { return n.persistence; });
17151
- const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-DfatCoQL.cjs'); }).then(function (n) { return n.api; });
17242
+ const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-DswZvA8V.cjs'); });
17243
+ const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./limits-B5wJ5Slz.cjs'); }).then(function (n) { return n.persistence; });
17244
+ const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-Ba9u0uZL.cjs'); }).then(function (n) { return n.api; });
17152
17245
  let userEmail = void 0;
17153
17246
  try {
17154
17247
  const credentials = await readCredentialsForConfiguredRelay2();
@@ -17179,7 +17272,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17179
17272
  }
17180
17273
  if (geminiSubcommand === "project" && args[2] === "get") {
17181
17274
  try {
17182
- const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-Dmkzs3o4.cjs'); });
17275
+ const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-DswZvA8V.cjs'); });
17183
17276
  const config = readGeminiLocalConfig();
17184
17277
  if (config.googleCloudProject) {
17185
17278
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -17219,7 +17312,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17219
17312
  process.exit(0);
17220
17313
  }
17221
17314
  try {
17222
- const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-B2GesRWm.cjs'); });
17315
+ const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-gbflWQ3_.cjs'); });
17223
17316
  let startedBy = void 0;
17224
17317
  for (let i = 1; i < args.length; i++) {
17225
17318
  if (args[i] === "--started-by") {
@@ -17249,7 +17342,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17249
17342
  }
17250
17343
  };
17251
17344
  try {
17252
- const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-vyTJsT_R.cjs'); });
17345
+ const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-dqKLs4dZ.cjs'); });
17253
17346
  const parsed = parsePiRunnerArgs(args.slice(1));
17254
17347
  const resolved = resolveAcpAgentConfig(["pi", ...parsed.passthrough]);
17255
17348
  const { credentials } = await authAndSetupMachineIfNeeded();
@@ -17259,6 +17352,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17259
17352
  startedBy: parsed.startedBy,
17260
17353
  verbose: parsed.verbose,
17261
17354
  permissionMode: parsed.permissionMode,
17355
+ model: parsed.model,
17262
17356
  agentName: resolved.agentName,
17263
17357
  command: resolved.command,
17264
17358
  args: resolved.args,
@@ -17276,7 +17370,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17276
17370
  return;
17277
17371
  } else if (subcommand === "acp") {
17278
17372
  try {
17279
- const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-vyTJsT_R.cjs'); });
17373
+ const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-dqKLs4dZ.cjs'); });
17280
17374
  let startedBy = void 0;
17281
17375
  let verbose = false;
17282
17376
  const acpArgs = [];
@@ -17316,7 +17410,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17316
17410
  return;
17317
17411
  } else if (subcommand === "openclaw") {
17318
17412
  try {
17319
- const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-DCK-R8qe.cjs'); });
17413
+ const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-CmhYI7OB.cjs'); });
17320
17414
  let startedBy = void 0;
17321
17415
  let verbose = false;
17322
17416
  let gatewayUrl;
@@ -17367,7 +17461,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17367
17461
  return;
17368
17462
  } else if (subcommand === "todo") {
17369
17463
  try {
17370
- const { handleTodoCommand } = await Promise.resolve().then(function () { return require('./todo-DrME15xq.cjs'); });
17464
+ const { handleTodoCommand } = await Promise.resolve().then(function () { return require('./todo-B-Kj9lXl.cjs'); });
17371
17465
  await handleTodoCommand(args.slice(1));
17372
17466
  } catch (error) {
17373
17467
  console.error(JSON.stringify({ error: error instanceof Error ? error.message : "Todo command failed" }));
@@ -17376,7 +17470,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17376
17470
  return;
17377
17471
  } else if (subcommand === "teams") {
17378
17472
  try {
17379
- const { handleTeamsCommand } = await Promise.resolve().then(function () { return require('./teams-CwXEJs9I.cjs'); });
17473
+ const { handleTeamsCommand } = await Promise.resolve().then(function () { return require('./teams-BtI6h4Dw.cjs'); });
17380
17474
  await handleTeamsCommand(args.slice(1));
17381
17475
  } catch (error) {
17382
17476
  console.error(error instanceof Error ? error.message : "Teams command failed");
@@ -17385,7 +17479,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17385
17479
  return;
17386
17480
  } else if (subcommand === "mcp" && args.length === 1) {
17387
17481
  try {
17388
- const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-Bc_mmJt8.cjs'); });
17482
+ const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-B7lwVQT8.cjs'); });
17389
17483
  await handleMcpCommand();
17390
17484
  } catch (error) {
17391
17485
  process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
@@ -17751,6 +17845,7 @@ exports.ALLOWED_SPAWN_PERMISSION_MODES = ALLOWED_SPAWN_PERMISSION_MODES;
17751
17845
  exports.BasePermissionHandler = BasePermissionHandler;
17752
17846
  exports.BaseReasoningProcessor = BaseReasoningProcessor;
17753
17847
  exports.CHANGE_TITLE_INSTRUCTION = CHANGE_TITLE_INSTRUCTION;
17848
+ exports.CLAUDE_ATTACHMENT_KINDS = CLAUDE_ATTACHMENT_KINDS;
17754
17849
  exports.DEFAULT_GEMINI_MODEL = DEFAULT_GEMINI_MODEL;
17755
17850
  exports.DEFAULT_RECENT_LIMIT = DEFAULT_RECENT_LIMIT;
17756
17851
  exports.GEMINI_API_KEY_ENV = GEMINI_API_KEY_ENV;
@@ -17764,6 +17859,7 @@ exports.SPAWN_AGENTS = SPAWN_AGENTS;
17764
17859
  exports.StreamRelay = StreamRelay;
17765
17860
  exports.TEAM_SKILL = TEAM_SKILL;
17766
17861
  exports.TitleGenerator = TitleGenerator;
17862
+ exports.appendStagedAttachmentsToPrompt = appendStagedAttachmentsToPrompt;
17767
17863
  exports.archiveSession = archiveSession;
17768
17864
  exports.checkIfDaemonRunningAndCleanupStaleState = checkIfDaemonRunningAndCleanupStaleState;
17769
17865
  exports.createSessionMetadata = createSessionMetadata;
@@ -17777,6 +17873,7 @@ exports.notifyDaemonSessionStarted = notifyDaemonSessionStarted;
17777
17873
  exports.pushClipboardViaDaemon = pushClipboardViaDaemon;
17778
17874
  exports.query = query;
17779
17875
  exports.readSessionTranscript = readSessionTranscript;
17876
+ exports.registerAgentAttachmentDownloads = registerAgentAttachmentDownloads;
17780
17877
  exports.registerAssistantSessionTools = registerAssistantSessionTools;
17781
17878
  exports.registerKillSessionHandler = registerKillSessionHandler;
17782
17879
  exports.removeSessionModeFile = removeSessionModeFile;
@@ -17787,6 +17884,7 @@ exports.sessionWebUrl = sessionWebUrl;
17787
17884
  exports.setTerminalTitleViaDaemon = setTerminalTitleViaDaemon;
17788
17885
  exports.setupOfflineReconnection = setupOfflineReconnection;
17789
17886
  exports.spawnDaemonSession = spawnDaemonSession;
17887
+ exports.stageClaudeAttachments = stageClaudeAttachments;
17790
17888
  exports.startHappyServer = startHappyServer;
17791
17889
  exports.stopSession = stopSession;
17792
17890
  exports.tmuxSupportsSessionEnv = tmuxSupportsSessionEnv;