very-happy-cli 0.2.111 → 0.2.113

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 (35) hide show
  1. package/dist/{AcpBackend-B_olk79F.cjs → AcpBackend-33KrZ5lq.cjs} +1 -1
  2. package/dist/{AcpBackend-CeXVb_s_.mjs → AcpBackend-Dldla8c8.mjs} +1 -1
  3. package/dist/{AcpSessionManager-vqdqfD1l.mjs → AcpSessionManager-BPSy8e5x.mjs} +1 -1
  4. package/dist/{AcpSessionManager-uXwWO2Tn.cjs → AcpSessionManager-DnodFLES.cjs} +1 -1
  5. package/dist/{config-vGkcq9nM.mjs → config-Bp2eRu4s.mjs} +2 -2
  6. package/dist/{config-BR3tkFL_.cjs → config-CzhVSd7F.cjs} +2 -2
  7. package/dist/{index-BOoGJGQc.cjs → index-Bhej85vt.cjs} +240 -19
  8. package/dist/{index-Bn-xsguz.mjs → index-C1KeV2ip.mjs} +236 -15
  9. package/dist/{index-C-RLk8-e.mjs → index-D7dc2QHa.mjs} +2 -2
  10. package/dist/{index-JAhGeW4_.mjs → index-DfAGG99Q.mjs} +5 -5
  11. package/dist/{index-CtBP0Qvc.cjs → index-H47khBtq.cjs} +4 -4
  12. package/dist/{index-SjthsMid.cjs → index-fjyucZBO.cjs} +2 -2
  13. package/dist/index.cjs +2 -2
  14. package/dist/index.mjs +2 -2
  15. package/dist/{installTerminalHooks-FbKaK149.cjs → installTerminalHooks-CxBFNpwn.cjs} +2 -2
  16. package/dist/{installTerminalHooks-ADNcNdnB.mjs → installTerminalHooks-hnyO1Trp.mjs} +2 -2
  17. package/dist/lib.cjs +1 -1
  18. package/dist/lib.d.cts +44 -0
  19. package/dist/lib.d.mts +44 -0
  20. package/dist/lib.mjs +1 -1
  21. package/dist/{mcp-DHPm_gvL.mjs → mcp-BlAJfG7B.mjs} +2 -2
  22. package/dist/{mcp-DPp-bYNE.cjs → mcp-D1XCJ2xc.cjs} +2 -2
  23. package/dist/{runGemini-D5ySpYIZ.cjs → runGemini-BhLjxHGD.cjs} +4 -4
  24. package/dist/{runGemini-CWWyjQMz.mjs → runGemini-DVb3uHxe.mjs} +4 -4
  25. package/dist/{runOpenClaw-Bwrb1LXP.cjs → runOpenClaw-BrGj8DO6.cjs} +3 -3
  26. package/dist/{runOpenClaw-Bv4rUTyJ.mjs → runOpenClaw-D_GPGmD3.mjs} +3 -3
  27. package/dist/{send-DBfSNILO.cjs → send-B9lvSBVC.cjs} +2 -2
  28. package/dist/{send-BlkxFZu4.mjs → send-XfDlFCXz.mjs} +2 -2
  29. package/dist/{sessions-CVuEsdRl.cjs → sessions-BkeCXy8-.cjs} +2 -2
  30. package/dist/{sessions-1fW8soBM.mjs → sessions-DwSgYAEK.mjs} +2 -2
  31. package/dist/{spawn-D_ZexrY9.cjs → spawn-BNvGZjic.cjs} +2 -2
  32. package/dist/{spawn-BorKN3W2.mjs → spawn-CwORJ-bq.mjs} +2 -2
  33. package/dist/{types-BG_5QKX5.cjs → types-BnsRaANk.cjs} +166 -11
  34. package/dist/{types-k_ipDb0c.mjs → types-CAzzJ4tO.mjs} +165 -11
  35. package/package.json +7 -7
@@ -29,7 +29,7 @@ import { SandboxManager } from '@anthropic-ai/sandbox-runtime';
29
29
  import { Expo } from 'expo-server-sdk';
