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.
- package/dist/{AcpBackend-B_olk79F.cjs → AcpBackend-33KrZ5lq.cjs} +1 -1
- package/dist/{AcpBackend-CeXVb_s_.mjs → AcpBackend-Dldla8c8.mjs} +1 -1
- package/dist/{AcpSessionManager-vqdqfD1l.mjs → AcpSessionManager-BPSy8e5x.mjs} +1 -1
- package/dist/{AcpSessionManager-uXwWO2Tn.cjs → AcpSessionManager-DnodFLES.cjs} +1 -1
- package/dist/{config-vGkcq9nM.mjs → config-Bp2eRu4s.mjs} +2 -2
- package/dist/{config-BR3tkFL_.cjs → config-CzhVSd7F.cjs} +2 -2
- package/dist/{index-BOoGJGQc.cjs → index-Bhej85vt.cjs} +240 -19
- package/dist/{index-Bn-xsguz.mjs → index-C1KeV2ip.mjs} +236 -15
- package/dist/{index-C-RLk8-e.mjs → index-D7dc2QHa.mjs} +2 -2
- package/dist/{index-JAhGeW4_.mjs → index-DfAGG99Q.mjs} +5 -5
- package/dist/{index-CtBP0Qvc.cjs → index-H47khBtq.cjs} +4 -4
- package/dist/{index-SjthsMid.cjs → index-fjyucZBO.cjs} +2 -2
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{installTerminalHooks-FbKaK149.cjs → installTerminalHooks-CxBFNpwn.cjs} +2 -2
- package/dist/{installTerminalHooks-ADNcNdnB.mjs → installTerminalHooks-hnyO1Trp.mjs} +2 -2
- package/dist/lib.cjs +1 -1
- package/dist/lib.d.cts +44 -0
- package/dist/lib.d.mts +44 -0
- package/dist/lib.mjs +1 -1
- package/dist/{mcp-DHPm_gvL.mjs → mcp-BlAJfG7B.mjs} +2 -2
- package/dist/{mcp-DPp-bYNE.cjs → mcp-D1XCJ2xc.cjs} +2 -2
- package/dist/{runGemini-D5ySpYIZ.cjs → runGemini-BhLjxHGD.cjs} +4 -4
- package/dist/{runGemini-CWWyjQMz.mjs → runGemini-DVb3uHxe.mjs} +4 -4
- package/dist/{runOpenClaw-Bwrb1LXP.cjs → runOpenClaw-BrGj8DO6.cjs} +3 -3
- package/dist/{runOpenClaw-Bv4rUTyJ.mjs → runOpenClaw-D_GPGmD3.mjs} +3 -3
- package/dist/{send-DBfSNILO.cjs → send-B9lvSBVC.cjs} +2 -2
- package/dist/{send-BlkxFZu4.mjs → send-XfDlFCXz.mjs} +2 -2
- package/dist/{sessions-CVuEsdRl.cjs → sessions-BkeCXy8-.cjs} +2 -2
- package/dist/{sessions-1fW8soBM.mjs → sessions-DwSgYAEK.mjs} +2 -2
- package/dist/{spawn-D_ZexrY9.cjs → spawn-BNvGZjic.cjs} +2 -2
- package/dist/{spawn-BorKN3W2.mjs → spawn-CwORJ-bq.mjs} +2 -2
- package/dist/{types-BG_5QKX5.cjs → types-BnsRaANk.cjs} +166 -11
- package/dist/{types-k_ipDb0c.mjs → types-CAzzJ4tO.mjs} +165 -11
- package/package.json +7 -7
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
var mcp_js = require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
4
4
|
var stdio_js = require('@modelcontextprotocol/sdk/server/stdio.js');
|
|
5
5
|
var z = require('zod');
|
|
6
|
-
var index = require('./index-
|
|
6
|
+
var index = require('./index-Bhej85vt.cjs');
|
|
7
7
|
var limits = require('./limits-KdWKmwtH.cjs');
|
|
8
|
-
var persistence = require('./types-
|
|
8
|
+
var persistence = require('./types-BnsRaANk.cjs');
|
|
9
9
|
require('chalk');
|
|
10
10
|
require('node:os');
|
|
11
11
|
require('node:crypto');
|
|
@@ -4,10 +4,10 @@ var ink = require('ink');
|
|
|
4
4
|
var React = require('react');
|
|
5
5
|
var node_crypto = require('node:crypto');
|
|
6
6
|
var path = require('node:path');
|
|
7
|
-
var persistence = require('./types-
|
|
8
|
-
var index = require('./index-
|
|
9
|
-
var AcpBackend = require('./AcpBackend-
|
|
10
|
-
var config = require('./config-
|
|
7
|
+
var persistence = require('./types-BnsRaANk.cjs');
|
|
8
|
+
var index = require('./index-Bhej85vt.cjs');
|
|
9
|
+
var AcpBackend = require('./AcpBackend-33KrZ5lq.cjs');
|
|
10
|
+
var config = require('./config-CzhVSd7F.cjs');
|
|
11
11
|
require('axios');
|
|
12
12
|
require('chalk');
|
|
13
13
|
require('node:util');
|
|
@@ -2,10 +2,10 @@ import { useStdout, useInput, Box, Text, render } from 'ink';
|
|
|
2
2
|
import React, { useState, useRef, useEffect, useCallback } from 'react';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
|
-
import { l as logger, h as connectionState, A as ApiClient, j as readSettings, e as errorLogMetadata, k as encodeBase64, p as projectPath, d as contentLogMetadata } from './types-
|
|
6
|
-
import { x as GEMINI_API_KEY_ENV, y as GOOGLE_API_KEY_ENV, G as GEMINI_MODEL_ENV, B as BasePermissionHandler, z as BaseReasoningProcessor, h as initialMachineMetadata, j as createSessionMetadata, k as setupOfflineReconnection, n as notifyDaemonSessionStarted, m as MessageQueue2, o as hashObject, C as MessageBuffer, E as CHANGE_TITLE_INSTRUCTION, v as registerKillSessionHandler, u as startHappyServer } from './index-
|
|
7
|
-
import { A as AcpBackend } from './AcpBackend-
|
|
8
|
-
import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-
|
|
5
|
+
import { l as logger, h as connectionState, A as ApiClient, j as readSettings, e as errorLogMetadata, k as encodeBase64, p as projectPath, d as contentLogMetadata } from './types-CAzzJ4tO.mjs';
|
|
6
|
+
import { x as GEMINI_API_KEY_ENV, y as GOOGLE_API_KEY_ENV, G as GEMINI_MODEL_ENV, B as BasePermissionHandler, z as BaseReasoningProcessor, h as initialMachineMetadata, j as createSessionMetadata, k as setupOfflineReconnection, n as notifyDaemonSessionStarted, m as MessageQueue2, o as hashObject, C as MessageBuffer, E as CHANGE_TITLE_INSTRUCTION, v as registerKillSessionHandler, u as startHappyServer } from './index-C1KeV2ip.mjs';
|
|
7
|
+
import { A as AcpBackend } from './AcpBackend-Dldla8c8.mjs';
|
|
8
|
+
import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-Bp2eRu4s.mjs';
|
|
9
9
|
import 'axios';
|
|
10
10
|
import 'chalk';
|
|
11
11
|
import 'node:util';
|
|
@@ -5,9 +5,9 @@ var node_child_process = require('node:child_process');
|
|
|
5
5
|
var os = require('node:os');
|
|
6
6
|
var node_fs = require('node:fs');
|
|
7
7
|
var path = require('node:path');
|
|
8
|
-
var persistence = require('./types-
|
|
9
|
-
var AcpSessionManager = require('./AcpSessionManager-
|
|
10
|
-
var index = require('./index-
|
|
8
|
+
var persistence = require('./types-BnsRaANk.cjs');
|
|
9
|
+
var AcpSessionManager = require('./AcpSessionManager-DnodFLES.cjs');
|
|
10
|
+
var index = require('./index-Bhej85vt.cjs');
|
|
11
11
|
var WebSocket = require('ws');
|
|
12
12
|
var ed = require('@noble/ed25519');
|
|
13
13
|
var sha2_js = require('@noble/hashes/sha2.js');
|
|
@@ -3,9 +3,9 @@ import { execFileSync } from 'node:child_process';
|
|
|
3
3
|
import os from 'node:os';
|
|
4
4
|
import { existsSync, readFileSync } from 'node:fs';
|
|
5
5
|
import { join } from 'node:path';
|
|
6
|
-
import { m as ensurePrivateDirectorySync, n as hardenPrivateFileSync, w as writePrivateFileSync, e as errorLogMetadata, d as contentLogMetadata, h as connectionState, A as ApiClient, j as readSettings, k as encodeBase64, l as logger, c as configuration } from './types-
|
|
7
|
-
import { A as AcpSessionManager } from './AcpSessionManager-
|
|
8
|
-
import { h as initialMachineMetadata, j as createSessionMetadata, k as setupOfflineReconnection, n as notifyDaemonSessionStarted, m as MessageQueue2, v as registerKillSessionHandler } from './index-
|
|
6
|
+
import { m as ensurePrivateDirectorySync, n as hardenPrivateFileSync, w as writePrivateFileSync, e as errorLogMetadata, d as contentLogMetadata, h as connectionState, A as ApiClient, j as readSettings, k as encodeBase64, l as logger, c as configuration } from './types-CAzzJ4tO.mjs';
|
|
7
|
+
import { A as AcpSessionManager } from './AcpSessionManager-BPSy8e5x.mjs';
|
|
8
|
+
import { h as initialMachineMetadata, j as createSessionMetadata, k as setupOfflineReconnection, n as notifyDaemonSessionStarted, m as MessageQueue2, v as registerKillSessionHandler } from './index-C1KeV2ip.mjs';
|
|
9
9
|
import WebSocket from 'ws';
|
|
10
10
|
import * as ed from '@noble/ed25519';
|
|
11
11
|
import { sha512 } from '@noble/hashes/sha2.js';
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
var chalk = require('chalk');
|
|
4
4
|
var node_fs = require('node:fs');
|
|
5
5
|
var path = require('node:path');
|
|
6
|
-
var persistence = require('./types-
|
|
7
|
-
var index = require('./index-
|
|
6
|
+
var persistence = require('./types-BnsRaANk.cjs');
|
|
7
|
+
var index = require('./index-Bhej85vt.cjs');
|
|
8
8
|
require('axios');
|
|
9
9
|
require('node:util');
|
|
10
10
|
require('node:os');
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { readFileSync } from 'node:fs';
|
|
3
3
|
import { resolve } from 'node:path';
|
|
4
|
-
import { r as readPersistedSessions, c as configuration } from './types-
|
|
5
|
-
import { d as sendUserMessage, a as sessionWebUrl } from './index-
|
|
4
|
+
import { r as readPersistedSessions, c as configuration } from './types-CAzzJ4tO.mjs';
|
|
5
|
+
import { d as sendUserMessage, a as sessionWebUrl } from './index-C1KeV2ip.mjs';
|
|
6
6
|
import 'axios';
|
|
7
7
|
import 'node:util';
|
|
8
8
|
import 'node:os';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chalk = require('chalk');
|
|
4
|
-
var index = require('./index-
|
|
5
|
-
var persistence = require('./types-
|
|
4
|
+
var index = require('./index-Bhej85vt.cjs');
|
|
5
|
+
var persistence = require('./types-BnsRaANk.cjs');
|
|
6
6
|
require('node:os');
|
|
7
7
|
require('node:crypto');
|
|
8
8
|
require('cross-spawn');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import { D as DEFAULT_RECENT_LIMIT, M as MAX_READ_LIMIT, l as listSessions, r as readSessionTranscript, e as stopSession, f as archiveSession } from './index-
|
|
3
|
-
import { i as isValidSessionId } from './types-
|
|
2
|
+
import { D as DEFAULT_RECENT_LIMIT, M as MAX_READ_LIMIT, l as listSessions, r as readSessionTranscript, e as stopSession, f as archiveSession } from './index-C1KeV2ip.mjs';
|
|
3
|
+
import { i as isValidSessionId } from './types-CAzzJ4tO.mjs';
|
|
4
4
|
import 'node:os';
|
|
5
5
|
import 'node:crypto';
|
|
6
6
|
import 'cross-spawn';
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
var chalk = require('chalk');
|
|
4
4
|
var node_fs = require('node:fs');
|
|
5
5
|
var path = require('node:path');
|
|
6
|
-
var index = require('./index-
|
|
7
|
-
var persistence = require('./types-
|
|
6
|
+
var index = require('./index-Bhej85vt.cjs');
|
|
7
|
+
var persistence = require('./types-BnsRaANk.cjs');
|
|
8
8
|
require('node:os');
|
|
9
9
|
require('node:crypto');
|
|
10
10
|
require('cross-spawn');
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { readFileSync, statSync } from 'node:fs';
|
|
3
3
|
import { resolve } from 'node:path';
|
|
4
|
-
import { c as checkIfDaemonRunningAndCleanupStaleState, s as spawnDaemonSession, a as sessionWebUrl, i as isValidSpawnOrigin, b as sanitizeSpawnPermissionMode, A as ALLOWED_SPAWN_PERMISSION_MODES, w as waitForSessionKey, d as sendUserMessage } from './index-
|
|
5
|
-
import { l as logger } from './types-
|
|
4
|
+
import { c as checkIfDaemonRunningAndCleanupStaleState, s as spawnDaemonSession, a as sessionWebUrl, i as isValidSpawnOrigin, b as sanitizeSpawnPermissionMode, A as ALLOWED_SPAWN_PERMISSION_MODES, w as waitForSessionKey, d as sendUserMessage } from './index-C1KeV2ip.mjs';
|
|
5
|
+
import { l as logger } from './types-CAzzJ4tO.mjs';
|
|
6
6
|
import 'node:os';
|
|
7
7
|
import 'node:crypto';
|
|
8
8
|
import 'cross-spawn';
|
|
@@ -51,7 +51,7 @@ var z__namespace = /*#__PURE__*/_interopNamespaceDefault(z);
|
|
|
51
51
|
var pty__namespace = /*#__PURE__*/_interopNamespaceDefault(pty);
|
|
52
52
|
|
|
53
53
|
var name = "very-happy-cli";
|
|
54
|
-
var version = "0.2.
|
|
54
|
+
var version = "0.2.113";
|
|
55
55
|
var description = "Remote multi-agent workspace CLI with deep Claude integration, native terminal streaming, and self-hosting.";
|
|
56
56
|
var author = "Kirill Dubovitskiy";
|
|
57
57
|
var contributors = [
|
|
@@ -164,12 +164,12 @@ var dependencies = {
|
|
|
164
164
|
zod: "^4.0.0"
|
|
165
165
|
};
|
|
166
166
|
var optionalDependencies = {
|
|
167
|
-
"very-happy-tools-arm64-darwin": "0.2.
|
|
168
|
-
"very-happy-tools-x64-darwin": "0.2.
|
|
169
|
-
"very-happy-tools-arm64-linux": "0.2.
|
|
170
|
-
"very-happy-tools-x64-linux": "0.2.
|
|
171
|
-
"very-happy-tools-arm64-win32": "0.2.
|
|
172
|
-
"very-happy-tools-x64-win32": "0.2.
|
|
167
|
+
"very-happy-tools-arm64-darwin": "0.2.113",
|
|
168
|
+
"very-happy-tools-x64-darwin": "0.2.113",
|
|
169
|
+
"very-happy-tools-arm64-linux": "0.2.113",
|
|
170
|
+
"very-happy-tools-x64-linux": "0.2.113",
|
|
171
|
+
"very-happy-tools-arm64-win32": "0.2.113",
|
|
172
|
+
"very-happy-tools-x64-win32": "0.2.113"
|
|
173
173
|
};
|
|
174
174
|
var devDependencies = {
|
|
175
175
|
"@slopus/happy-wire": "workspace:*",
|
|
@@ -769,6 +769,14 @@ const sessionEnvelopeSchema = z__namespace.object({
|
|
|
769
769
|
// Codex app-server item id for this envelope. Used as the precise
|
|
770
770
|
// rollback point for Codex thread duplicate/fork-from-message.
|
|
771
771
|
codexItemId: z__namespace.string().min(1).optional(),
|
|
772
|
+
// B-309: identity of the live draft this envelope supersedes,
|
|
773
|
+
// `"<api message id>:<content block index>"`. Set on text/thinking
|
|
774
|
+
// envelopes mapped from a Claude assistant message so the web can replace
|
|
775
|
+
// the streamed draft with the persisted message in a single frame instead
|
|
776
|
+
// of letting it flicker out and back in. Absent from every other producer
|
|
777
|
+
// (and from CLIs older than the streaming relay) — consumers must treat a
|
|
778
|
+
// missing key as "no draft to claim", never as an error.
|
|
779
|
+
streamKey: z__namespace.string().min(1).optional(),
|
|
772
780
|
// Per-API-call token usage of the assistant message this envelope was
|
|
773
781
|
// mapped from (B-108). Envelope-level (not inside `ev`) so every envelope
|
|
774
782
|
// type carries it uniformly — the web feeds it into its context meter.
|
|
@@ -807,6 +815,7 @@ function createEnvelope(role, ev, opts = {}) {
|
|
|
807
815
|
...opts.subagent ? { subagent: opts.subagent } : {},
|
|
808
816
|
...opts.claudeUuid ? { claudeUuid: opts.claudeUuid } : {},
|
|
809
817
|
...opts.codexItemId ? { codexItemId: opts.codexItemId } : {},
|
|
818
|
+
...opts.streamKey ? { streamKey: opts.streamKey } : {},
|
|
810
819
|
...opts.usage ? { usage: opts.usage } : {},
|
|
811
820
|
ev
|
|
812
821
|
});
|
|
@@ -909,6 +918,44 @@ z__namespace.object({
|
|
|
909
918
|
body: CoreUpdateBodySchema,
|
|
910
919
|
createdAt: z__namespace.number()
|
|
911
920
|
});
|
|
921
|
+
const STREAM_DELTA_MAX_CHARS = 16 * 1024;
|
|
922
|
+
const sessionStreamBlockKindSchema = z__namespace.enum(["text", "thinking"]);
|
|
923
|
+
const sessionStreamBlockStartSchema = z__namespace.object({
|
|
924
|
+
t: z__namespace.literal("block-start"),
|
|
925
|
+
mid: z__namespace.string().min(1),
|
|
926
|
+
idx: z__namespace.number().int().min(0),
|
|
927
|
+
kind: sessionStreamBlockKindSchema
|
|
928
|
+
});
|
|
929
|
+
const sessionStreamBlockDeltaSchema = z__namespace.object({
|
|
930
|
+
t: z__namespace.literal("block-delta"),
|
|
931
|
+
mid: z__namespace.string().min(1),
|
|
932
|
+
idx: z__namespace.number().int().min(0),
|
|
933
|
+
text: z__namespace.string().max(STREAM_DELTA_MAX_CHARS)
|
|
934
|
+
});
|
|
935
|
+
const sessionStreamBlockEndSchema = z__namespace.object({
|
|
936
|
+
t: z__namespace.literal("block-end"),
|
|
937
|
+
mid: z__namespace.string().min(1),
|
|
938
|
+
idx: z__namespace.number().int().min(0)
|
|
939
|
+
});
|
|
940
|
+
const sessionStreamProgressSchema = z__namespace.object({
|
|
941
|
+
t: z__namespace.literal("progress"),
|
|
942
|
+
thinkingTokens: z__namespace.number().int().min(0).optional(),
|
|
943
|
+
outputTokens: z__namespace.number().int().min(0).optional(),
|
|
944
|
+
status: z__namespace.enum(["requesting", "compacting"]).optional()
|
|
945
|
+
});
|
|
946
|
+
const sessionStreamTurnEndSchema = z__namespace.object({
|
|
947
|
+
t: z__namespace.literal("turn-end")
|
|
948
|
+
});
|
|
949
|
+
z__namespace.discriminatedUnion("t", [
|
|
950
|
+
sessionStreamBlockStartSchema,
|
|
951
|
+
sessionStreamBlockDeltaSchema,
|
|
952
|
+
sessionStreamBlockEndSchema,
|
|
953
|
+
sessionStreamProgressSchema,
|
|
954
|
+
sessionStreamTurnEndSchema
|
|
955
|
+
]);
|
|
956
|
+
function streamKeyOf(messageId, blockIndex) {
|
|
957
|
+
return `${messageId}:${blockIndex}`;
|
|
958
|
+
}
|
|
912
959
|
const VoiceConversationGrantedSchema = z__namespace.object({
|
|
913
960
|
allowed: z__namespace.literal(true),
|
|
914
961
|
conversationToken: z__namespace.string(),
|
|
@@ -1390,6 +1437,23 @@ let backoff = createBackoff({
|
|
|
1390
1437
|
}
|
|
1391
1438
|
});
|
|
1392
1439
|
|
|
1440
|
+
function isRateQuotaCode(code) {
|
|
1441
|
+
return typeof code === "string" && code.endsWith("_rate_quota_exceeded");
|
|
1442
|
+
}
|
|
1443
|
+
const RATE_RETRY_MIN_DELAY_MS = 2e3;
|
|
1444
|
+
const RATE_RETRY_MAX_DELAY_MS = 6e4;
|
|
1445
|
+
function rateRetryDelayMs(attempt, random = Math.random()) {
|
|
1446
|
+
const exponent = Math.max(0, Math.min(attempt, 32) - 1);
|
|
1447
|
+
const ceiling = Math.min(RATE_RETRY_MIN_DELAY_MS * 2 ** exponent, RATE_RETRY_MAX_DELAY_MS);
|
|
1448
|
+
return Math.round(RATE_RETRY_MIN_DELAY_MS + random * (ceiling - RATE_RETRY_MIN_DELAY_MS));
|
|
1449
|
+
}
|
|
1450
|
+
async function pauseForRateQuota(opts) {
|
|
1451
|
+
const ms = rateRetryDelayMs(opts.attempt);
|
|
1452
|
+
opts.log?.(`[RATE] ${opts.label} write refused (${opts.code}), attempt ${opts.attempt} \u2014 waiting ${ms}ms`);
|
|
1453
|
+
await opts.sleep(ms);
|
|
1454
|
+
return ms;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1393
1457
|
class AsyncLock {
|
|
1394
1458
|
permits = 1;
|
|
1395
1459
|
promiseResolverQueue = [];
|
|
@@ -1603,7 +1667,7 @@ class RpcHandlerManager {
|
|
|
1603
1667
|
}
|
|
1604
1668
|
}
|
|
1605
1669
|
|
|
1606
|
-
const __dirname$1 = path$1.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-
|
|
1670
|
+
const __dirname$1 = path$1.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-BnsRaANk.cjs', document.baseURI).href))));
|
|
1607
1671
|
function projectPath() {
|
|
1608
1672
|
const path = path$1.resolve(__dirname$1, "..");
|
|
1609
1673
|
return path;
|
|
@@ -2791,13 +2855,24 @@ function mapClaudeLogMessageToSessionEnvelopesInternal(message, state) {
|
|
|
2791
2855
|
maybeEmitSubagentStart(state, turnId, subagent, envelopes);
|
|
2792
2856
|
const usage = pickAssistantUsage(message);
|
|
2793
2857
|
const blocks = Array.isArray(message.message?.content) ? message.message.content : [];
|
|
2794
|
-
|
|
2858
|
+
const apiMessageId = !isSidechainMessage(message) && typeof message.message?.id === "string" && message.message.id.length > 0 ? message.message.id : void 0;
|
|
2859
|
+
let blockCursor = 0;
|
|
2860
|
+
if (apiMessageId) {
|
|
2861
|
+
if (state.streamBlockMessageId !== apiMessageId) {
|
|
2862
|
+
state.streamBlockMessageId = apiMessageId;
|
|
2863
|
+
state.streamBlockCursor = 0;
|
|
2864
|
+
}
|
|
2865
|
+
blockCursor = state.streamBlockCursor ?? 0;
|
|
2866
|
+
state.streamBlockCursor = blockCursor + blocks.length;
|
|
2867
|
+
}
|
|
2868
|
+
const draftKey = (index) => apiMessageId ? streamKeyOf(apiMessageId, blockCursor + index) : void 0;
|
|
2869
|
+
for (const [blockIndex, block] of blocks.entries()) {
|
|
2795
2870
|
if (block.type === "text" && typeof block.text === "string" && block.text.trim().length > 0) {
|
|
2796
|
-
envelopes.push(createEnvelope("agent", { t: "text", text: block.text }, { turn: turnId, subagent, claudeUuid, usage }));
|
|
2871
|
+
envelopes.push(createEnvelope("agent", { t: "text", text: block.text }, { turn: turnId, subagent, claudeUuid, usage, streamKey: draftKey(blockIndex) }));
|
|
2797
2872
|
continue;
|
|
2798
2873
|
}
|
|
2799
2874
|
if (block.type === "thinking" && typeof block.thinking === "string" && block.thinking.trim().length > 0) {
|
|
2800
|
-
envelopes.push(createEnvelope("agent", { t: "text", text: block.thinking, thinking: true }, { turn: turnId, subagent, claudeUuid, usage }));
|
|
2875
|
+
envelopes.push(createEnvelope("agent", { t: "text", text: block.thinking, thinking: true }, { turn: turnId, subagent, claudeUuid, usage, streamKey: draftKey(blockIndex) }));
|
|
2801
2876
|
continue;
|
|
2802
2877
|
}
|
|
2803
2878
|
if (block.type === "tool_use") {
|
|
@@ -3796,6 +3871,33 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
3796
3871
|
mode
|
|
3797
3872
|
});
|
|
3798
3873
|
}
|
|
3874
|
+
/**
|
|
3875
|
+
* B-309: push one live stream frame (thinking/text delta or progress) to
|
|
3876
|
+
* this account's web clients.
|
|
3877
|
+
*
|
|
3878
|
+
* Encrypted with the SESSION key and relayed without being stored —
|
|
3879
|
+
* clipboard-push's shape, for clipboard-push's reasons: the relay must not
|
|
3880
|
+
* be able to read thinking text, and the session id is stamped by the
|
|
3881
|
+
* server from the authenticated connection rather than trusted from here.
|
|
3882
|
+
*
|
|
3883
|
+
* `volatile` on purpose. A draft that misses the wire while disconnected
|
|
3884
|
+
* is worth nothing — the persisted message is still coming, and replaying
|
|
3885
|
+
* stale deltas after a reconnect would paint text that has already landed.
|
|
3886
|
+
*/
|
|
3887
|
+
sendStreamFrame(frame) {
|
|
3888
|
+
if (!this.socket.connected) return;
|
|
3889
|
+
try {
|
|
3890
|
+
this.socket.volatile.emit("session-stream", {
|
|
3891
|
+
// The frame object, NOT a JSON string: `encrypt` serializes
|
|
3892
|
+
// internally, so pre-stringifying would double-encode and
|
|
3893
|
+
// escape every quote in the streamed text.
|
|
3894
|
+
payload: encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, frame)),
|
|
3895
|
+
enc: true
|
|
3896
|
+
});
|
|
3897
|
+
} catch (error) {
|
|
3898
|
+
logger.debug(`[API] Failed to relay stream frame: ${error}`);
|
|
3899
|
+
}
|
|
3900
|
+
}
|
|
3799
3901
|
/**
|
|
3800
3902
|
* Send session death message
|
|
3801
3903
|
*/
|
|
@@ -3926,12 +4028,14 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
3926
4028
|
}
|
|
3927
4029
|
updateMetadata(handler) {
|
|
3928
4030
|
this.metadataLock.inLock(async () => {
|
|
4031
|
+
let rateRefusals = 0;
|
|
3929
4032
|
await backoff(async () => {
|
|
3930
4033
|
let updated = handler(this.metadata);
|
|
3931
4034
|
const answer = await this.socket.emitWithAck("update-metadata", { sid: this.sessionId, expectedVersion: this.metadataVersion, metadata: encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, updated)) });
|
|
3932
4035
|
if (answer.result === "success") {
|
|
3933
4036
|
this.metadata = decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(answer.metadata));
|
|
3934
4037
|
this.metadataVersion = answer.version;
|
|
4038
|
+
rateRefusals = 0;
|
|
3935
4039
|
} else if (answer.result === "version-mismatch") {
|
|
3936
4040
|
if (answer.version > this.metadataVersion) {
|
|
3937
4041
|
this.metadataVersion = answer.version;
|
|
@@ -3939,6 +4043,16 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
3939
4043
|
}
|
|
3940
4044
|
throw new Error("Metadata version mismatch");
|
|
3941
4045
|
} else if (answer.result === "error") {
|
|
4046
|
+
if (isRateQuotaCode(answer.error)) {
|
|
4047
|
+
rateRefusals += 1;
|
|
4048
|
+
await pauseForRateQuota({
|
|
4049
|
+
label: "session metadata",
|
|
4050
|
+
code: answer.error,
|
|
4051
|
+
attempt: rateRefusals,
|
|
4052
|
+
sleep: delay,
|
|
4053
|
+
log: (message) => logger.debug(message)
|
|
4054
|
+
});
|
|
4055
|
+
}
|
|
3942
4056
|
throw new Error("Metadata update failed");
|
|
3943
4057
|
}
|
|
3944
4058
|
});
|
|
@@ -3951,12 +4065,14 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
3951
4065
|
updateAgentState(handler) {
|
|
3952
4066
|
logger.debugLargeJson("Updating agent state", this.agentState);
|
|
3953
4067
|
this.agentStateLock.inLock(async () => {
|
|
4068
|
+
let rateRefusals = 0;
|
|
3954
4069
|
await backoff(async () => {
|
|
3955
4070
|
let updated = handler(this.agentState || {});
|
|
3956
4071
|
const answer = await this.socket.emitWithAck("update-state", { sid: this.sessionId, expectedVersion: this.agentStateVersion, agentState: updated ? encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, updated)) : null });
|
|
3957
4072
|
if (answer.result === "success") {
|
|
3958
4073
|
this.agentState = answer.agentState ? decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(answer.agentState)) : null;
|
|
3959
4074
|
this.agentStateVersion = answer.version;
|
|
4075
|
+
rateRefusals = 0;
|
|
3960
4076
|
logger.debug("Agent state updated", this.agentState);
|
|
3961
4077
|
} else if (answer.result === "version-mismatch") {
|
|
3962
4078
|
if (answer.version > this.agentStateVersion) {
|
|
@@ -3965,6 +4081,16 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
3965
4081
|
}
|
|
3966
4082
|
throw new Error("Agent state version mismatch");
|
|
3967
4083
|
} else if (answer.result === "error") {
|
|
4084
|
+
if (isRateQuotaCode(answer.error)) {
|
|
4085
|
+
rateRefusals += 1;
|
|
4086
|
+
await pauseForRateQuota({
|
|
4087
|
+
label: "session agent state",
|
|
4088
|
+
code: answer.error,
|
|
4089
|
+
attempt: rateRefusals,
|
|
4090
|
+
sleep: delay,
|
|
4091
|
+
log: (message) => logger.debug(message)
|
|
4092
|
+
});
|
|
4093
|
+
}
|
|
3968
4094
|
throw new Error("Agent state update failed");
|
|
3969
4095
|
}
|
|
3970
4096
|
});
|
|
@@ -14866,6 +14992,7 @@ class ApiMachineClient {
|
|
|
14866
14992
|
* for example to set a custom name.
|
|
14867
14993
|
*/
|
|
14868
14994
|
async updateMachineMetadata(handler) {
|
|
14995
|
+
let rateRefusals = 0;
|
|
14869
14996
|
await backoff(async () => {
|
|
14870
14997
|
const updated = handler(this.machine.metadata);
|
|
14871
14998
|
const answer = await this.socket.emitWithAck("machine-update-metadata", {
|
|
@@ -14876,6 +15003,7 @@ class ApiMachineClient {
|
|
|
14876
15003
|
if (answer.result === "success") {
|
|
14877
15004
|
this.machine.metadata = decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, decodeBase64(answer.metadata));
|
|
14878
15005
|
this.machine.metadataVersion = answer.version;
|
|
15006
|
+
rateRefusals = 0;
|
|
14879
15007
|
logger.debug("[API MACHINE] Metadata updated successfully");
|
|
14880
15008
|
} else if (answer.result === "version-mismatch") {
|
|
14881
15009
|
if (answer.version > this.machine.metadataVersion) {
|
|
@@ -14883,6 +15011,18 @@ class ApiMachineClient {
|
|
|
14883
15011
|
this.machine.metadata = decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, decodeBase64(answer.metadata));
|
|
14884
15012
|
}
|
|
14885
15013
|
throw new Error("Metadata version mismatch");
|
|
15014
|
+
} else if (answer.result === "error") {
|
|
15015
|
+
if (isRateQuotaCode(answer.error)) {
|
|
15016
|
+
rateRefusals += 1;
|
|
15017
|
+
await pauseForRateQuota({
|
|
15018
|
+
label: "machine metadata",
|
|
15019
|
+
code: answer.error,
|
|
15020
|
+
attempt: rateRefusals,
|
|
15021
|
+
sleep: delay,
|
|
15022
|
+
log: (message) => logger.debug(message)
|
|
15023
|
+
});
|
|
15024
|
+
}
|
|
15025
|
+
throw new Error("Machine metadata update failed");
|
|
14886
15026
|
}
|
|
14887
15027
|
});
|
|
14888
15028
|
}
|
|
@@ -14891,6 +15031,7 @@ class ApiMachineClient {
|
|
|
14891
15031
|
* Simplified without lock - relies on backoff for retry
|
|
14892
15032
|
*/
|
|
14893
15033
|
async updateDaemonState(handler) {
|
|
15034
|
+
let rateRefusals = 0;
|
|
14894
15035
|
await backoff(async () => {
|
|
14895
15036
|
const updated = handler(this.machine.daemonState);
|
|
14896
15037
|
const answer = await this.socket.emitWithAck("machine-update-state", {
|
|
@@ -14901,6 +15042,7 @@ class ApiMachineClient {
|
|
|
14901
15042
|
if (answer.result === "success") {
|
|
14902
15043
|
this.machine.daemonState = decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, decodeBase64(answer.daemonState));
|
|
14903
15044
|
this.machine.daemonStateVersion = answer.version;
|
|
15045
|
+
rateRefusals = 0;
|
|
14904
15046
|
logger.debug("[API MACHINE] Daemon state updated successfully");
|
|
14905
15047
|
} else if (answer.result === "version-mismatch") {
|
|
14906
15048
|
if (answer.version > this.machine.daemonStateVersion) {
|
|
@@ -14908,6 +15050,18 @@ class ApiMachineClient {
|
|
|
14908
15050
|
this.machine.daemonState = decrypt(this.machine.encryptionKey, this.machine.encryptionVariant, decodeBase64(answer.daemonState));
|
|
14909
15051
|
}
|
|
14910
15052
|
throw new Error("Daemon state version mismatch");
|
|
15053
|
+
} else if (answer.result === "error") {
|
|
15054
|
+
if (isRateQuotaCode(answer.error)) {
|
|
15055
|
+
rateRefusals += 1;
|
|
15056
|
+
await pauseForRateQuota({
|
|
15057
|
+
label: "daemon state",
|
|
15058
|
+
code: answer.error,
|
|
15059
|
+
attempt: rateRefusals,
|
|
15060
|
+
sleep: delay,
|
|
15061
|
+
log: (message) => logger.debug(message)
|
|
15062
|
+
});
|
|
15063
|
+
}
|
|
15064
|
+
throw new Error("Daemon state update failed");
|
|
14911
15065
|
}
|
|
14912
15066
|
});
|
|
14913
15067
|
}
|
|
@@ -16334,6 +16488,7 @@ exports.InvalidateSync = InvalidateSync;
|
|
|
16334
16488
|
exports.MAX_CHAT_ATTACHMENT_SOURCE_BYTES = MAX_CHAT_ATTACHMENT_SOURCE_BYTES;
|
|
16335
16489
|
exports.MIRROR_BACKFILL_LINES_DEFAULT = MIRROR_BACKFILL_LINES_DEFAULT;
|
|
16336
16490
|
exports.RawJSONLinesSchema = RawJSONLinesSchema;
|
|
16491
|
+
exports.STREAM_DELTA_MAX_CHARS = STREAM_DELTA_MAX_CHARS;
|
|
16337
16492
|
exports.SandboxConfigSchema = SandboxConfigSchema;
|
|
16338
16493
|
exports.TITLE_PROMPT_PREFIX = TITLE_PROMPT_PREFIX;
|
|
16339
16494
|
exports.acquireDaemonLock = acquireDaemonLock;
|