very-happy-cli 0.2.127 → 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-B9_vB_mY.mjs → AcpBackend-MAU4POiE.mjs} +16 -4
  2. package/dist/{AcpBackend-Cbykm5Pg.cjs → AcpBackend-kU2VqiYx.cjs} +16 -4
  3. package/dist/{AcpSessionManager-DGCsNKRd.cjs → AcpSessionManager-BWasT5jq.cjs} +1 -1
  4. package/dist/{AcpSessionManager-HsxKXreC.mjs → AcpSessionManager-uSGDDRqF.mjs} +1 -1
  5. package/dist/{agentGuidance-B-CazXmT.cjs → agentGuidance-B1PsijGg.cjs} +1 -1
  6. package/dist/{agentGuidance-CTyzeLCQ.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-Dwt-15hE.cjs → config-DswZvA8V.cjs} +4 -4
  10. package/dist/{config-DotNknpP.mjs → config-_DKtp9qs.mjs} +4 -4
  11. package/dist/{index-CWPgxeLD.mjs → index-1QwKRLYG.mjs} +4 -4
  12. package/dist/{index-DgjzHewW.cjs → index-BdZ7Dlg0.cjs} +185 -86
  13. package/dist/{index-C2kblG8-.mjs → index-FMMrmSa2.mjs} +115 -32
  14. package/dist/{index-DyvVjr8Y.cjs → index-dqKLs4dZ.cjs} +114 -31
  15. package/dist/{index-DhCEmP3d.cjs → index-lwOIU7K9.cjs} +4 -4
  16. package/dist/{index-B1qzJIMw.mjs → index-tr2Fqhby.mjs} +178 -83
  17. package/dist/index.cjs +4 -4
  18. package/dist/index.mjs +4 -4
  19. package/dist/{installTerminalHooks-cpuDExTT.mjs → installTerminalHooks-B3a0ugvz.mjs} +4 -4
  20. package/dist/{installTerminalHooks-DfBvxRdw.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-BDG3QjIB.cjs → limits-B5wJ5Slz.cjs} +7 -7
  26. package/dist/{limits-D2XM3dvN.mjs → limits-C41sn_OJ.mjs} +7 -7
  27. package/dist/{mcp-BZ3iYnBc.cjs → mcp-B7lwVQT8.cjs} +4 -4
  28. package/dist/{mcp-CpUrsnoC.mjs → mcp-BHNVwrwS.mjs} +4 -4
  29. package/dist/{runGemini-BY7uA-Uk.mjs → runGemini-FNZrH8yX.mjs} +6 -6
  30. package/dist/{runGemini-BE_nghsj.cjs → runGemini-gbflWQ3_.cjs} +6 -6
  31. package/dist/{runOpenClaw-Be_U4DHZ.mjs → runOpenClaw-3EF_Rqv_.mjs} +5 -5
  32. package/dist/{runOpenClaw-Cqun9jar.cjs → runOpenClaw-CmhYI7OB.cjs} +5 -5
  33. package/dist/{send-D2xX42zg.mjs → send-DV7IeBAv.mjs} +4 -4
  34. package/dist/{send-DbqRxLQW.cjs → send-DqedYZtc.cjs} +4 -4
  35. package/dist/{sessions-CtrMbMBJ.cjs → sessions-Bz243hZ9.cjs} +4 -4
  36. package/dist/{sessions-D06cLJ7f.mjs → sessions-ieB0bLb5.mjs} +4 -4
  37. package/dist/{spawn-Cu_kM761.cjs → spawn-BXwwueEs.cjs} +4 -4
  38. package/dist/{spawn-DMx1JKXo.mjs → spawn-CcqzmjhT.mjs} +4 -4
  39. package/dist/{teams-C2MfKWFe.cjs → teams-BtI6h4Dw.cjs} +4 -4
  40. package/dist/{teams-D7ubdfTY.mjs → teams-Bx79Wr9-.mjs} +4 -4
  41. package/dist/{todo-yvodzg_y.cjs → todo-B-Kj9lXl.cjs} +3 -3
  42. package/dist/{todo-hKSIY23F.mjs → todo-CGRuBaiH.mjs} +3 -3
  43. package/dist/{types-BuxqyzYf.cjs → types-Ba9u0uZL.cjs} +19 -5
  44. package/dist/{types-Df_vXvzD.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-BuxqyzYf.cjs');
7
- var persistence = require('./limits-BDG3QjIB.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-B-CazXmT.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,
@@ -4764,6 +4780,7 @@ function createSessionMetadata(opts) {
4764
4780
  version: persistence.packageJson.version,
4765
4781
  os: os.platform(),
4766
4782
  machineId: opts.machineId,
4783
+ ...opts.teamOperationId ? { teamOperationId: opts.teamOperationId } : {},
4767
4784
  homeDir: os.homedir(),
4768
4785
  happyHomeDir: persistence.configuration.happyHomeDir,
4769
4786
  happyLibDir: api.projectPath(),
@@ -5292,6 +5309,11 @@ ${typeLabels[type] || type}:`));
5292
5309
  console.log(chalk.green("\n\u2705 Doctor diagnosis complete!\n"));
5293
5310
  }
5294
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
+
5295
5317
  const SPAWN_AGENTS = ["claude", "codex", "gemini", "openclaw", "pi"];
5296
5318
  function isSpawnAgent(value) {
5297
5319
  return typeof value === "string" && SPAWN_AGENTS.includes(value);
@@ -7054,6 +7076,12 @@ function parsePiRunnerArgs(args) {
7054
7076
  parsed.verbose = true;
7055
7077
  continue;
7056
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
+ }
7057
7085
  if (arg === "--permission-mode") {
7058
7086
  const mode = normalizeAcpPermissionMode(args[++i]);
7059
7087
  if (mode) parsed.permissionMode = mode;
@@ -7676,7 +7704,7 @@ function parseJsonObject(text) {
7676
7704
  return null;
7677
7705
  }
7678
7706
  }
7679
- 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-DgjzHewW.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)) {
7680
7708
  const platformArch = `${platform}-${arch}`;
7681
7709
  const candidates = [
7682
7710
  `@anthropic-ai/claude-agent-sdk-${platformArch}/claude`,
@@ -9944,6 +9972,7 @@ async function startDaemon() {
9944
9972
  const currentCliAvailability = () => apiMachineRef?.getCLIAvailability() ?? startupCliAvailability;
9945
9973
  const spawnSessionImpl = async (options) => {
9946
9974
  persistence.logger.debugLargeJson("[DAEMON RUN] Spawning session", api.summarizeSpawnSessionForLog(options));
9975
+ const spawnModel = options.agent === "pi" ? sanitizeSpawnModel(options.model) : null;
9947
9976
  const spawnPermissionMode = sanitizeSpawnPermissionMode(options.permissionMode);
9948
9977
  if (options.permissionMode !== void 0 && spawnPermissionMode === null) {
9949
9978
  persistence.logger.warn("[DAEMON RUN] Ignoring invalid permissionMode in spawn request");
@@ -10168,7 +10197,8 @@ async function startDaemon() {
10168
10197
  const resumeId = agent === "claude" ? options.resumeClaudeSessionId : agent === "codex" ? options.resumeCodexThreadId : void 0;
10169
10198
  const resumeFragment = resumeId ? ` --resume ${api.shellescape(resumeId)}` : "";
10170
10199
  const permissionModeFragment = spawnPermissionMode ? ` --permission-mode ${api.shellescape(spawnPermissionMode)}` : "";
10171
- 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}`;
10172
10202
  const windowName = `happy-${Date.now()}-${agent}`;
10173
10203
  const tmuxEnv = {};
10174
10204
  for (const [key, value] of Object.entries(process.env)) {
@@ -10261,6 +10291,7 @@ async function startDaemon() {
10261
10291
  if (options.resumeCodexThreadId && agentCommand === "codex") {
10262
10292
  args.push("--resume", options.resumeCodexThreadId);
10263
10293
  }
10294
+ if (spawnModel) args.push("--model", spawnModel);
10264
10295
  if (spawnPermissionMode) {
10265
10296
  args.push("--permission-mode", spawnPermissionMode);
10266
10297
  }
@@ -12044,7 +12075,7 @@ function registerSideQuestionHandler(rpc, deps) {
12044
12075
  const retainMs = deps.retainMs ?? SIDE_QUESTION_RETAIN_MS;
12045
12076
  const maxRunMs = deps.maxRunMs ?? SIDE_QUESTION_MAX_RUN_MS;
12046
12077
  const run = deps.run ?? (async (input) => {
12047
- const { query } = await Promise.resolve().then(function () { return require('./index-DhCEmP3d.cjs'); });
12078
+ const { query } = await Promise.resolve().then(function () { return require('./index-lwOIU7K9.cjs'); });
12048
12079
  return runSideQuestion(query, input);
12049
12080
  });
12050
12081
  const slots = /* @__PURE__ */ new Map();
@@ -12146,7 +12177,7 @@ const MAX_TITLE_CHARS = 60;
12146
12177
  const GENERATION_TIMEOUT_MS = 3e4;
12147
12178
  function resolveClaudeBinary() {
12148
12179
  try {
12149
- 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-DgjzHewW.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)));
12150
12181
  const utilsPath = path.resolve(path.join(api.projectPath(), "scripts", "claude_version_utils.cjs"));
12151
12182
  const { getClaudeCliPath } = require$1(utilsPath);
12152
12183
  const path$1 = getClaudeCliPath();
@@ -14364,9 +14395,9 @@ function resolveLocalSignupBootstrap(configuredMode, configuredInviteCodes, gene
14364
14395
  };
14365
14396
  }
14366
14397
 
14367
- 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-DgjzHewW.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)));
14368
14399
  const __dirname$1 = path.dirname(__filename$1);
14369
- const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-DgjzHewW.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)));
14370
14401
  const PRISMA_QUERY_ENGINE_FILES = {
14371
14402
  "arm64-darwin": "libquery_engine-darwin-arm64.dylib.node",
14372
14403
  "x64-darwin": "libquery_engine-darwin.dylib.node",
@@ -14788,6 +14819,23 @@ async function ensureDaemonRunning() {
14788
14819
  persistence.logger.debug(`Happy background service did not become ready within ${DAEMON_READY_TIMEOUT_MS}ms; continuing anyway`);
14789
14820
  }
14790
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
+
14791
14839
  class BasePermissionHandler {
14792
14840
  pendingRequests = /* @__PURE__ */ new Map();
14793
14841
  session;
@@ -15427,6 +15475,11 @@ function createOfflineSessionStub(sessionTag) {
15427
15475
  },
15428
15476
  onUserMessage: () => {
15429
15477
  },
15478
+ onFileEvent: () => {
15479
+ },
15480
+ trackAttachmentDownload: () => {
15481
+ },
15482
+ drainAttachmentsForUserMessage: async () => [],
15430
15483
  rpcHandlerManager: {
15431
15484
  registerHandler: () => {
15432
15485
  }
@@ -15477,8 +15530,8 @@ function resolveCodexExecutionPolicy(permissionMode, sandboxManagedByHappy) {
15477
15530
  return "never";
15478
15531
  // Never ask, read-only enforced by sandbox
15479
15532
  case "safe-yolo":
15480
- return "on-failure";
15481
- // Auto-run, ask only on failure
15533
+ return "on-request";
15534
+ // Workspace auto-run; request approval for escalation (0.153 removed on-failure)
15482
15535
  case "yolo":
15483
15536
  return "never";
15484
15537
  // Full YOLO: never interrupt for approvals
@@ -16074,10 +16127,10 @@ function isCodexClearText(text) {
16074
16127
  }
16075
16128
  function enqueueCodexUserText(opts) {
16076
16129
  if (isCodexClearText(opts.text)) {
16077
- opts.queue.pushIsolateAndClear(opts.text, opts.mode, void 0, opts.sourceId);
16130
+ opts.queue.pushIsolateAndClear(opts.text, opts.mode, opts.attachments, opts.sourceId);
16078
16131
  return "clear";
16079
16132
  }
16080
- opts.queue.push(opts.text, opts.mode, void 0, opts.sourceId);
16133
+ opts.queue.push(opts.text, opts.mode, opts.attachments, opts.sourceId);
16081
16134
  return "queued";
16082
16135
  }
16083
16136
 
@@ -16201,6 +16254,7 @@ async function runCodex(opts) {
16201
16254
  ...forkedFromSessionId ? { parentSessionId: forkedFromSessionId } : {},
16202
16255
  ...forkedFromMessageId ? { forkedFromMessageId } : {}
16203
16256
  });
16257
+ metadata.attachmentKinds = [...CLAUDE_ATTACHMENT_KINDS];
16204
16258
  const reconnectSessionId = process.env.HAPPY_RECONNECT_SESSION_ID;
16205
16259
  const reconnectKeyBase64 = process.env.HAPPY_RECONNECT_ENCRYPTION_KEY;
16206
16260
  const reconnectVariant = process.env.HAPPY_RECONNECT_ENCRYPTION_VARIANT;
@@ -16308,76 +16362,88 @@ async function runCodex(opts) {
16308
16362
  "safe-yolo",
16309
16363
  "yolo"
16310
16364
  ];
16365
+ let discoveredModels = [];
16311
16366
  const VALID_REMOTE_EFFORTS = [
16312
16367
  "none",
16313
16368
  "minimal",
16314
16369
  "low",
16315
16370
  "medium",
16316
16371
  "high",
16317
- "xhigh"
16372
+ "xhigh",
16373
+ "max"
16318
16374
  ];
16375
+ registerAgentAttachmentDownloads(session);
16376
+ let userMessageDelivery = Promise.resolve();
16319
16377
  session.onUserMessage((message) => {
16320
- let messagePermissionMode = currentPermissionMode;
16321
- if (message.meta?.permissionMode) {
16322
- const incoming = message.meta.permissionMode;
16323
- if (VALID_REMOTE_PERMISSION_MODES.includes(incoming)) {
16324
- messagePermissionMode = incoming;
16325
- currentPermissionMode = messagePermissionMode;
16326
- 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
+ }
16327
16391
  } else {
16328
- 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");
16329
16393
  }
16330
- } else {
16331
- persistence.logger.debug("[Codex] User message received without a permission mode override");
16332
- }
16333
- let messageModel = currentModel;
16334
- if (message.meta?.hasOwnProperty("model")) {
16335
- messageModel = message.meta.model || void 0;
16336
- currentModel = messageModel;
16337
- persistence.logger.debug("[Codex] Model override updated", logValueMetadata(message.meta.model));
16338
- } else {
16339
- persistence.logger.debug("[Codex] User message received without a model override");
16340
- }
16341
- let messageEffort = currentEffort;
16342
- if (message.meta?.hasOwnProperty("effort")) {
16343
- const incoming = message.meta.effort;
16344
- if (incoming === null || incoming === void 0) {
16345
- messageEffort = void 0;
16346
- currentEffort = void 0;
16347
- persistence.logger.debug(`[Codex] Effort reset to default`);
16348
- } else if (typeof incoming === "string" && VALID_REMOTE_EFFORTS.includes(incoming)) {
16349
- messageEffort = incoming;
16350
- currentEffort = messageEffort;
16351
- 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
+ }
16352
16416
  } else {
16353
- persistence.logger.debug("[Codex] Ignoring invalid effort override", logValueMetadata(incoming));
16417
+ persistence.logger.debug("[Codex] User message received without an effort override");
16354
16418
  }
16355
- } else {
16356
- persistence.logger.debug("[Codex] User message received without an effort override");
16357
- }
16358
- let messageAppendSystemPrompt = currentAppendSystemPrompt;
16359
- if (message.meta?.hasOwnProperty("appendSystemPrompt")) {
16360
- messageAppendSystemPrompt = message.meta.appendSystemPrompt || void 0;
16361
- currentAppendSystemPrompt = messageAppendSystemPrompt;
16362
- persistence.logger.debug("[Codex] Append system prompt override updated", logValueMetadata(message.meta.appendSystemPrompt));
16363
- } else {
16364
- persistence.logger.debug("[Codex] User message received without an append system prompt override");
16365
- }
16366
- const enhancedMode = {
16367
- permissionMode: messagePermissionMode || "default",
16368
- model: messageModel,
16369
- appendSystemPrompt: messageAppendSystemPrompt,
16370
- effort: messageEffort
16371
- };
16372
- const enqueueResult = enqueueCodexUserText({
16373
- text: message.content.text,
16374
- mode: enhancedMode,
16375
- queue: messageQueue,
16376
- 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." });
16377
16446
  });
16378
- if (enqueueResult === "clear") {
16379
- persistence.logger.debug("[Codex] /clear command pushed to isolated queue");
16380
- }
16381
16447
  });
16382
16448
  let thinking = false;
16383
16449
  let currentTurnId = null;
@@ -16653,6 +16719,24 @@ async function runCodex(opts) {
16653
16719
  persistence.logger.debug("[codex]: client.connect begin");
16654
16720
  await client.connect();
16655
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
+ }
16656
16740
  if (opts.resumeThreadId) {
16657
16741
  await resumeExistingThread({
16658
16742
  client,
@@ -16741,6 +16825,11 @@ async function runCodex(opts) {
16741
16825
  message.mode.permissionMode,
16742
16826
  sandboxManagedByHappy
16743
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
+ }
16744
16833
  if (!client.hasActiveThread()) {
16745
16834
  const startedThread = await client.startThread({
16746
16835
  model: message.mode.model,
@@ -16763,7 +16852,12 @@ async function runCodex(opts) {
16763
16852
  includeAppendSystemPrompt,
16764
16853
  includeTitleInstruction: first
16765
16854
  });
16766
- 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),
16767
16861
  model: message.mode.model,
16768
16862
  approvalPolicy: executionPolicy.approvalPolicy,
16769
16863
  sandbox: executionPolicy.sandbox,
@@ -16998,7 +17092,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
16998
17092
  process.exit(0);
16999
17093
  } else if (subcommand === "install-terminal-hooks") {
17000
17094
  try {
17001
- const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-DfBvxRdw.cjs'); });
17095
+ const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-CV2LAKXO.cjs'); });
17002
17096
  const command = parseTerminalHooksArgs(args.slice(1));
17003
17097
  if (command.action === "help") {
17004
17098
  console.log(TERMINAL_HOOKS_HELP);
@@ -17015,7 +17109,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17015
17109
  }
17016
17110
  } else if (subcommand === "spawn") {
17017
17111
  try {
17018
- const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-Cu_kM761.cjs'); });
17112
+ const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-BXwwueEs.cjs'); });
17019
17113
  await handleSpawnCommand(args.slice(1));
17020
17114
  } catch (error) {
17021
17115
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -17027,7 +17121,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17027
17121
  return;
17028
17122
  } else if (subcommand === "sessions") {
17029
17123
  try {
17030
- const { handleSessionsCommand } = await Promise.resolve().then(function () { return require('./sessions-CtrMbMBJ.cjs'); });
17124
+ const { handleSessionsCommand } = await Promise.resolve().then(function () { return require('./sessions-Bz243hZ9.cjs'); });
17031
17125
  await handleSessionsCommand(args.slice(1));
17032
17126
  } catch (error) {
17033
17127
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -17039,7 +17133,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17039
17133
  return;
17040
17134
  } else if (subcommand === "send") {
17041
17135
  try {
17042
- const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-DbqRxLQW.cjs'); });
17136
+ const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-DqedYZtc.cjs'); });
17043
17137
  await handleSendCommand(args.slice(1));
17044
17138
  } catch (error) {
17045
17139
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -17145,9 +17239,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17145
17239
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
17146
17240
  const projectId = args[3];
17147
17241
  try {
17148
- const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-Dwt-15hE.cjs'); });
17149
- const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./limits-BDG3QjIB.cjs'); }).then(function (n) { return n.persistence; });
17150
- const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-BuxqyzYf.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; });
17151
17245
  let userEmail = void 0;
17152
17246
  try {
17153
17247
  const credentials = await readCredentialsForConfiguredRelay2();
@@ -17178,7 +17272,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17178
17272
  }
17179
17273
  if (geminiSubcommand === "project" && args[2] === "get") {
17180
17274
  try {
17181
- const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-Dwt-15hE.cjs'); });
17275
+ const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-DswZvA8V.cjs'); });
17182
17276
  const config = readGeminiLocalConfig();
17183
17277
  if (config.googleCloudProject) {
17184
17278
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -17218,7 +17312,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17218
17312
  process.exit(0);
17219
17313
  }
17220
17314
  try {
17221
- const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-BE_nghsj.cjs'); });
17315
+ const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-gbflWQ3_.cjs'); });
17222
17316
  let startedBy = void 0;
17223
17317
  for (let i = 1; i < args.length; i++) {
17224
17318
  if (args[i] === "--started-by") {
@@ -17248,7 +17342,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17248
17342
  }
17249
17343
  };
17250
17344
  try {
17251
- const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-DyvVjr8Y.cjs'); });
17345
+ const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-dqKLs4dZ.cjs'); });
17252
17346
  const parsed = parsePiRunnerArgs(args.slice(1));
17253
17347
  const resolved = resolveAcpAgentConfig(["pi", ...parsed.passthrough]);
17254
17348
  const { credentials } = await authAndSetupMachineIfNeeded();
@@ -17258,6 +17352,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17258
17352
  startedBy: parsed.startedBy,
17259
17353
  verbose: parsed.verbose,
17260
17354
  permissionMode: parsed.permissionMode,
17355
+ model: parsed.model,
17261
17356
  agentName: resolved.agentName,
17262
17357
  command: resolved.command,
17263
17358
  args: resolved.args,
@@ -17275,7 +17370,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17275
17370
  return;
17276
17371
  } else if (subcommand === "acp") {
17277
17372
  try {
17278
- const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-DyvVjr8Y.cjs'); });
17373
+ const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-dqKLs4dZ.cjs'); });
17279
17374
  let startedBy = void 0;
17280
17375
  let verbose = false;
17281
17376
  const acpArgs = [];
@@ -17315,7 +17410,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17315
17410
  return;
17316
17411
  } else if (subcommand === "openclaw") {
17317
17412
  try {
17318
- const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-Cqun9jar.cjs'); });
17413
+ const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-CmhYI7OB.cjs'); });
17319
17414
  let startedBy = void 0;
17320
17415
  let verbose = false;
17321
17416
  let gatewayUrl;
@@ -17366,7 +17461,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17366
17461
  return;
17367
17462
  } else if (subcommand === "todo") {
17368
17463
  try {
17369
- const { handleTodoCommand } = await Promise.resolve().then(function () { return require('./todo-yvodzg_y.cjs'); });
17464
+ const { handleTodoCommand } = await Promise.resolve().then(function () { return require('./todo-B-Kj9lXl.cjs'); });
17370
17465
  await handleTodoCommand(args.slice(1));
17371
17466
  } catch (error) {
17372
17467
  console.error(JSON.stringify({ error: error instanceof Error ? error.message : "Todo command failed" }));
@@ -17375,7 +17470,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17375
17470
  return;
17376
17471
  } else if (subcommand === "teams") {
17377
17472
  try {
17378
- const { handleTeamsCommand } = await Promise.resolve().then(function () { return require('./teams-C2MfKWFe.cjs'); });
17473
+ const { handleTeamsCommand } = await Promise.resolve().then(function () { return require('./teams-BtI6h4Dw.cjs'); });
17379
17474
  await handleTeamsCommand(args.slice(1));
17380
17475
  } catch (error) {
17381
17476
  console.error(error instanceof Error ? error.message : "Teams command failed");
@@ -17384,7 +17479,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17384
17479
  return;
17385
17480
  } else if (subcommand === "mcp" && args.length === 1) {
17386
17481
  try {
17387
- const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-BZ3iYnBc.cjs'); });
17482
+ const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-B7lwVQT8.cjs'); });
17388
17483
  await handleMcpCommand();
17389
17484
  } catch (error) {
17390
17485
  process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
@@ -17750,6 +17845,7 @@ exports.ALLOWED_SPAWN_PERMISSION_MODES = ALLOWED_SPAWN_PERMISSION_MODES;
17750
17845
  exports.BasePermissionHandler = BasePermissionHandler;
17751
17846
  exports.BaseReasoningProcessor = BaseReasoningProcessor;
17752
17847
  exports.CHANGE_TITLE_INSTRUCTION = CHANGE_TITLE_INSTRUCTION;
17848
+ exports.CLAUDE_ATTACHMENT_KINDS = CLAUDE_ATTACHMENT_KINDS;
17753
17849
  exports.DEFAULT_GEMINI_MODEL = DEFAULT_GEMINI_MODEL;
17754
17850
  exports.DEFAULT_RECENT_LIMIT = DEFAULT_RECENT_LIMIT;
17755
17851
  exports.GEMINI_API_KEY_ENV = GEMINI_API_KEY_ENV;
@@ -17763,6 +17859,7 @@ exports.SPAWN_AGENTS = SPAWN_AGENTS;
17763
17859
  exports.StreamRelay = StreamRelay;
17764
17860
  exports.TEAM_SKILL = TEAM_SKILL;
17765
17861
  exports.TitleGenerator = TitleGenerator;
17862
+ exports.appendStagedAttachmentsToPrompt = appendStagedAttachmentsToPrompt;
17766
17863
  exports.archiveSession = archiveSession;
17767
17864
  exports.checkIfDaemonRunningAndCleanupStaleState = checkIfDaemonRunningAndCleanupStaleState;
17768
17865
  exports.createSessionMetadata = createSessionMetadata;
@@ -17776,6 +17873,7 @@ exports.notifyDaemonSessionStarted = notifyDaemonSessionStarted;
17776
17873
  exports.pushClipboardViaDaemon = pushClipboardViaDaemon;
17777
17874
  exports.query = query;
17778
17875
  exports.readSessionTranscript = readSessionTranscript;
17876
+ exports.registerAgentAttachmentDownloads = registerAgentAttachmentDownloads;
17779
17877
  exports.registerAssistantSessionTools = registerAssistantSessionTools;
17780
17878
  exports.registerKillSessionHandler = registerKillSessionHandler;
17781
17879
  exports.removeSessionModeFile = removeSessionModeFile;
@@ -17786,6 +17884,7 @@ exports.sessionWebUrl = sessionWebUrl;
17786
17884
  exports.setTerminalTitleViaDaemon = setTerminalTitleViaDaemon;
17787
17885
  exports.setupOfflineReconnection = setupOfflineReconnection;
17788
17886
  exports.spawnDaemonSession = spawnDaemonSession;
17887
+ exports.stageClaudeAttachments = stageClaudeAttachments;
17789
17888
  exports.startHappyServer = startHappyServer;
17790
17889
  exports.stopSession = stopSession;
17791
17890
  exports.tmuxSupportsSessionEnv = tmuxSupportsSessionEnv;