30
30
 
31
31
  var name = "very-happy-cli";
32
- var version = "0.2.111";
32
+ var version = "0.2.113";
33
33
  var description = "Remote multi-agent workspace CLI with deep Claude integration, native terminal streaming, and self-hosting.";
34
34
  var author = "Kirill Dubovitskiy";
35
35
  var contributors = [
@@ -142,12 +142,12 @@ var dependencies = {
142
142
  zod: "^4.0.0"
143
143
  };
144
144
  var optionalDependencies = {
145
- "very-happy-tools-arm64-darwin": "0.2.111",
146
- "very-happy-tools-x64-darwin": "0.2.111",
147
- "very-happy-tools-arm64-linux": "0.2.111",
148
- "very-happy-tools-x64-linux": "0.2.111",
149
- "very-happy-tools-arm64-win32": "0.2.111",
150
- "very-happy-tools-x64-win32": "0.2.111"
145
+ "very-happy-tools-arm64-darwin": "0.2.113",
146
+ "very-happy-tools-x64-darwin": "0.2.113",
147
+ "very-happy-tools-arm64-linux": "0.2.113",
148
+ "very-happy-tools-x64-linux": "0.2.113",
149
+ "very-happy-tools-arm64-win32": "0.2.113",
150
+ "very-happy-tools-x64-win32": "0.2.113"
151
151
  };
152
152
  var devDependencies = {
153
153
  "@slopus/happy-wire": "workspace:*",
@@ -747,6 +747,14 @@ const sessionEnvelopeSchema = z.object({
747
747
  // Codex app-server item id for this envelope. Used as the precise
748
748
  // rollback point for Codex thread duplicate/fork-from-message.
749
749
  codexItemId: z.string().min(1).optional(),
750
+ // B-309: identity of the live draft this envelope supersedes,
751
+ // `"<api message id>:<content block index>"`. Set on text/thinking
752
+ // envelopes mapped from a Claude assistant message so the web can replace
753
+ // the streamed draft with the persisted message in a single frame instead
754
+ // of letting it flicker out and back in. Absent from every other producer
755
+ // (and from CLIs older than the streaming relay) — consumers must treat a
756
+ // missing key as "no draft to claim", never as an error.
757
+ streamKey: z.string().min(1).optional(),
750
758
  // Per-API-call token usage of the assistant message this envelope was
751
759
  // mapped from (B-108). Envelope-level (not inside `ev`) so every envelope
752
760
  // type carries it uniformly — the web feeds it into its context meter.
@@ -785,6 +793,7 @@ function createEnvelope(role, ev, opts = {}) {
785
793
  ...opts.subagent ? { subagent: opts.subagent } : {},
786
794
  ...opts.claudeUuid ? { claudeUuid: opts.claudeUuid } : {},
787
795
  ...opts.codexItemId ? { codexItemId: opts.codexItemId } : {},
796
+ ...opts.streamKey ? { streamKey: opts.streamKey } : {},
788
797
  ...opts.usage ? { usage: opts.usage } : {},
789
798
  ev
790
799
  });
@@ -887,6 +896,44 @@ z.object({
887
896
  body: CoreUpdateBodySchema,
888
897
  createdAt: z.number()
889
898
  });
899
+ const STREAM_DELTA_MAX_CHARS = 16 * 1024;
900
+ const sessionStreamBlockKindSchema = z.enum(["text", "thinking"]);
901
+ const sessionStreamBlockStartSchema = z.object({
902
+ t: z.literal("block-start"),
903
+ mid: z.string().min(1),
904
+ idx: z.number().int().min(0),
905
+ kind: sessionStreamBlockKindSchema
906
+ });
907
+ const sessionStreamBlockDeltaSchema = z.object({
908
+ t: z.literal("block-delta"),
909
+ mid: z.string().min(1),
910
+ idx: z.number().int().min(0),
911
+ text: z.string().max(STREAM_DELTA_MAX_CHARS)
912
+ });
913
+ const sessionStreamBlockEndSchema = z.object({
914
+ t: z.literal("block-end"),
915
+ mid: z.string().min(1),
916
+ idx: z.number().int().min(0)
917
+ });
918
+ const sessionStreamProgressSchema = z.object({
919
+ t: z.literal("progress"),
920
+ thinkingTokens: z.number().int().min(0).optional(),
921
+ outputTokens: z.number().int().min(0).optional(),
922
+ status: z.enum(["requesting", "compacting"]).optional()
923
+ });
924
+ const sessionStreamTurnEndSchema = z.object({
925
+ t: z.literal("turn-end")
926
+ });
927
+ z.discriminatedUnion("t", [
928
+ sessionStreamBlockStartSchema,
929
+ sessionStreamBlockDeltaSchema,
930
+ sessionStreamBlockEndSchema,
931
+ sessionStreamProgressSchema,
932
+ sessionStreamTurnEndSchema
933
+ ]);
934
+ function streamKeyOf(messageId, blockIndex) {
935
+ return `${messageId}:${blockIndex}`;
936
+ }
890
937
  const VoiceConversationGrantedSchema = z.object({
891
938
  allowed: z.literal(true),
892
939
  conversationToken: z.string(),
@@ -1368,6 +1415,23 @@ let backoff = createBackoff({
1368
1415
  }
1369
1416
  });
1370
1417
 
1418
+ function isRateQuotaCode(code) {
1419
+ return typeof code === "string" && code.endsWith("_rate_quota_exceeded");
1420
+ }
1421
+ const RATE_RETRY_MIN_DELAY_MS = 2e3;
1422
+ const RATE_RETRY_MAX_DELAY_MS = 6e4;
1423
+ function rateRetryDelayMs(attempt, random = Math.random()) {
1424
+ const exponent = Math.max(0, Math.min(attempt, 32) - 1);
1425
+ const ceiling = Math.min(RATE_RETRY_MIN_DELAY_MS * 2 ** exponent, RATE_RETRY_MAX_DELAY_MS);
1426
+ return Math.round(RATE_RETRY_MIN_DELAY_MS + random * (ceiling - RATE_RETRY_MIN_DELAY_MS));
1427
+ }
1428
+ async function pauseForRateQuota(opts) {
1429
+ const ms = rateRetryDelayMs(opts.attempt);
1430
+ opts.log?.(`[RATE] ${opts.label} write refused (${opts.code}), attempt ${opts.attempt} \u2014 waiting ${ms}ms`);
1431
+ await opts.sleep(ms);
1432
+ return ms;
1433
+ }
1434
+
1371
1435
  class AsyncLock {
1372
1436
  permits = 1;
1373
1437
  promiseResolverQueue = [];
@@ -2769,13 +2833,24 @@ function mapClaudeLogMessageToSessionEnvelopesInternal(message, state) {
2769
2833
  maybeEmitSubagentStart(state, turnId, subagent, envelopes);
2770
2834
  const usage = pickAssistantUsage(message);
2771
2835
  const blocks = Array.isArray(message.message?.content) ? message.message.content : [];
2772
- for (const block of blocks) {
2836
+ const apiMessageId = !isSidechainMessage(message) && typeof message.message?.id === "string" && message.message.id.length > 0 ? message.message.id : void 0;
2837
+ let blockCursor = 0;
2838
+ if (apiMessageId) {
2839
+ if (state.streamBlockMessageId !== apiMessageId) {
2840
+ state.streamBlockMessageId = apiMessageId;
2841
+ state.streamBlockCursor = 0;
2842
+ }
2843
+ blockCursor = state.streamBlockCursor ?? 0;
2844
+ state.streamBlockCursor = blockCursor + blocks.length;
2845
+ }
2846
+ const draftKey = (index) => apiMessageId ? streamKeyOf(apiMessageId, blockCursor + index) : void 0;
2847
+ for (const [blockIndex, block] of blocks.entries()) {
2773
2848
  if (block.type === "text" && typeof block.text === "string" && block.text.trim().length > 0) {
2774
- envelopes.push(createEnvelope("agent", { t: "text", text: block.text }, { turn: turnId, subagent, claudeUuid, usage }));
2849
+ envelopes.push(createEnvelope("agent", { t: "text", text: block.text }, { turn: turnId, subagent, claudeUuid, usage, streamKey: draftKey(blockIndex) }));
2775
2850
  continue;
2776
2851
  }
2777
2852
  if (block.type === "thinking" && typeof block.thinking === "string" && block.thinking.trim().length > 0) {
2778
- envelopes.push(createEnvelope("agent", { t: "text", text: block.thinking, thinking: true }, { turn: turnId, subagent, claudeUuid, usage }));
2853
+ envelopes.push(createEnvelope("agent", { t: "text", text: block.thinking, thinking: true }, { turn: turnId, subagent, claudeUuid, usage, streamKey: draftKey(blockIndex) }));
2779
2854
  continue;
2780
2855
  }
2781
2856
  if (block.type === "tool_use") {
@@ -3774,6 +3849,33 @@ class ApiSessionClient extends EventEmitter {
3774
3849
  mode
3775
3850
  });
3776
3851
  }
3852
+ /**
3853
+ * B-309: push one live stream frame (thinking/text delta or progress) to
3854
+ * this account's web clients.
3855
+ *
3856
+ * Encrypted with the SESSION key and relayed without being stored —
3857
+ * clipboard-push's shape, for clipboard-push's reasons: the relay must not
3858
+ * be able to read thinking text, and the session id is stamped by the
3859
+ * server from the authenticated connection rather than trusted from here.
3860
+ *
3861
+ * `volatile` on purpose. A draft that misses the wire while disconnected
3862
+ * is worth nothing — the persisted message is still coming, and replaying
3863
+ * stale deltas after a reconnect would paint text that has already landed.
3864
+ */
3865
+ sendStreamFrame(frame) {
3866
+ if (!this.socket.connected) return;
3867
+ try {
3868
+ this.socket.volatile.emit("session-stream", {
3869
+ // The frame object, NOT a JSON string: `encrypt` serializes
3870
+ // internally, so pre-stringifying would double-encode and
3871
+ // escape every quote in the streamed text.
3872
+ payload: encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, frame)),
3873
+ enc: true
3874
+ });
3875
+ } catch (error) {
3876
+ logger.debug(`[API] Failed to relay stream frame: ${error}`);
3877
+ }
3878
+ }
3777
3879
  /**
3778
3880
  * Send session death message
3779
3881
  */
@@ -3904,12 +4006,14 @@ class ApiSessionClient extends EventEmitter {
3904
4006
  }
3905
4007
  updateMetadata(handler) {
3906
4008
  this.metadataLock.inLock(async () => {
4009
+ let rateRefusals = 0;
3907
4010
  await backoff(async () => {
3908
4011
  let updated = handler(this.metadata);
3909
4012
  const answer = await this.socket.emitWithAck("update-metadata", { sid: this.sessionId, expectedVersion: this.metadataVersion, metadata: encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, updated)) });
3910
4013
  if (answer.result === "success") {
3911
4014
  this.metadata = decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(answer.metadata));
3912
4015
  this.metadataVersion = answer.version;
4016
+ rateRefusals = 0;
3913
4017
  } else if (answer.result === "version-mismatch") {
3914
4018
  if (answer.version > this.metadataVersion) {
3915
4019
  this.metadataVersion = answer.version;
@@ -3917,6 +4021,16 @@ class ApiSessionClient extends EventEmitter {
3917
4021
  }
3918
4022
  throw new Error("Metadata version mismatch");
3919
4023
  } else if (answer.result === "error") {
4024
+ if (isRateQuotaCode(answer.error)) {
4025
+ rateRefusals += 1;
4026
+ await pauseForRateQuota({
4027
+ label: "session metadata",
4028
+ code: answer.error,
4029
+ attempt: rateRefusals,
4030
+ sleep: delay,
4031
+ log: (message) => logger.debug(message)
4032
+ });
4033
+ }
3920
4034
  throw new Error("Metadata update failed");
3921
4035
  }
3922
4036
  });
@@ -3929,12 +4043,14 @@ class ApiSessionClient extends EventEmitter {
3929
4043
  updateAgentState(handler) {
3930
4044
  logger.debugLargeJson("Updating agent state", this.agentState);
3931
4045
  this.agentStateLock.inLock(async () => {
4046
+ let rateRefusals = 0;
3932
4047
  await backoff(async () => {
3933
4048
  let updated = handler(this.agentState || {});
3934
4049
  const answer = await this.socket.emitWithAck("update-state", { sid: this.sessionId, expectedVersion: this.agentStateVersion, agentState: updated ? encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, updated)) : null });
3935
4050
  if (answer.result === "success") {
3936
4051
  this.agentState = answer.agentState ? decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(answer.agentState)) : null;
3937
4052
  this.agentStateVersion = answer.version;
4053
+ rateRefusals = 0;
3938
4054
  logger.debug("Agent state updated", this.agentState);
3939
4055
  } else if (answer.result === "version-mismatch") {
3940
4056
  if (answer.version > this.agentStateVersion) {
@@ -3943,6 +4059,16 @@ class ApiSessionClient extends EventEmitter {
3943
4059
  }
3944
4060
  throw new Error("Agent state version mismatch");
3945
4061
  } else if (answer.result === "error") {
4062
+ if (isRateQuotaCode(answer.error)) {
4063
+ rateRefusals += 1;
4064
+ await pauseForRateQuota({
4065
+ label: "session agent state",
4066
+ code: answer.error,
4067
+ attempt: rateRefusals,
4068
+ sleep: delay,
4069
+ log: (message) => logger.debug(message)
4070
+ });
4071
+ }
3946
4072
  throw new Error("Agent state update failed");
3947
4073
  }
3948
4074
  });
@@ -14844,6 +14970,7 @@ class ApiMachineClient {
14844
14970
  * for example to set a custom name.
14845
14971
  */
14846
14972
  async updateMachineMetadata(handler) {
14973
+ let rateRefusals = 0;
14847
14974
  await backoff(async () => {
14848
14975
  const updated = handler(this.machine.metadata);
14849
14976
  const answer = await this.socket.emitWithAck("machine-update-metadata", {
@@ -14854,6 +14981,7 @@ class ApiMachineClient {
14854
14981
  if (answer.result === "success") {
14855
14982
  this.machine.metadata = decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, decodeBase64(answer.metadata));
14856
14983
  this.machine.metadataVersion = answer.version;
14984
+ rateRefusals = 0;
14857
14985
  logger.debug("[API MACHINE] Metadata updated successfully");
14858
14986
  } else if (answer.result === "version-mismatch") {
14859
14987
  if (answer.version > this.machine.metadataVersion) {
@@ -14861,6 +14989,18 @@ class ApiMachineClient {
14861
14989
  this.machine.metadata = decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, decodeBase64(answer.metadata));
14862
14990
  }
14863
14991
  throw new Error("Metadata version mismatch");
14992
+ } else if (answer.result === "error") {
14993
+ if (isRateQuotaCode(answer.error)) {
14994
+ rateRefusals += 1;
14995
+ await pauseForRateQuota({
14996
+ label: "machine metadata",
14997
+ code: answer.error,
14998
+ attempt: rateRefusals,
14999
+ sleep: delay,
15000
+ log: (message) => logger.debug(message)
15001
+ });
15002
+ }
15003
+ throw new Error("Machine metadata update failed");
14864
15004
  }
14865
15005
  });
14866
15006
  }
@@ -14869,6 +15009,7 @@ class ApiMachineClient {
14869
15009
  * Simplified without lock - relies on backoff for retry
14870
15010
  */
14871
15011
  async updateDaemonState(handler) {
15012
+ let rateRefusals = 0;
14872
15013
  await backoff(async () => {
14873
15014
  const updated = handler(this.machine.daemonState);
14874
15015
  const answer = await this.socket.emitWithAck("machine-update-state", {
@@ -14879,6 +15020,7 @@ class ApiMachineClient {
14879
15020
  if (answer.result === "success") {
14880
15021
  this.machine.daemonState = decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, decodeBase64(answer.daemonState));
14881
15022
  this.machine.daemonStateVersion = answer.version;
15023
+ rateRefusals = 0;
14882
15024
  logger.debug("[API MACHINE] Daemon state updated successfully");
14883
15025
  } else if (answer.result === "version-mismatch") {
14884
15026
  if (answer.version > this.machine.daemonStateVersion) {
@@ -14886,6 +15028,18 @@ class ApiMachineClient {
14886
15028
  this.machine.daemonState = decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, decodeBase64(answer.daemonState));
14887
15029
  }
14888
15030
  throw new Error("Daemon state version mismatch");
15031
+ } else if (answer.result === "error") {
15032
+ if (isRateQuotaCode(answer.error)) {
15033
+ rateRefusals += 1;
15034
+ await pauseForRateQuota({
15035
+ label: "daemon state",
15036
+ code: answer.error,
15037
+ attempt: rateRefusals,
15038
+ sleep: delay,
15039
+ log: (message) => logger.debug(message)
15040
+ });
15041
+ }
15042
+ throw new Error("Daemon state update failed");
14889
15043
  }
14890
15044
  });
14891
15045
  }
@@ -16302,4 +16456,4 @@ const RawJSONLinesSchema = z$1.discriminatedUnion("type", [
16302
16456
  }).passthrough()
16303
16457
  ]);
16304
16458
 
16305
- export { mirrorLocalId as $, ApiClient as A, credentialRelayProblem as B, deriveLocalCliUpdateSummary as C, updateSettings as D, encodeBase64Url as E, decodeBase64 as F, writeCredentialsLegacy as G, writeCredentialsDataKey as H, InvalidateSync as I, readCredentialsForConfiguredRelay as J, encrypt as K, isClaudeSessionId as L, MAX_CHAT_ATTACHMENT_SOURCE_BYTES as M, getLocalHappyAgentCredentialPath as N, readLocalHappyAgentCredentials as O, decryptWithDataKey as P, decryptLegacy as Q, RawJSONLinesSchema as R, extractCompleteLines as S, decideBackfill as T, parseTerminalHookPayload as U, tmuxArgs as V, scrubTmuxClientEnv as W, decideMirrorBinding as X, MIRROR_BACKFILL_LINES_DEFAULT as Y, persistSession as Z, mirrorLineKey as _, ApiSessionClient as a, detectResumeSupport as a0, detectCLIAvailability as a1, acquireDaemonLock as a2, summarizeSpawnSessionForLog as a3, deletePersistedSessions as a4, shellescape as a5, decrypt as a6, writeDaemonState as a7, writeSettings as a8, fetchCliUpdateState as a9, resolveCliUpdateCheckInterval as aa, DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS as ab, releaseDaemonLock as ac, listVhTerminals as ad, isValidTerminalId as ae, readVhTerminal as af, sendToVhTerminal as ag, TITLE_PROMPT_PREFIX as ah, BOARD_ANALYZER_PROMPT_PREFIX as ai, startOfflineReconnection as aj, clearCredentials as ak, clearMachineId as al, SandboxConfigSchema as am, CodexAppServerClient as an, getLatestDaemonLog as ao, persistence as ap, api as aq, createEnvelope as b, configuration as c, contentLogMetadata as d, errorLogMetadata as e, packageJson as f, delay as g, connectionState as h, isValidSessionId as i, readSettings as j, encodeBase64 as k, logger as l, ensurePrivateDirectorySync as m, hardenPrivateFileSync as n, readDaemonState as o, projectPath as p, clearDaemonState as q, readPersistedSessions as r, getProjectPath as s, initializeSandbox as t, wrapCommand as u, AsyncLock as v, writePrivateFileSync as w, ensurePrivateDirectory as x, hardenPrivateFile as y, readCredentials as z };
16459
+ export { mirrorLineKey as $, ApiClient as A, credentialRelayProblem as B, deriveLocalCliUpdateSummary as C, updateSettings as D, encodeBase64Url as E, decodeBase64 as F, writeCredentialsLegacy as G, writeCredentialsDataKey as H, InvalidateSync as I, readCredentialsForConfiguredRelay as J, encrypt as K, isClaudeSessionId as L, MAX_CHAT_ATTACHMENT_SOURCE_BYTES as M, getLocalHappyAgentCredentialPath as N, readLocalHappyAgentCredentials as O, decryptWithDataKey as P, decryptLegacy as Q, RawJSONLinesSchema as R, STREAM_DELTA_MAX_CHARS as S, extractCompleteLines as T, decideBackfill as U, parseTerminalHookPayload as V, tmuxArgs as W, scrubTmuxClientEnv as X, decideMirrorBinding as Y, MIRROR_BACKFILL_LINES_DEFAULT as Z, persistSession as _, ApiSessionClient as a, mirrorLocalId as a0, detectResumeSupport as a1, detectCLIAvailability as a2, acquireDaemonLock as a3, summarizeSpawnSessionForLog as a4, deletePersistedSessions as a5, shellescape as a6, decrypt as a7, writeDaemonState as a8, writeSettings as a9, fetchCliUpdateState as aa, resolveCliUpdateCheckInterval as ab, DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS as ac, releaseDaemonLock as ad, listVhTerminals as ae, isValidTerminalId as af, readVhTerminal as ag, sendToVhTerminal as ah, TITLE_PROMPT_PREFIX as ai, BOARD_ANALYZER_PROMPT_PREFIX as aj, startOfflineReconnection as ak, clearCredentials as al, clearMachineId as am, SandboxConfigSchema as an, CodexAppServerClient as ao, getLatestDaemonLog as ap, persistence as aq, api as ar, createEnvelope as b, configuration as c, contentLogMetadata as d, errorLogMetadata as e, packageJson as f, delay as g, connectionState as h, isValidSessionId as i, readSettings as j, encodeBase64 as k, logger as l, ensurePrivateDirectorySync as m, hardenPrivateFileSync as n, readDaemonState as o, projectPath as p, clearDaemonState as q, readPersistedSessions as r, getProjectPath as s, initializeSandbox as t, wrapCommand as u, AsyncLock as v, writePrivateFileSync as w, ensurePrivateDirectory as x, hardenPrivateFile as y, readCredentials as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "very-happy-cli",
3
- "version": "0.2.111",
3
+ "version": "0.2.113",
4
4
  "description": "Remote multi-agent workspace CLI with deep Claude integration, native terminal streaming, and self-hosting.",
5
5
  "author": "Kirill Dubovitskiy",
6
6
  "contributors": [
@@ -113,12 +113,12 @@
113
113
  "zod": "^4.0.0"
114
114
  },
115
115
  "optionalDependencies": {
116
- "very-happy-tools-arm64-darwin": "0.2.111",
117
- "very-happy-tools-x64-darwin": "0.2.111",
118
- "very-happy-tools-arm64-linux": "0.2.111",
119
- "very-happy-tools-x64-linux": "0.2.111",
120
- "very-happy-tools-arm64-win32": "0.2.111",
121
- "very-happy-tools-x64-win32": "0.2.111"
116
+ "very-happy-tools-arm64-darwin": "0.2.113",
117
+ "very-happy-tools-x64-darwin": "0.2.113",
118
+ "very-happy-tools-arm64-linux": "0.2.113",
119
+ "very-happy-tools-x64-linux": "0.2.113",
120
+ "very-happy-tools-arm64-win32": "0.2.113",
121
+ "very-happy-tools-x64-win32": "0.2.113"
122
122
  },
123
123
  "devDependencies": {
124
124
  "@slopus/happy-wire": "workspace:*",