@adhdev/daemon-core 0.7.41 → 0.7.42
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/cli-adapters/provider-cli-adapter.d.ts +1 -0
- package/dist/commands/cli-manager.d.ts +4 -2
- package/dist/config/config.d.ts +2 -22
- package/dist/index.js +314 -88
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +314 -88
- package/dist/index.mjs.map +1 -1
- package/dist/providers/cli-provider-instance.d.ts +4 -10
- package/dist/providers/contracts.d.ts +0 -79
- package/dist/providers/extension-provider-instance.d.ts +1 -0
- package/dist/providers/provider-instance.d.ts +0 -2
- package/dist/shared-types.d.ts +1 -3
- package/dist/status/normalize.js +67 -1
- package/dist/status/normalize.js.map +1 -1
- package/dist/status/normalize.mjs +67 -1
- package/dist/status/normalize.mjs.map +1 -1
- package/dist/status/reporter.d.ts +1 -0
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/agent-stream/forward.ts +21 -1
- package/src/agent-stream/poller.ts +6 -1
- package/src/cli-adapters/provider-cli-adapter.ts +37 -2
- package/src/commands/cli-manager.ts +44 -39
- package/src/commands/router.ts +1 -0
- package/src/commands/stream-commands.ts +14 -0
- package/src/config/config.d.ts +5 -50
- package/src/config/config.ts +71 -49
- package/src/config/workspaces.d.ts +1 -4
- package/src/providers/cli-provider-instance.ts +18 -32
- package/src/providers/contracts.ts +0 -81
- package/src/providers/extension-provider-instance.ts +27 -0
- package/src/providers/ide-provider-instance.ts +12 -0
- package/src/providers/provider-instance.ts +0 -2
- package/src/shared-types.ts +1 -3
- package/src/status/builders.ts +7 -2
- package/src/status/normalize.ts +85 -0
- package/src/status/reporter.ts +31 -2
|
@@ -26,19 +26,13 @@ export declare class CliProviderInstance implements ProviderInstance {
|
|
|
26
26
|
private lastApprovalEventAt;
|
|
27
27
|
private historyWriter;
|
|
28
28
|
readonly instanceId: string;
|
|
29
|
-
private
|
|
30
|
-
|
|
31
|
-
constructor(provider: ProviderModule, workingDir: string, cliArgs?: string[], instanceId?: string, transportFactory?: PtyTransportFactory, launchModeId?: string);
|
|
32
|
-
/**
|
|
33
|
-
* Determine output rendering format from:
|
|
34
|
-
* 1. launchMode.outputFormat (explicit override)
|
|
35
|
-
* 2. launchOptions[].outputFormatMap — check actual args for matching values
|
|
36
|
-
* 3. Default: 'terminal'
|
|
37
|
-
*/
|
|
38
|
-
private resolveOutputFormat;
|
|
29
|
+
private presentationMode;
|
|
30
|
+
constructor(provider: ProviderModule, workingDir: string, cliArgs?: string[], instanceId?: string, transportFactory?: PtyTransportFactory);
|
|
39
31
|
init(context: InstanceContext): Promise<void>;
|
|
40
32
|
onTick(): Promise<void>;
|
|
41
33
|
getState(): ProviderState;
|
|
34
|
+
setPresentationMode(mode: 'terminal' | 'chat'): void;
|
|
35
|
+
getPresentationMode(): 'terminal' | 'chat';
|
|
42
36
|
onEvent(event: string, data?: any): void;
|
|
43
37
|
dispose(): void;
|
|
44
38
|
private completedDebounceTimer;
|
|
@@ -245,20 +245,6 @@ export interface ProviderModule {
|
|
|
245
245
|
shell?: boolean;
|
|
246
246
|
env?: Record<string, string>;
|
|
247
247
|
};
|
|
248
|
-
/**
|
|
249
|
-
* Configurable options shown at session launch time (schema declaration).
|
|
250
|
-
* The frontend renders these as a launch config UI.
|
|
251
|
-
* Values are passed to launchArgBuilder to produce the final args.
|
|
252
|
-
*/
|
|
253
|
-
launchOptions?: ProviderLaunchOption[];
|
|
254
|
-
/**
|
|
255
|
-
* Builds extra spawn args from user-selected launch option values.
|
|
256
|
-
* Called with the merged defaults + mode preset + user overrides.
|
|
257
|
-
* When defined, takes precedence over launchMode.extraArgs.
|
|
258
|
-
*/
|
|
259
|
-
launchArgBuilder?: (options: Record<string, string | boolean | number>) => string[];
|
|
260
|
-
/** Named presets — shortcuts that set launchOption values in bulk */
|
|
261
|
-
launchModes?: ProviderLaunchMode[];
|
|
262
248
|
patterns?: {
|
|
263
249
|
prompt?: RegExp[];
|
|
264
250
|
generating?: RegExp[];
|
|
@@ -320,71 +306,6 @@ export interface ProviderModule {
|
|
|
320
306
|
/** ACP agent auth methods (multiple supported — in priority order) */
|
|
321
307
|
auth?: AcpAuthMethod[];
|
|
322
308
|
}
|
|
323
|
-
export type ProviderLaunchOptionType = 'select' | 'boolean' | 'string' | 'number';
|
|
324
|
-
/**
|
|
325
|
-
* A single configurable option exposed at session launch time.
|
|
326
|
-
* Providers declare these so the frontend can render a launch config UI.
|
|
327
|
-
* The final args are built by launchArgBuilder(selectedValues).
|
|
328
|
-
*
|
|
329
|
-
* Example — Claude Code:
|
|
330
|
-
* { id: 'outputFormat', type: 'select', options: [
|
|
331
|
-
* { value: 'terminal', label: 'Terminal' },
|
|
332
|
-
* { value: 'stream-json', label: 'Chat' },
|
|
333
|
-
* ], default: 'terminal' }
|
|
334
|
-
*/
|
|
335
|
-
export interface ProviderLaunchOption {
|
|
336
|
-
/** Unique identifier — key used in launchArgBuilder options map */
|
|
337
|
-
id: string;
|
|
338
|
-
/** Display label */
|
|
339
|
-
name: string;
|
|
340
|
-
description?: string;
|
|
341
|
-
type: ProviderLaunchOptionType;
|
|
342
|
-
/** Options for 'select' type */
|
|
343
|
-
options?: {
|
|
344
|
-
value: string;
|
|
345
|
-
label: string;
|
|
346
|
-
description?: string;
|
|
347
|
-
}[];
|
|
348
|
-
/** Default value — applied when not explicitly set */
|
|
349
|
-
default?: string | boolean | number;
|
|
350
|
-
/**
|
|
351
|
-
* Maps specific values of this option to a frontend rendering hint.
|
|
352
|
-
* e.g. { 'stream-json': 'stream-json' } tells the UI to switch to Chat mode.
|
|
353
|
-
*/
|
|
354
|
-
outputFormatMap?: Record<string, 'terminal' | 'stream-json'>;
|
|
355
|
-
}
|
|
356
|
-
/**
|
|
357
|
-
* A named launch preset — shorthand for a specific set of launchOption values.
|
|
358
|
-
* When selected, its `options` are merged with user-configured values before
|
|
359
|
-
* calling launchArgBuilder. Falls back to `extraArgs` if no launchArgBuilder defined.
|
|
360
|
-
*/
|
|
361
|
-
export interface ProviderLaunchMode {
|
|
362
|
-
/** Unique mode identifier (e.g. 'terminal', 'chat') */
|
|
363
|
-
id: string;
|
|
364
|
-
/** Display name */
|
|
365
|
-
name: string;
|
|
366
|
-
description?: string;
|
|
367
|
-
/**
|
|
368
|
-
* Preset option values — merged over defaults before calling launchArgBuilder.
|
|
369
|
-
* Keys correspond to ProviderLaunchOption.id.
|
|
370
|
-
*/
|
|
371
|
-
options?: Record<string, string | boolean | number>;
|
|
372
|
-
/**
|
|
373
|
-
* Fallback: raw args appended when no launchArgBuilder is defined.
|
|
374
|
-
* Use launchArgBuilder + options for anything more than trivial cases.
|
|
375
|
-
*/
|
|
376
|
-
extraArgs?: string[];
|
|
377
|
-
/** Env var overrides applied on top of spawn.env */
|
|
378
|
-
env?: Record<string, string>;
|
|
379
|
-
/**
|
|
380
|
-
* Output rendering hint (shorthand when not using launchOptions/outputFormatMap).
|
|
381
|
-
* - 'terminal' — raw PTY stream (default)
|
|
382
|
-
* - 'stream-json' — structured JSON events → chat messages
|
|
383
|
-
*/
|
|
384
|
-
outputFormat?: 'terminal' | 'stream-json';
|
|
385
|
-
/** Whether this is the default mode when none is specified */
|
|
386
|
-
default?: boolean;
|
|
387
|
-
}
|
|
388
309
|
export interface ProviderResumeCapability {
|
|
389
310
|
supported: boolean;
|
|
390
311
|
stopStrategy?: 'command' | 'ctrl_c';
|
|
@@ -86,8 +86,6 @@ export interface CliProviderState extends ProviderStateBase {
|
|
|
86
86
|
category: 'cli';
|
|
87
87
|
/** terminal = PTY stream, chat = parsed conversation */
|
|
88
88
|
mode: 'terminal' | 'chat';
|
|
89
|
-
/** Active launch mode id (e.g. 'chat') — undefined means default terminal */
|
|
90
|
-
launchMode?: string;
|
|
91
89
|
}
|
|
92
90
|
/** ACP provider state */
|
|
93
91
|
export interface AcpProviderState extends ProviderStateBase {
|
package/dist/shared-types.d.ts
CHANGED
|
@@ -51,9 +51,7 @@ export interface SessionEntry {
|
|
|
51
51
|
runtimeKey?: string;
|
|
52
52
|
runtimeDisplayName?: string;
|
|
53
53
|
runtimeWorkspaceLabel?: string;
|
|
54
|
-
/** CLI only: active
|
|
55
|
-
launchMode?: string;
|
|
56
|
-
/** CLI only: output rendering mode derived from launchMode.outputFormat */
|
|
54
|
+
/** CLI only: active presentation mode */
|
|
57
55
|
mode?: 'terminal' | 'chat';
|
|
58
56
|
runtimeWriteOwner?: RuntimeWriteOwner | null;
|
|
59
57
|
runtimeAttachedClients?: RuntimeAttachedClient[];
|
package/dist/status/normalize.js
CHANGED
|
@@ -34,6 +34,63 @@ var WORKING_STATUSES = /* @__PURE__ */ new Set([
|
|
|
34
34
|
"thinking",
|
|
35
35
|
"active"
|
|
36
36
|
]);
|
|
37
|
+
var STATUS_ACTIVE_CHAT_MESSAGE_LIMIT = 60;
|
|
38
|
+
var STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT = 96 * 1024;
|
|
39
|
+
var STATUS_ACTIVE_CHAT_STRING_LIMIT = 4 * 1024;
|
|
40
|
+
var STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT = 1024;
|
|
41
|
+
var STATUS_TERMINAL_HISTORY_LIMIT = 8 * 1024;
|
|
42
|
+
var STATUS_INPUT_CONTENT_LIMIT = 2 * 1024;
|
|
43
|
+
var STATUS_MODAL_MESSAGE_LIMIT = 2 * 1024;
|
|
44
|
+
var STATUS_MODAL_BUTTON_LIMIT = 120;
|
|
45
|
+
function truncateString(value, maxChars) {
|
|
46
|
+
if (value.length <= maxChars) return value;
|
|
47
|
+
if (maxChars <= 12) return value.slice(0, Math.max(0, maxChars));
|
|
48
|
+
return `${value.slice(0, maxChars - 12)}...[truncated]`;
|
|
49
|
+
}
|
|
50
|
+
function truncateStringTail(value, maxChars) {
|
|
51
|
+
if (value.length <= maxChars) return value;
|
|
52
|
+
if (maxChars <= 12) return value.slice(value.length - Math.max(0, maxChars));
|
|
53
|
+
return `...[truncated]${value.slice(value.length - (maxChars - 12))}`;
|
|
54
|
+
}
|
|
55
|
+
function trimStructuredStrings(value, maxChars) {
|
|
56
|
+
if (typeof value === "string") return truncateString(value, maxChars);
|
|
57
|
+
if (Array.isArray(value)) return value.map((item) => trimStructuredStrings(item, maxChars));
|
|
58
|
+
if (!value || typeof value !== "object") return value;
|
|
59
|
+
return Object.fromEntries(
|
|
60
|
+
Object.entries(value).map(([key, nested]) => [key, trimStructuredStrings(nested, maxChars)])
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
function estimateBytes(value) {
|
|
64
|
+
try {
|
|
65
|
+
return JSON.stringify(value).length;
|
|
66
|
+
} catch {
|
|
67
|
+
return String(value ?? "").length;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function trimMessageForStatus(message, stringLimit) {
|
|
71
|
+
if (!message || typeof message !== "object") return message;
|
|
72
|
+
return trimStructuredStrings(message, stringLimit);
|
|
73
|
+
}
|
|
74
|
+
function trimMessagesForStatus(messages) {
|
|
75
|
+
if (!Array.isArray(messages) || messages.length === 0) return [];
|
|
76
|
+
const recent = messages.slice(-STATUS_ACTIVE_CHAT_MESSAGE_LIMIT);
|
|
77
|
+
const kept = [];
|
|
78
|
+
let totalBytes = 0;
|
|
79
|
+
for (let i = recent.length - 1; i >= 0; i -= 1) {
|
|
80
|
+
let normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_STRING_LIMIT);
|
|
81
|
+
let size = estimateBytes(normalized);
|
|
82
|
+
if (size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
|
|
83
|
+
normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT);
|
|
84
|
+
size = estimateBytes(normalized);
|
|
85
|
+
}
|
|
86
|
+
if (kept.length > 0 && totalBytes + size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
kept.push(normalized);
|
|
90
|
+
totalBytes += size;
|
|
91
|
+
}
|
|
92
|
+
return kept.reverse();
|
|
93
|
+
}
|
|
37
94
|
function hasApprovalButtons(activeModal) {
|
|
38
95
|
return (activeModal?.buttons?.length ?? 0) > 0;
|
|
39
96
|
}
|
|
@@ -60,7 +117,16 @@ function normalizeActiveChatData(activeChat) {
|
|
|
60
117
|
if (!activeChat) return activeChat;
|
|
61
118
|
return {
|
|
62
119
|
...activeChat,
|
|
63
|
-
status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal })
|
|
120
|
+
status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal }),
|
|
121
|
+
messages: trimMessagesForStatus(activeChat.messages),
|
|
122
|
+
activeModal: activeChat.activeModal ? {
|
|
123
|
+
message: truncateString(activeChat.activeModal.message || "", STATUS_MODAL_MESSAGE_LIMIT),
|
|
124
|
+
buttons: (activeChat.activeModal.buttons || []).map(
|
|
125
|
+
(button) => truncateString(String(button || ""), STATUS_MODAL_BUTTON_LIMIT)
|
|
126
|
+
)
|
|
127
|
+
} : activeChat.activeModal,
|
|
128
|
+
terminalHistory: activeChat.terminalHistory ? truncateStringTail(activeChat.terminalHistory, STATUS_TERMINAL_HISTORY_LIMIT) : activeChat.terminalHistory,
|
|
129
|
+
inputContent: activeChat.inputContent ? truncateString(activeChat.inputContent, STATUS_INPUT_CONTENT_LIMIT) : activeChat.inputContent
|
|
64
130
|
};
|
|
65
131
|
}
|
|
66
132
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/status/normalize.ts"],"sourcesContent":["import type { ActiveChatData } from '../providers/provider-instance.js';\n\nexport type ManagedStatus =\n | 'idle'\n | 'generating'\n | 'waiting_approval'\n | 'error'\n | 'stopped'\n | 'starting'\n | 'panel_hidden'\n | 'not_monitored'\n | 'disconnected';\n\nconst WORKING_STATUSES = new Set([\n 'generating',\n 'streaming',\n 'loading',\n 'loading_reference',\n 'thinking',\n 'active',\n]);\n\nfunction hasApprovalButtons(activeModal?: { buttons?: unknown[] | null } | null): boolean {\n return (activeModal?.buttons?.length ?? 0) > 0;\n}\n\nexport function normalizeManagedStatus(\n status?: string | null,\n opts?: { activeModal?: { buttons?: unknown[] | null } | null },\n): ManagedStatus {\n if (hasApprovalButtons(opts?.activeModal)) return 'waiting_approval';\n\n const normalized = String(status || 'idle').trim().toLowerCase();\n if (normalized === 'waiting_approval') return 'waiting_approval';\n if (WORKING_STATUSES.has(normalized)) return 'generating';\n if (normalized === 'error') return 'error';\n if (normalized === 'stopped') return 'stopped';\n if (normalized === 'starting') return 'starting';\n if (normalized === 'panel_hidden') return 'panel_hidden';\n if (normalized === 'not_monitored') return 'not_monitored';\n if (normalized === 'disconnected') return 'disconnected';\n return 'idle';\n}\n\nexport function isManagedStatusWorking(status?: string | null): boolean {\n return normalizeManagedStatus(status) === 'generating';\n}\n\nexport function isManagedStatusWaiting(\n status?: string | null,\n opts?: { activeModal?: { buttons?: unknown[] | null } | null },\n): boolean {\n return normalizeManagedStatus(status, opts) === 'waiting_approval';\n}\n\nexport function normalizeActiveChatData<T extends ActiveChatData | null | undefined>(\n activeChat: T,\n): T {\n if (!activeChat) return activeChat;\n return {\n ...activeChat,\n status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal }),\n } as T;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAaA,IAAM,mBAAmB,oBAAI,IAAI;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,CAAC;
|
|
1
|
+
{"version":3,"sources":["../../src/status/normalize.ts"],"sourcesContent":["import type { ActiveChatData } from '../providers/provider-instance.js';\n\nexport type ManagedStatus =\n | 'idle'\n | 'generating'\n | 'waiting_approval'\n | 'error'\n | 'stopped'\n | 'starting'\n | 'panel_hidden'\n | 'not_monitored'\n | 'disconnected';\n\nconst WORKING_STATUSES = new Set([\n 'generating',\n 'streaming',\n 'loading',\n 'loading_reference',\n 'thinking',\n 'active',\n]);\n\n// Status snapshots are sent over P2P every 5s, so keep only a recent live window here.\n// Older history is fetched on demand via `chat_history`, and CLI terminals stream via runtime events.\nconst STATUS_ACTIVE_CHAT_MESSAGE_LIMIT = 60;\nconst STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT = 96 * 1024;\nconst STATUS_ACTIVE_CHAT_STRING_LIMIT = 4 * 1024;\nconst STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT = 1024;\nconst STATUS_TERMINAL_HISTORY_LIMIT = 8 * 1024;\nconst STATUS_INPUT_CONTENT_LIMIT = 2 * 1024;\nconst STATUS_MODAL_MESSAGE_LIMIT = 2 * 1024;\nconst STATUS_MODAL_BUTTON_LIMIT = 120;\n\nfunction truncateString(value: string, maxChars: number): string {\n if (value.length <= maxChars) return value;\n if (maxChars <= 12) return value.slice(0, Math.max(0, maxChars));\n return `${value.slice(0, maxChars - 12)}...[truncated]`;\n}\n\nfunction truncateStringTail(value: string, maxChars: number): string {\n if (value.length <= maxChars) return value;\n if (maxChars <= 12) return value.slice(value.length - Math.max(0, maxChars));\n return `...[truncated]${value.slice(value.length - (maxChars - 12))}`;\n}\n\nfunction trimStructuredStrings(value: unknown, maxChars: number): unknown {\n if (typeof value === 'string') return truncateString(value, maxChars);\n if (Array.isArray(value)) return value.map((item) => trimStructuredStrings(item, maxChars));\n if (!value || typeof value !== 'object') return value;\n return Object.fromEntries(\n Object.entries(value).map(([key, nested]) => [key, trimStructuredStrings(nested, maxChars)]),\n );\n}\n\nfunction estimateBytes(value: unknown): number {\n try {\n return JSON.stringify(value).length;\n } catch {\n return String(value ?? '').length;\n }\n}\n\nfunction trimMessageForStatus(message: unknown, stringLimit: number): unknown {\n if (!message || typeof message !== 'object') return message;\n return trimStructuredStrings(message, stringLimit);\n}\n\nfunction trimMessagesForStatus(messages: unknown[] | null | undefined): unknown[] {\n if (!Array.isArray(messages) || messages.length === 0) return [];\n\n const recent = messages.slice(-STATUS_ACTIVE_CHAT_MESSAGE_LIMIT);\n const kept: unknown[] = [];\n let totalBytes = 0;\n\n for (let i = recent.length - 1; i >= 0; i -= 1) {\n let normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_STRING_LIMIT);\n let size = estimateBytes(normalized);\n\n if (size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {\n normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT);\n size = estimateBytes(normalized);\n }\n\n if (kept.length > 0 && (totalBytes + size) > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {\n continue;\n }\n\n kept.push(normalized);\n totalBytes += size;\n }\n\n return kept.reverse();\n}\n\nfunction hasApprovalButtons(activeModal?: { buttons?: unknown[] | null } | null): boolean {\n return (activeModal?.buttons?.length ?? 0) > 0;\n}\n\nexport function normalizeManagedStatus(\n status?: string | null,\n opts?: { activeModal?: { buttons?: unknown[] | null } | null },\n): ManagedStatus {\n if (hasApprovalButtons(opts?.activeModal)) return 'waiting_approval';\n\n const normalized = String(status || 'idle').trim().toLowerCase();\n if (normalized === 'waiting_approval') return 'waiting_approval';\n if (WORKING_STATUSES.has(normalized)) return 'generating';\n if (normalized === 'error') return 'error';\n if (normalized === 'stopped') return 'stopped';\n if (normalized === 'starting') return 'starting';\n if (normalized === 'panel_hidden') return 'panel_hidden';\n if (normalized === 'not_monitored') return 'not_monitored';\n if (normalized === 'disconnected') return 'disconnected';\n return 'idle';\n}\n\nexport function isManagedStatusWorking(status?: string | null): boolean {\n return normalizeManagedStatus(status) === 'generating';\n}\n\nexport function isManagedStatusWaiting(\n status?: string | null,\n opts?: { activeModal?: { buttons?: unknown[] | null } | null },\n): boolean {\n return normalizeManagedStatus(status, opts) === 'waiting_approval';\n}\n\nexport function normalizeActiveChatData<T extends ActiveChatData | null | undefined>(\n activeChat: T,\n): T {\n if (!activeChat) return activeChat;\n return {\n ...activeChat,\n status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal }),\n messages: trimMessagesForStatus(activeChat.messages) as T extends { messages: infer M } ? M : never,\n activeModal: activeChat.activeModal ? {\n message: truncateString(activeChat.activeModal.message || '', STATUS_MODAL_MESSAGE_LIMIT),\n buttons: (activeChat.activeModal.buttons || []).map((button) =>\n truncateString(String(button || ''), STATUS_MODAL_BUTTON_LIMIT)\n ),\n } : activeChat.activeModal,\n terminalHistory: activeChat.terminalHistory\n ? truncateStringTail(activeChat.terminalHistory, STATUS_TERMINAL_HISTORY_LIMIT)\n : activeChat.terminalHistory,\n inputContent: activeChat.inputContent\n ? truncateString(activeChat.inputContent, STATUS_INPUT_CONTENT_LIMIT)\n : activeChat.inputContent,\n } as T;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -7,6 +7,63 @@ var WORKING_STATUSES = /* @__PURE__ */ new Set([
|
|
|
7
7
|
"thinking",
|
|
8
8
|
"active"
|
|
9
9
|
]);
|
|
10
|
+
var STATUS_ACTIVE_CHAT_MESSAGE_LIMIT = 60;
|
|
11
|
+
var STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT = 96 * 1024;
|
|
12
|
+
var STATUS_ACTIVE_CHAT_STRING_LIMIT = 4 * 1024;
|
|
13
|
+
var STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT = 1024;
|
|
14
|
+
var STATUS_TERMINAL_HISTORY_LIMIT = 8 * 1024;
|
|
15
|
+
var STATUS_INPUT_CONTENT_LIMIT = 2 * 1024;
|
|
16
|
+
var STATUS_MODAL_MESSAGE_LIMIT = 2 * 1024;
|
|
17
|
+
var STATUS_MODAL_BUTTON_LIMIT = 120;
|
|
18
|
+
function truncateString(value, maxChars) {
|
|
19
|
+
if (value.length <= maxChars) return value;
|
|
20
|
+
if (maxChars <= 12) return value.slice(0, Math.max(0, maxChars));
|
|
21
|
+
return `${value.slice(0, maxChars - 12)}...[truncated]`;
|
|
22
|
+
}
|
|
23
|
+
function truncateStringTail(value, maxChars) {
|
|
24
|
+
if (value.length <= maxChars) return value;
|
|
25
|
+
if (maxChars <= 12) return value.slice(value.length - Math.max(0, maxChars));
|
|
26
|
+
return `...[truncated]${value.slice(value.length - (maxChars - 12))}`;
|
|
27
|
+
}
|
|
28
|
+
function trimStructuredStrings(value, maxChars) {
|
|
29
|
+
if (typeof value === "string") return truncateString(value, maxChars);
|
|
30
|
+
if (Array.isArray(value)) return value.map((item) => trimStructuredStrings(item, maxChars));
|
|
31
|
+
if (!value || typeof value !== "object") return value;
|
|
32
|
+
return Object.fromEntries(
|
|
33
|
+
Object.entries(value).map(([key, nested]) => [key, trimStructuredStrings(nested, maxChars)])
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
function estimateBytes(value) {
|
|
37
|
+
try {
|
|
38
|
+
return JSON.stringify(value).length;
|
|
39
|
+
} catch {
|
|
40
|
+
return String(value ?? "").length;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function trimMessageForStatus(message, stringLimit) {
|
|
44
|
+
if (!message || typeof message !== "object") return message;
|
|
45
|
+
return trimStructuredStrings(message, stringLimit);
|
|
46
|
+
}
|
|
47
|
+
function trimMessagesForStatus(messages) {
|
|
48
|
+
if (!Array.isArray(messages) || messages.length === 0) return [];
|
|
49
|
+
const recent = messages.slice(-STATUS_ACTIVE_CHAT_MESSAGE_LIMIT);
|
|
50
|
+
const kept = [];
|
|
51
|
+
let totalBytes = 0;
|
|
52
|
+
for (let i = recent.length - 1; i >= 0; i -= 1) {
|
|
53
|
+
let normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_STRING_LIMIT);
|
|
54
|
+
let size = estimateBytes(normalized);
|
|
55
|
+
if (size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
|
|
56
|
+
normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT);
|
|
57
|
+
size = estimateBytes(normalized);
|
|
58
|
+
}
|
|
59
|
+
if (kept.length > 0 && totalBytes + size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
kept.push(normalized);
|
|
63
|
+
totalBytes += size;
|
|
64
|
+
}
|
|
65
|
+
return kept.reverse();
|
|
66
|
+
}
|
|
10
67
|
function hasApprovalButtons(activeModal) {
|
|
11
68
|
return (activeModal?.buttons?.length ?? 0) > 0;
|
|
12
69
|
}
|
|
@@ -33,7 +90,16 @@ function normalizeActiveChatData(activeChat) {
|
|
|
33
90
|
if (!activeChat) return activeChat;
|
|
34
91
|
return {
|
|
35
92
|
...activeChat,
|
|
36
|
-
status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal })
|
|
93
|
+
status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal }),
|
|
94
|
+
messages: trimMessagesForStatus(activeChat.messages),
|
|
95
|
+
activeModal: activeChat.activeModal ? {
|
|
96
|
+
message: truncateString(activeChat.activeModal.message || "", STATUS_MODAL_MESSAGE_LIMIT),
|
|
97
|
+
buttons: (activeChat.activeModal.buttons || []).map(
|
|
98
|
+
(button) => truncateString(String(button || ""), STATUS_MODAL_BUTTON_LIMIT)
|
|
99
|
+
)
|
|
100
|
+
} : activeChat.activeModal,
|
|
101
|
+
terminalHistory: activeChat.terminalHistory ? truncateStringTail(activeChat.terminalHistory, STATUS_TERMINAL_HISTORY_LIMIT) : activeChat.terminalHistory,
|
|
102
|
+
inputContent: activeChat.inputContent ? truncateString(activeChat.inputContent, STATUS_INPUT_CONTENT_LIMIT) : activeChat.inputContent
|
|
37
103
|
};
|
|
38
104
|
}
|
|
39
105
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/status/normalize.ts"],"sourcesContent":["import type { ActiveChatData } from '../providers/provider-instance.js';\n\nexport type ManagedStatus =\n | 'idle'\n | 'generating'\n | 'waiting_approval'\n | 'error'\n | 'stopped'\n | 'starting'\n | 'panel_hidden'\n | 'not_monitored'\n | 'disconnected';\n\nconst WORKING_STATUSES = new Set([\n 'generating',\n 'streaming',\n 'loading',\n 'loading_reference',\n 'thinking',\n 'active',\n]);\n\nfunction hasApprovalButtons(activeModal?: { buttons?: unknown[] | null } | null): boolean {\n return (activeModal?.buttons?.length ?? 0) > 0;\n}\n\nexport function normalizeManagedStatus(\n status?: string | null,\n opts?: { activeModal?: { buttons?: unknown[] | null } | null },\n): ManagedStatus {\n if (hasApprovalButtons(opts?.activeModal)) return 'waiting_approval';\n\n const normalized = String(status || 'idle').trim().toLowerCase();\n if (normalized === 'waiting_approval') return 'waiting_approval';\n if (WORKING_STATUSES.has(normalized)) return 'generating';\n if (normalized === 'error') return 'error';\n if (normalized === 'stopped') return 'stopped';\n if (normalized === 'starting') return 'starting';\n if (normalized === 'panel_hidden') return 'panel_hidden';\n if (normalized === 'not_monitored') return 'not_monitored';\n if (normalized === 'disconnected') return 'disconnected';\n return 'idle';\n}\n\nexport function isManagedStatusWorking(status?: string | null): boolean {\n return normalizeManagedStatus(status) === 'generating';\n}\n\nexport function isManagedStatusWaiting(\n status?: string | null,\n opts?: { activeModal?: { buttons?: unknown[] | null } | null },\n): boolean {\n return normalizeManagedStatus(status, opts) === 'waiting_approval';\n}\n\nexport function normalizeActiveChatData<T extends ActiveChatData | null | undefined>(\n activeChat: T,\n): T {\n if (!activeChat) return activeChat;\n return {\n ...activeChat,\n status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal }),\n } as T;\n}\n"],"mappings":";AAaA,IAAM,mBAAmB,oBAAI,IAAI;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,CAAC;
|
|
1
|
+
{"version":3,"sources":["../../src/status/normalize.ts"],"sourcesContent":["import type { ActiveChatData } from '../providers/provider-instance.js';\n\nexport type ManagedStatus =\n | 'idle'\n | 'generating'\n | 'waiting_approval'\n | 'error'\n | 'stopped'\n | 'starting'\n | 'panel_hidden'\n | 'not_monitored'\n | 'disconnected';\n\nconst WORKING_STATUSES = new Set([\n 'generating',\n 'streaming',\n 'loading',\n 'loading_reference',\n 'thinking',\n 'active',\n]);\n\n// Status snapshots are sent over P2P every 5s, so keep only a recent live window here.\n// Older history is fetched on demand via `chat_history`, and CLI terminals stream via runtime events.\nconst STATUS_ACTIVE_CHAT_MESSAGE_LIMIT = 60;\nconst STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT = 96 * 1024;\nconst STATUS_ACTIVE_CHAT_STRING_LIMIT = 4 * 1024;\nconst STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT = 1024;\nconst STATUS_TERMINAL_HISTORY_LIMIT = 8 * 1024;\nconst STATUS_INPUT_CONTENT_LIMIT = 2 * 1024;\nconst STATUS_MODAL_MESSAGE_LIMIT = 2 * 1024;\nconst STATUS_MODAL_BUTTON_LIMIT = 120;\n\nfunction truncateString(value: string, maxChars: number): string {\n if (value.length <= maxChars) return value;\n if (maxChars <= 12) return value.slice(0, Math.max(0, maxChars));\n return `${value.slice(0, maxChars - 12)}...[truncated]`;\n}\n\nfunction truncateStringTail(value: string, maxChars: number): string {\n if (value.length <= maxChars) return value;\n if (maxChars <= 12) return value.slice(value.length - Math.max(0, maxChars));\n return `...[truncated]${value.slice(value.length - (maxChars - 12))}`;\n}\n\nfunction trimStructuredStrings(value: unknown, maxChars: number): unknown {\n if (typeof value === 'string') return truncateString(value, maxChars);\n if (Array.isArray(value)) return value.map((item) => trimStructuredStrings(item, maxChars));\n if (!value || typeof value !== 'object') return value;\n return Object.fromEntries(\n Object.entries(value).map(([key, nested]) => [key, trimStructuredStrings(nested, maxChars)]),\n );\n}\n\nfunction estimateBytes(value: unknown): number {\n try {\n return JSON.stringify(value).length;\n } catch {\n return String(value ?? '').length;\n }\n}\n\nfunction trimMessageForStatus(message: unknown, stringLimit: number): unknown {\n if (!message || typeof message !== 'object') return message;\n return trimStructuredStrings(message, stringLimit);\n}\n\nfunction trimMessagesForStatus(messages: unknown[] | null | undefined): unknown[] {\n if (!Array.isArray(messages) || messages.length === 0) return [];\n\n const recent = messages.slice(-STATUS_ACTIVE_CHAT_MESSAGE_LIMIT);\n const kept: unknown[] = [];\n let totalBytes = 0;\n\n for (let i = recent.length - 1; i >= 0; i -= 1) {\n let normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_STRING_LIMIT);\n let size = estimateBytes(normalized);\n\n if (size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {\n normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT);\n size = estimateBytes(normalized);\n }\n\n if (kept.length > 0 && (totalBytes + size) > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {\n continue;\n }\n\n kept.push(normalized);\n totalBytes += size;\n }\n\n return kept.reverse();\n}\n\nfunction hasApprovalButtons(activeModal?: { buttons?: unknown[] | null } | null): boolean {\n return (activeModal?.buttons?.length ?? 0) > 0;\n}\n\nexport function normalizeManagedStatus(\n status?: string | null,\n opts?: { activeModal?: { buttons?: unknown[] | null } | null },\n): ManagedStatus {\n if (hasApprovalButtons(opts?.activeModal)) return 'waiting_approval';\n\n const normalized = String(status || 'idle').trim().toLowerCase();\n if (normalized === 'waiting_approval') return 'waiting_approval';\n if (WORKING_STATUSES.has(normalized)) return 'generating';\n if (normalized === 'error') return 'error';\n if (normalized === 'stopped') return 'stopped';\n if (normalized === 'starting') return 'starting';\n if (normalized === 'panel_hidden') return 'panel_hidden';\n if (normalized === 'not_monitored') return 'not_monitored';\n if (normalized === 'disconnected') return 'disconnected';\n return 'idle';\n}\n\nexport function isManagedStatusWorking(status?: string | null): boolean {\n return normalizeManagedStatus(status) === 'generating';\n}\n\nexport function isManagedStatusWaiting(\n status?: string | null,\n opts?: { activeModal?: { buttons?: unknown[] | null } | null },\n): boolean {\n return normalizeManagedStatus(status, opts) === 'waiting_approval';\n}\n\nexport function normalizeActiveChatData<T extends ActiveChatData | null | undefined>(\n activeChat: T,\n): T {\n if (!activeChat) return activeChat;\n return {\n ...activeChat,\n status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal }),\n messages: trimMessagesForStatus(activeChat.messages) as T extends { messages: infer M } ? M : never,\n activeModal: activeChat.activeModal ? {\n message: truncateString(activeChat.activeModal.message || '', STATUS_MODAL_MESSAGE_LIMIT),\n buttons: (activeChat.activeModal.buttons || []).map((button) =>\n truncateString(String(button || ''), STATUS_MODAL_BUTTON_LIMIT)\n ),\n } : activeChat.activeModal,\n terminalHistory: activeChat.terminalHistory\n ? truncateStringTail(activeChat.terminalHistory, STATUS_TERMINAL_HISTORY_LIMIT)\n : activeChat.terminalHistory,\n inputContent: activeChat.inputContent\n ? truncateString(activeChat.inputContent, STATUS_INPUT_CONTENT_LIMIT)\n : activeChat.inputContent,\n } as T;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -61,6 +61,7 @@ export declare class DaemonStatusReporter {
|
|
|
61
61
|
/** Reset P2P dedup hash — forces next send to transmit even if content unchanged */
|
|
62
62
|
resetP2PHash(): void;
|
|
63
63
|
private ts;
|
|
64
|
+
private summarizeLargePayloadSessions;
|
|
64
65
|
sendUnifiedStatusReport(opts?: {
|
|
65
66
|
p2pOnly?: boolean;
|
|
66
67
|
}): Promise<void>;
|
package/package.json
CHANGED
|
@@ -10,12 +10,20 @@ export function forwardAgentStreamsToIdeInstance(
|
|
|
10
10
|
streams: any[],
|
|
11
11
|
): void {
|
|
12
12
|
const ideInstance = instanceManager.getInstance(`ide:${ideType}`) as
|
|
13
|
-
| {
|
|
13
|
+
| {
|
|
14
|
+
onEvent?: (event: string, payload?: Record<string, unknown>) => void;
|
|
15
|
+
getExtensionTypes?: () => string[];
|
|
16
|
+
}
|
|
14
17
|
| undefined;
|
|
15
18
|
|
|
16
19
|
if (!ideInstance?.onEvent) return;
|
|
17
20
|
|
|
21
|
+
const seenExtensionTypes = new Set<string>();
|
|
22
|
+
|
|
18
23
|
for (const stream of streams) {
|
|
24
|
+
if (typeof stream.agentType === 'string' && stream.agentType) {
|
|
25
|
+
seenExtensionTypes.add(stream.agentType);
|
|
26
|
+
}
|
|
19
27
|
ideInstance.onEvent('stream_update', {
|
|
20
28
|
extensionType: stream.agentType,
|
|
21
29
|
streams: [stream],
|
|
@@ -32,4 +40,16 @@ export function forwardAgentStreamsToIdeInstance(
|
|
|
32
40
|
inputContent: stream.inputContent || '',
|
|
33
41
|
});
|
|
34
42
|
}
|
|
43
|
+
|
|
44
|
+
const extensionTypes = ideInstance.getExtensionTypes?.() || [];
|
|
45
|
+
if (streams.length === 0) {
|
|
46
|
+
ideInstance.onEvent('stream_reset_all');
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
for (const extensionType of extensionTypes) {
|
|
51
|
+
if (!seenExtensionTypes.has(extensionType)) {
|
|
52
|
+
ideInstance.onEvent('stream_reset', { extensionType });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
35
55
|
}
|
|
@@ -167,7 +167,12 @@ export class AgentStreamPoller {
|
|
|
167
167
|
} catch { }
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
if (!resolvedActiveSessionId || !parentSessionId)
|
|
170
|
+
if (!resolvedActiveSessionId || !parentSessionId) {
|
|
171
|
+
if (parentSessionId) {
|
|
172
|
+
this.deps.onStreamsUpdated?.(ideType, []);
|
|
173
|
+
}
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
171
176
|
|
|
172
177
|
try {
|
|
173
178
|
await agentStreamManager.syncActiveSession(cdp, parentSessionId);
|
|
@@ -440,6 +440,18 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
440
440
|
this.structuredMessages = [...this.committedMessages];
|
|
441
441
|
}
|
|
442
442
|
|
|
443
|
+
private normalizeParsedMessages(parsedMessages: any[]): CliChatMessage[] {
|
|
444
|
+
return parsedMessages
|
|
445
|
+
.filter((message) => message && (message.role === 'user' || message.role === 'assistant'))
|
|
446
|
+
.map((message) => ({
|
|
447
|
+
role: message.role,
|
|
448
|
+
content: typeof message.content === 'string' ? message.content : String(message.content || ''),
|
|
449
|
+
timestamp: typeof message.timestamp === 'number' && Number.isFinite(message.timestamp)
|
|
450
|
+
? message.timestamp
|
|
451
|
+
: Date.now(),
|
|
452
|
+
}));
|
|
453
|
+
}
|
|
454
|
+
|
|
443
455
|
private sliceFromOffset(text: string, start: number): string {
|
|
444
456
|
if (!text) return '';
|
|
445
457
|
if (!Number.isFinite(start) || start <= 0) return text;
|
|
@@ -951,8 +963,15 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
951
963
|
}
|
|
952
964
|
|
|
953
965
|
private commitCurrentTranscript(): void {
|
|
954
|
-
|
|
955
|
-
|
|
966
|
+
const parsed = this.parseCurrentTranscript(
|
|
967
|
+
this.committedMessages,
|
|
968
|
+
this.responseBuffer,
|
|
969
|
+
this.currentTurnScope,
|
|
970
|
+
);
|
|
971
|
+
if (parsed && Array.isArray(parsed.messages)) {
|
|
972
|
+
this.committedMessages = this.normalizeParsedMessages(parsed.messages);
|
|
973
|
+
this.syncMessageViews();
|
|
974
|
+
}
|
|
956
975
|
}
|
|
957
976
|
|
|
958
977
|
// ─── Script Execution ──────────────────────────
|
|
@@ -1003,6 +1022,22 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1003
1022
|
* Called by command handler / dashboard for rich content rendering.
|
|
1004
1023
|
*/
|
|
1005
1024
|
getScriptParsedStatus(): any {
|
|
1025
|
+
const parsed = this.parseCurrentTranscript(
|
|
1026
|
+
this.committedMessages,
|
|
1027
|
+
this.responseBuffer,
|
|
1028
|
+
this.currentTurnScope,
|
|
1029
|
+
);
|
|
1030
|
+
if (parsed && Array.isArray(parsed.messages)) {
|
|
1031
|
+
return {
|
|
1032
|
+
id: parsed.id || 'cli_session',
|
|
1033
|
+
status: parsed.status || this.currentStatus,
|
|
1034
|
+
title: parsed.title || this.cliName,
|
|
1035
|
+
terminalHistory: this.terminalHistory,
|
|
1036
|
+
messages: parsed.messages,
|
|
1037
|
+
activeModal: parsed.activeModal ?? this.activeModal,
|
|
1038
|
+
};
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1006
1041
|
const messages = [...this.committedMessages];
|
|
1007
1042
|
return {
|
|
1008
1043
|
id: 'cli_session',
|