@adhdev/daemon-core 0.7.40 → 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 +3 -0
- package/dist/config/config.d.ts +2 -22
- package/dist/index.js +310 -34
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +310 -34
- package/dist/index.mjs.map +1 -1
- package/dist/providers/cli-provider-instance.d.ts +3 -0
- package/dist/providers/extension-provider-instance.d.ts +1 -0
- package/dist/shared-types.d.ts +2 -0
- 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 +45 -2
- 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 -5
- package/src/providers/contracts.ts +0 -1
- package/src/providers/extension-provider-instance.ts +27 -0
- package/src/providers/ide-provider-instance.ts +12 -0
- package/src/shared-types.ts +2 -0
- package/src/status/builders.ts +8 -1
- package/src/status/normalize.ts +85 -0
- package/src/status/reporter.ts +31 -2
package/dist/index.mjs
CHANGED
|
@@ -28,7 +28,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
28
28
|
// src/config/config.ts
|
|
29
29
|
var config_exports = {};
|
|
30
30
|
__export(config_exports, {
|
|
31
|
-
generateConnectionToken: () => generateConnectionToken,
|
|
32
31
|
generateMachineId: () => generateMachineId,
|
|
33
32
|
getConfigDir: () => getConfigDir,
|
|
34
33
|
isSetupComplete: () => isSetupComplete,
|
|
@@ -43,6 +42,57 @@ import { homedir } from "os";
|
|
|
43
42
|
import { join } from "path";
|
|
44
43
|
import { existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync } from "fs";
|
|
45
44
|
import { randomUUID } from "crypto";
|
|
45
|
+
function isPlainObject(value) {
|
|
46
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
47
|
+
}
|
|
48
|
+
function asStringArray(value) {
|
|
49
|
+
if (!Array.isArray(value)) return [];
|
|
50
|
+
return value.filter((item) => typeof item === "string");
|
|
51
|
+
}
|
|
52
|
+
function asNullableString(value) {
|
|
53
|
+
return typeof value === "string" ? value : null;
|
|
54
|
+
}
|
|
55
|
+
function asOptionalString(value) {
|
|
56
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
57
|
+
}
|
|
58
|
+
function asBoolean(value, fallback) {
|
|
59
|
+
return typeof value === "boolean" ? value : fallback;
|
|
60
|
+
}
|
|
61
|
+
function normalizeConfig(raw) {
|
|
62
|
+
const parsed = isPlainObject(raw) ? raw : {};
|
|
63
|
+
const legacySessionReads = isPlainObject(parsed.recentSessionReads) ? parsed.recentSessionReads : {};
|
|
64
|
+
const sessionReads = isPlainObject(parsed.sessionReads) ? parsed.sessionReads : {};
|
|
65
|
+
const mergedSessionReads = Object.fromEntries(
|
|
66
|
+
Object.entries({ ...legacySessionReads, ...sessionReads }).filter(([, value]) => typeof value === "number" && Number.isFinite(value))
|
|
67
|
+
);
|
|
68
|
+
const sessionReadMarkers = Object.fromEntries(
|
|
69
|
+
Object.entries(isPlainObject(parsed.sessionReadMarkers) ? parsed.sessionReadMarkers : {}).filter(([, value]) => typeof value === "string")
|
|
70
|
+
);
|
|
71
|
+
return {
|
|
72
|
+
serverUrl: typeof parsed.serverUrl === "string" && parsed.serverUrl.trim() ? parsed.serverUrl : DEFAULT_CONFIG.serverUrl,
|
|
73
|
+
selectedIde: asNullableString(parsed.selectedIde),
|
|
74
|
+
configuredIdes: asStringArray(parsed.configuredIdes),
|
|
75
|
+
installedExtensions: asStringArray(parsed.installedExtensions),
|
|
76
|
+
userEmail: asNullableString(parsed.userEmail),
|
|
77
|
+
userName: asNullableString(parsed.userName),
|
|
78
|
+
setupCompleted: asBoolean(parsed.setupCompleted, DEFAULT_CONFIG.setupCompleted),
|
|
79
|
+
setupDate: asNullableString(parsed.setupDate),
|
|
80
|
+
enabledIdes: asStringArray(parsed.enabledIdes),
|
|
81
|
+
workspaces: Array.isArray(parsed.workspaces) ? parsed.workspaces : [],
|
|
82
|
+
defaultWorkspaceId: asNullableString(parsed.defaultWorkspaceId) ?? asNullableString(parsed.activeWorkspaceId),
|
|
83
|
+
recentActivity: Array.isArray(parsed.recentActivity) ? parsed.recentActivity : [],
|
|
84
|
+
sessionReads: mergedSessionReads,
|
|
85
|
+
sessionReadMarkers,
|
|
86
|
+
machineNickname: asNullableString(parsed.machineNickname),
|
|
87
|
+
machineId: asOptionalString(parsed.machineId),
|
|
88
|
+
machineSecret: parsed.machineSecret === null ? null : asOptionalString(parsed.machineSecret),
|
|
89
|
+
registeredMachineId: asOptionalString(parsed.registeredMachineId),
|
|
90
|
+
providerSettings: isPlainObject(parsed.providerSettings) ? parsed.providerSettings : {},
|
|
91
|
+
ideSettings: isPlainObject(parsed.ideSettings) ? parsed.ideSettings : {},
|
|
92
|
+
disableUpstream: asBoolean(parsed.disableUpstream, DEFAULT_CONFIG.disableUpstream ?? false),
|
|
93
|
+
providerDir: asOptionalString(parsed.providerDir)
|
|
94
|
+
};
|
|
95
|
+
}
|
|
46
96
|
function generateMachineId() {
|
|
47
97
|
return `${MACHINE_ID_PREFIX}${randomUUID().replace(/-/g, "")}`;
|
|
48
98
|
}
|
|
@@ -86,14 +136,10 @@ function loadConfig() {
|
|
|
86
136
|
try {
|
|
87
137
|
const raw = readFileSync(configPath, "utf-8");
|
|
88
138
|
const parsed = JSON.parse(raw);
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
merged.defaultWorkspaceId = merged.activeWorkspaceId;
|
|
92
|
-
}
|
|
93
|
-
delete merged.activeWorkspaceId;
|
|
94
|
-
const ensured = ensureMachineId(merged);
|
|
139
|
+
const normalizedInput = normalizeConfig(parsed);
|
|
140
|
+
const ensured = ensureMachineId(normalizedInput);
|
|
95
141
|
const normalized = ensured.config;
|
|
96
|
-
if (ensured.changed) {
|
|
142
|
+
if (ensured.changed || JSON.stringify(parsed) !== JSON.stringify(normalized)) {
|
|
97
143
|
try {
|
|
98
144
|
saveConfig(normalized);
|
|
99
145
|
} catch {
|
|
@@ -108,10 +154,11 @@ function loadConfig() {
|
|
|
108
154
|
function saveConfig(config) {
|
|
109
155
|
const configPath = getConfigPath();
|
|
110
156
|
const dir = getConfigDir();
|
|
157
|
+
const normalized = normalizeConfig(config);
|
|
111
158
|
if (!existsSync(dir)) {
|
|
112
159
|
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
113
160
|
}
|
|
114
|
-
writeFileSync(configPath, JSON.stringify(
|
|
161
|
+
writeFileSync(configPath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
|
|
115
162
|
try {
|
|
116
163
|
chmodSync(configPath, 384);
|
|
117
164
|
} catch {
|
|
@@ -140,32 +187,19 @@ function isSetupComplete() {
|
|
|
140
187
|
function resetConfig() {
|
|
141
188
|
saveConfig({ ...DEFAULT_CONFIG });
|
|
142
189
|
}
|
|
143
|
-
function generateConnectionToken() {
|
|
144
|
-
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
145
|
-
let token = "db_";
|
|
146
|
-
for (let i = 0; i < 32; i++) {
|
|
147
|
-
token += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
148
|
-
}
|
|
149
|
-
return token;
|
|
150
|
-
}
|
|
151
190
|
var DEFAULT_CONFIG, MACHINE_ID_PREFIX;
|
|
152
191
|
var init_config = __esm({
|
|
153
192
|
"src/config/config.ts"() {
|
|
154
193
|
"use strict";
|
|
155
194
|
DEFAULT_CONFIG = {
|
|
156
195
|
serverUrl: "https://api.adhf.dev",
|
|
157
|
-
apiToken: null,
|
|
158
|
-
connectionToken: null,
|
|
159
196
|
selectedIde: null,
|
|
160
197
|
configuredIdes: [],
|
|
161
198
|
installedExtensions: [],
|
|
162
|
-
autoConnect: true,
|
|
163
|
-
notifications: true,
|
|
164
199
|
userEmail: null,
|
|
165
200
|
userName: null,
|
|
166
201
|
setupCompleted: false,
|
|
167
202
|
setupDate: null,
|
|
168
|
-
configuredCLIs: [],
|
|
169
203
|
enabledIdes: [],
|
|
170
204
|
workspaces: [],
|
|
171
205
|
defaultWorkspaceId: null,
|
|
@@ -978,6 +1012,13 @@ var init_provider_cli_adapter = __esm({
|
|
|
978
1012
|
this.messages = [...this.committedMessages];
|
|
979
1013
|
this.structuredMessages = [...this.committedMessages];
|
|
980
1014
|
}
|
|
1015
|
+
normalizeParsedMessages(parsedMessages) {
|
|
1016
|
+
return parsedMessages.filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message) => ({
|
|
1017
|
+
role: message.role,
|
|
1018
|
+
content: typeof message.content === "string" ? message.content : String(message.content || ""),
|
|
1019
|
+
timestamp: typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : Date.now()
|
|
1020
|
+
}));
|
|
1021
|
+
}
|
|
981
1022
|
sliceFromOffset(text, start) {
|
|
982
1023
|
if (!text) return "";
|
|
983
1024
|
if (!Number.isFinite(start) || start <= 0) return text;
|
|
@@ -1374,6 +1415,15 @@ var init_provider_cli_adapter = __esm({
|
|
|
1374
1415
|
this.onStatusChange?.();
|
|
1375
1416
|
}
|
|
1376
1417
|
commitCurrentTranscript() {
|
|
1418
|
+
const parsed = this.parseCurrentTranscript(
|
|
1419
|
+
this.committedMessages,
|
|
1420
|
+
this.responseBuffer,
|
|
1421
|
+
this.currentTurnScope
|
|
1422
|
+
);
|
|
1423
|
+
if (parsed && Array.isArray(parsed.messages)) {
|
|
1424
|
+
this.committedMessages = this.normalizeParsedMessages(parsed.messages);
|
|
1425
|
+
this.syncMessageViews();
|
|
1426
|
+
}
|
|
1377
1427
|
}
|
|
1378
1428
|
// ─── Script Execution ──────────────────────────
|
|
1379
1429
|
runDetectStatus(text) {
|
|
@@ -1418,6 +1468,21 @@ var init_provider_cli_adapter = __esm({
|
|
|
1418
1468
|
* Called by command handler / dashboard for rich content rendering.
|
|
1419
1469
|
*/
|
|
1420
1470
|
getScriptParsedStatus() {
|
|
1471
|
+
const parsed = this.parseCurrentTranscript(
|
|
1472
|
+
this.committedMessages,
|
|
1473
|
+
this.responseBuffer,
|
|
1474
|
+
this.currentTurnScope
|
|
1475
|
+
);
|
|
1476
|
+
if (parsed && Array.isArray(parsed.messages)) {
|
|
1477
|
+
return {
|
|
1478
|
+
id: parsed.id || "cli_session",
|
|
1479
|
+
status: parsed.status || this.currentStatus,
|
|
1480
|
+
title: parsed.title || this.cliName,
|
|
1481
|
+
terminalHistory: this.terminalHistory,
|
|
1482
|
+
messages: parsed.messages,
|
|
1483
|
+
activeModal: parsed.activeModal ?? this.activeModal
|
|
1484
|
+
};
|
|
1485
|
+
}
|
|
1421
1486
|
const messages = [...this.committedMessages];
|
|
1422
1487
|
return {
|
|
1423
1488
|
id: "cli_session",
|
|
@@ -3744,6 +3809,8 @@ var ExtensionProviderInstance = class {
|
|
|
3744
3809
|
this.detectTransition(newStatus, data);
|
|
3745
3810
|
this.currentStatus = newStatus;
|
|
3746
3811
|
}
|
|
3812
|
+
} else if (event === "stream_reset") {
|
|
3813
|
+
this.resetStreamState();
|
|
3747
3814
|
} else if (event === "extension_connected") {
|
|
3748
3815
|
this.ideType = data?.ideType || "";
|
|
3749
3816
|
}
|
|
@@ -3823,6 +3890,30 @@ var ExtensionProviderInstance = class {
|
|
|
3823
3890
|
const title = typeof data?.title === "string" && data.title.trim() ? data.title.trim() : this.chatTitle;
|
|
3824
3891
|
return title || this.agentName || this.provider.name;
|
|
3825
3892
|
}
|
|
3893
|
+
resetStreamState() {
|
|
3894
|
+
if (this.currentStatus !== "idle") {
|
|
3895
|
+
this.detectTransition("idle", {
|
|
3896
|
+
title: this.chatTitle,
|
|
3897
|
+
agentName: this.agentName,
|
|
3898
|
+
extensionId: this.extensionId,
|
|
3899
|
+
messages: this.messages
|
|
3900
|
+
});
|
|
3901
|
+
}
|
|
3902
|
+
this.agentStreams = [];
|
|
3903
|
+
this.messages = [];
|
|
3904
|
+
this.activeModal = null;
|
|
3905
|
+
this.currentModel = "";
|
|
3906
|
+
this.currentMode = "";
|
|
3907
|
+
this.controlValues = {};
|
|
3908
|
+
this.currentStatus = "idle";
|
|
3909
|
+
this.chatId = null;
|
|
3910
|
+
this.chatTitle = null;
|
|
3911
|
+
this.agentName = "";
|
|
3912
|
+
this.extensionId = "";
|
|
3913
|
+
this.lastAgentStatus = "idle";
|
|
3914
|
+
this.generatingStartedAt = 0;
|
|
3915
|
+
this.monitor.reset();
|
|
3916
|
+
}
|
|
3826
3917
|
};
|
|
3827
3918
|
|
|
3828
3919
|
// src/config/chat-history.ts
|
|
@@ -4105,11 +4196,23 @@ var IdeProviderInstance = class {
|
|
|
4105
4196
|
} else if (event === "cdp_disconnected") {
|
|
4106
4197
|
this.cachedChat = null;
|
|
4107
4198
|
this.currentStatus = "idle";
|
|
4199
|
+
for (const ext of this.extensions.values()) {
|
|
4200
|
+
ext.onEvent("stream_reset");
|
|
4201
|
+
}
|
|
4108
4202
|
} else if (event === "stream_update") {
|
|
4109
4203
|
const extType = data?.extensionType;
|
|
4110
4204
|
if (extType && this.extensions.has(extType)) {
|
|
4111
4205
|
this.extensions.get(extType).onEvent("stream_update", data);
|
|
4112
4206
|
}
|
|
4207
|
+
} else if (event === "stream_reset") {
|
|
4208
|
+
const extType = data?.extensionType;
|
|
4209
|
+
if (extType && this.extensions.has(extType)) {
|
|
4210
|
+
this.extensions.get(extType).onEvent("stream_reset");
|
|
4211
|
+
}
|
|
4212
|
+
} else if (event === "stream_reset_all") {
|
|
4213
|
+
for (const ext of this.extensions.values()) {
|
|
4214
|
+
ext.onEvent("stream_reset");
|
|
4215
|
+
}
|
|
4113
4216
|
}
|
|
4114
4217
|
}
|
|
4115
4218
|
dispose() {
|
|
@@ -4776,6 +4879,63 @@ var WORKING_STATUSES = /* @__PURE__ */ new Set([
|
|
|
4776
4879
|
"thinking",
|
|
4777
4880
|
"active"
|
|
4778
4881
|
]);
|
|
4882
|
+
var STATUS_ACTIVE_CHAT_MESSAGE_LIMIT = 60;
|
|
4883
|
+
var STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT = 96 * 1024;
|
|
4884
|
+
var STATUS_ACTIVE_CHAT_STRING_LIMIT = 4 * 1024;
|
|
4885
|
+
var STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT = 1024;
|
|
4886
|
+
var STATUS_TERMINAL_HISTORY_LIMIT = 8 * 1024;
|
|
4887
|
+
var STATUS_INPUT_CONTENT_LIMIT = 2 * 1024;
|
|
4888
|
+
var STATUS_MODAL_MESSAGE_LIMIT = 2 * 1024;
|
|
4889
|
+
var STATUS_MODAL_BUTTON_LIMIT = 120;
|
|
4890
|
+
function truncateString(value, maxChars) {
|
|
4891
|
+
if (value.length <= maxChars) return value;
|
|
4892
|
+
if (maxChars <= 12) return value.slice(0, Math.max(0, maxChars));
|
|
4893
|
+
return `${value.slice(0, maxChars - 12)}...[truncated]`;
|
|
4894
|
+
}
|
|
4895
|
+
function truncateStringTail(value, maxChars) {
|
|
4896
|
+
if (value.length <= maxChars) return value;
|
|
4897
|
+
if (maxChars <= 12) return value.slice(value.length - Math.max(0, maxChars));
|
|
4898
|
+
return `...[truncated]${value.slice(value.length - (maxChars - 12))}`;
|
|
4899
|
+
}
|
|
4900
|
+
function trimStructuredStrings(value, maxChars) {
|
|
4901
|
+
if (typeof value === "string") return truncateString(value, maxChars);
|
|
4902
|
+
if (Array.isArray(value)) return value.map((item) => trimStructuredStrings(item, maxChars));
|
|
4903
|
+
if (!value || typeof value !== "object") return value;
|
|
4904
|
+
return Object.fromEntries(
|
|
4905
|
+
Object.entries(value).map(([key, nested]) => [key, trimStructuredStrings(nested, maxChars)])
|
|
4906
|
+
);
|
|
4907
|
+
}
|
|
4908
|
+
function estimateBytes(value) {
|
|
4909
|
+
try {
|
|
4910
|
+
return JSON.stringify(value).length;
|
|
4911
|
+
} catch {
|
|
4912
|
+
return String(value ?? "").length;
|
|
4913
|
+
}
|
|
4914
|
+
}
|
|
4915
|
+
function trimMessageForStatus(message, stringLimit) {
|
|
4916
|
+
if (!message || typeof message !== "object") return message;
|
|
4917
|
+
return trimStructuredStrings(message, stringLimit);
|
|
4918
|
+
}
|
|
4919
|
+
function trimMessagesForStatus(messages) {
|
|
4920
|
+
if (!Array.isArray(messages) || messages.length === 0) return [];
|
|
4921
|
+
const recent = messages.slice(-STATUS_ACTIVE_CHAT_MESSAGE_LIMIT);
|
|
4922
|
+
const kept = [];
|
|
4923
|
+
let totalBytes = 0;
|
|
4924
|
+
for (let i = recent.length - 1; i >= 0; i -= 1) {
|
|
4925
|
+
let normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_STRING_LIMIT);
|
|
4926
|
+
let size = estimateBytes(normalized);
|
|
4927
|
+
if (size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
|
|
4928
|
+
normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT);
|
|
4929
|
+
size = estimateBytes(normalized);
|
|
4930
|
+
}
|
|
4931
|
+
if (kept.length > 0 && totalBytes + size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
|
|
4932
|
+
continue;
|
|
4933
|
+
}
|
|
4934
|
+
kept.push(normalized);
|
|
4935
|
+
totalBytes += size;
|
|
4936
|
+
}
|
|
4937
|
+
return kept.reverse();
|
|
4938
|
+
}
|
|
4779
4939
|
function hasApprovalButtons(activeModal) {
|
|
4780
4940
|
return (activeModal?.buttons?.length ?? 0) > 0;
|
|
4781
4941
|
}
|
|
@@ -4802,7 +4962,16 @@ function normalizeActiveChatData(activeChat) {
|
|
|
4802
4962
|
if (!activeChat) return activeChat;
|
|
4803
4963
|
return {
|
|
4804
4964
|
...activeChat,
|
|
4805
|
-
status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal })
|
|
4965
|
+
status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal }),
|
|
4966
|
+
messages: trimMessagesForStatus(activeChat.messages),
|
|
4967
|
+
activeModal: activeChat.activeModal ? {
|
|
4968
|
+
message: truncateString(activeChat.activeModal.message || "", STATUS_MODAL_MESSAGE_LIMIT),
|
|
4969
|
+
buttons: (activeChat.activeModal.buttons || []).map(
|
|
4970
|
+
(button) => truncateString(String(button || ""), STATUS_MODAL_BUTTON_LIMIT)
|
|
4971
|
+
)
|
|
4972
|
+
} : activeChat.activeModal,
|
|
4973
|
+
terminalHistory: activeChat.terminalHistory ? truncateStringTail(activeChat.terminalHistory, STATUS_TERMINAL_HISTORY_LIMIT) : activeChat.terminalHistory,
|
|
4974
|
+
inputContent: activeChat.inputContent ? truncateString(activeChat.inputContent, STATUS_INPUT_CONTENT_LIMIT) : activeChat.inputContent
|
|
4806
4975
|
};
|
|
4807
4976
|
}
|
|
4808
4977
|
|
|
@@ -4900,6 +5069,11 @@ var PTY_SESSION_CAPABILITIES = [
|
|
|
4900
5069
|
"terminal_io",
|
|
4901
5070
|
"resize_terminal"
|
|
4902
5071
|
];
|
|
5072
|
+
var CLI_CHAT_SESSION_CAPABILITIES = [
|
|
5073
|
+
"read_chat",
|
|
5074
|
+
"send_message",
|
|
5075
|
+
"resolve_action"
|
|
5076
|
+
];
|
|
4903
5077
|
var ACP_SESSION_CAPABILITIES = [
|
|
4904
5078
|
"read_chat",
|
|
4905
5079
|
"send_message",
|
|
@@ -4989,9 +5163,10 @@ function buildCliSession(state) {
|
|
|
4989
5163
|
runtimeWorkspaceLabel: state.runtime?.workspaceLabel,
|
|
4990
5164
|
runtimeWriteOwner: state.runtime?.writeOwner || null,
|
|
4991
5165
|
runtimeAttachedClients: state.runtime?.attachedClients || [],
|
|
5166
|
+
mode: state.mode,
|
|
4992
5167
|
resume: state.resume,
|
|
4993
5168
|
activeChat,
|
|
4994
|
-
capabilities: PTY_SESSION_CAPABILITIES,
|
|
5169
|
+
capabilities: state.mode === "terminal" ? PTY_SESSION_CAPABILITIES : CLI_CHAT_SESSION_CAPABILITIES,
|
|
4995
5170
|
controlValues: state.controlValues,
|
|
4996
5171
|
providerControls: buildFallbackControls(
|
|
4997
5172
|
state.providerControls
|
|
@@ -6165,6 +6340,13 @@ async function handleFileListBrowse(h, args) {
|
|
|
6165
6340
|
|
|
6166
6341
|
// src/commands/stream-commands.ts
|
|
6167
6342
|
init_logger();
|
|
6343
|
+
function getCliPresentationMode(h, targetSessionId) {
|
|
6344
|
+
if (!targetSessionId) return null;
|
|
6345
|
+
const instance = h.ctx.instanceManager?.getInstance(targetSessionId);
|
|
6346
|
+
if (instance?.category !== "cli") return null;
|
|
6347
|
+
const mode = instance.getPresentationMode?.();
|
|
6348
|
+
return mode === "chat" || mode === "terminal" ? mode : null;
|
|
6349
|
+
}
|
|
6168
6350
|
async function handleFocusSession(h, args) {
|
|
6169
6351
|
if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
6170
6352
|
const sessionId = args?.targetSessionId || h.currentSession?.sessionId;
|
|
@@ -6175,6 +6357,9 @@ async function handleFocusSession(h, args) {
|
|
|
6175
6357
|
function handlePtyInput(h, args) {
|
|
6176
6358
|
const { cliType, data, targetSessionId } = args || {};
|
|
6177
6359
|
if (!data) return { success: false, error: "data required" };
|
|
6360
|
+
if (getCliPresentationMode(h, targetSessionId) === "chat") {
|
|
6361
|
+
return { success: false, error: "CLI session is in chat mode", code: "CLI_VIEW_MODE_NOT_TERMINAL" };
|
|
6362
|
+
}
|
|
6178
6363
|
const adapter = h.getCliAdapter(targetSessionId || cliType);
|
|
6179
6364
|
if (!adapter || typeof adapter.writeRaw !== "function") {
|
|
6180
6365
|
return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
|
|
@@ -6185,6 +6370,9 @@ function handlePtyInput(h, args) {
|
|
|
6185
6370
|
function handlePtyResize(h, args) {
|
|
6186
6371
|
const { cliType, cols, rows, force, targetSessionId } = args || {};
|
|
6187
6372
|
if (!cols || !rows) return { success: false, error: "cols and rows required" };
|
|
6373
|
+
if (getCliPresentationMode(h, targetSessionId) === "chat") {
|
|
6374
|
+
return { success: false, error: "CLI session is in chat mode", code: "CLI_VIEW_MODE_NOT_TERMINAL" };
|
|
6375
|
+
}
|
|
6188
6376
|
const adapter = h.getCliAdapter(targetSessionId || cliType);
|
|
6189
6377
|
if (!adapter || typeof adapter.resize !== "function") {
|
|
6190
6378
|
return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
|
|
@@ -8592,6 +8780,7 @@ var DaemonCommandRouter = class {
|
|
|
8592
8780
|
// ─── CLI / ACP commands ───
|
|
8593
8781
|
case "launch_cli":
|
|
8594
8782
|
case "stop_cli":
|
|
8783
|
+
case "set_cli_view_mode":
|
|
8595
8784
|
case "agent_command": {
|
|
8596
8785
|
return this.deps.cliManager.handleCliCommand(cmd, args);
|
|
8597
8786
|
}
|
|
@@ -8936,6 +9125,20 @@ var DaemonStatusReporter = class {
|
|
|
8936
9125
|
ts() {
|
|
8937
9126
|
return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
|
|
8938
9127
|
}
|
|
9128
|
+
summarizeLargePayloadSessions(payload) {
|
|
9129
|
+
const sessions = Array.isArray(payload.sessions) ? payload.sessions : [];
|
|
9130
|
+
return sessions.map((session) => ({
|
|
9131
|
+
id: String(session?.id || ""),
|
|
9132
|
+
providerType: String(session?.providerType || ""),
|
|
9133
|
+
bytes: (() => {
|
|
9134
|
+
try {
|
|
9135
|
+
return JSON.stringify(session).length;
|
|
9136
|
+
} catch {
|
|
9137
|
+
return 0;
|
|
9138
|
+
}
|
|
9139
|
+
})()
|
|
9140
|
+
})).sort((a, b) => b.bytes - a.bytes).slice(0, 3).map((session) => `${session.providerType || "unknown"}:${session.id}=${session.bytes}b`).join(", ");
|
|
9141
|
+
}
|
|
8939
9142
|
async sendUnifiedStatusReport(opts) {
|
|
8940
9143
|
const { serverConn, p2p } = this.deps;
|
|
8941
9144
|
if (!serverConn?.isConnected()) return;
|
|
@@ -8988,9 +9191,16 @@ var DaemonStatusReporter = class {
|
|
|
8988
9191
|
screenshotUsage: this.deps.getScreenshotUsage?.() || null,
|
|
8989
9192
|
connectedExtensions: []
|
|
8990
9193
|
};
|
|
9194
|
+
const payloadBytes = JSON.stringify(payload).length;
|
|
8991
9195
|
const p2pSent = this.sendP2PPayload(payload);
|
|
8992
9196
|
if (p2pSent) {
|
|
8993
|
-
LOG.debug("P2P", `sent (${
|
|
9197
|
+
LOG.debug("P2P", `sent (${payloadBytes} bytes)`);
|
|
9198
|
+
if (payloadBytes > 256 * 1024) {
|
|
9199
|
+
LOG.warn(
|
|
9200
|
+
"P2P",
|
|
9201
|
+
`large status payload (${payloadBytes} bytes) top sessions: ${this.summarizeLargePayloadSessions(payload) || "n/a"}`
|
|
9202
|
+
);
|
|
9203
|
+
}
|
|
8994
9204
|
}
|
|
8995
9205
|
if (opts?.p2pOnly) return;
|
|
8996
9206
|
const wsPayload = {
|
|
@@ -9020,7 +9230,9 @@ var DaemonStatusReporter = class {
|
|
|
9020
9230
|
acpModes: session.acpModes
|
|
9021
9231
|
})),
|
|
9022
9232
|
p2p: payload.p2p,
|
|
9023
|
-
timestamp: now
|
|
9233
|
+
timestamp: now,
|
|
9234
|
+
detectedIdes: payload.detectedIdes,
|
|
9235
|
+
availableProviders: payload.availableProviders
|
|
9024
9236
|
};
|
|
9025
9237
|
serverConn.sendMessage("status_report", wsPayload);
|
|
9026
9238
|
LOG.debug("Server", `sent status_report (${JSON.stringify(wsPayload).length} bytes)`);
|
|
@@ -9072,6 +9284,7 @@ var CliProviderInstance = class {
|
|
|
9072
9284
|
this.cliArgs = cliArgs;
|
|
9073
9285
|
this.type = provider.type;
|
|
9074
9286
|
this.instanceId = instanceId || crypto3.randomUUID();
|
|
9287
|
+
this.presentationMode = "terminal";
|
|
9075
9288
|
this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, transportFactory);
|
|
9076
9289
|
this.monitor = new StatusMonitor();
|
|
9077
9290
|
this.historyWriter = new ChatHistoryWriter();
|
|
@@ -9090,6 +9303,7 @@ var CliProviderInstance = class {
|
|
|
9090
9303
|
lastApprovalEventAt = 0;
|
|
9091
9304
|
historyWriter;
|
|
9092
9305
|
instanceId;
|
|
9306
|
+
presentationMode;
|
|
9093
9307
|
// ─── Lifecycle ─────────────────────────────────
|
|
9094
9308
|
async init(context) {
|
|
9095
9309
|
this.context = context;
|
|
@@ -9114,6 +9328,7 @@ var CliProviderInstance = class {
|
|
|
9114
9328
|
}
|
|
9115
9329
|
getState() {
|
|
9116
9330
|
const adapterStatus = this.adapter.getStatus();
|
|
9331
|
+
const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
|
|
9117
9332
|
const runtime = this.adapter.getRuntimeMetadata();
|
|
9118
9333
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
9119
9334
|
if (adapterStatus.terminalHistory?.trim()) {
|
|
@@ -9129,13 +9344,13 @@ var CliProviderInstance = class {
|
|
|
9129
9344
|
name: this.provider.name,
|
|
9130
9345
|
category: "cli",
|
|
9131
9346
|
status: adapterStatus.status,
|
|
9132
|
-
mode:
|
|
9347
|
+
mode: this.presentationMode,
|
|
9133
9348
|
activeChat: {
|
|
9134
9349
|
id: `${this.type}_${this.workingDir}`,
|
|
9135
|
-
title: `${this.provider.name} \xB7 ${dirName}`,
|
|
9136
|
-
status: adapterStatus.status,
|
|
9137
|
-
messages: [],
|
|
9138
|
-
activeModal: adapterStatus.activeModal,
|
|
9350
|
+
title: parsedStatus?.title || `${this.provider.name} \xB7 ${dirName}`,
|
|
9351
|
+
status: parsedStatus?.status || adapterStatus.status,
|
|
9352
|
+
messages: Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [],
|
|
9353
|
+
activeModal: parsedStatus?.activeModal ?? adapterStatus.activeModal,
|
|
9139
9354
|
terminalHistory: adapterStatus.terminalHistory,
|
|
9140
9355
|
inputContent: ""
|
|
9141
9356
|
},
|
|
@@ -9158,6 +9373,13 @@ var CliProviderInstance = class {
|
|
|
9158
9373
|
providerControls: this.provider.controls
|
|
9159
9374
|
};
|
|
9160
9375
|
}
|
|
9376
|
+
setPresentationMode(mode) {
|
|
9377
|
+
if (this.presentationMode === mode) return;
|
|
9378
|
+
this.presentationMode = mode;
|
|
9379
|
+
}
|
|
9380
|
+
getPresentationMode() {
|
|
9381
|
+
return this.presentationMode;
|
|
9382
|
+
}
|
|
9161
9383
|
onEvent(event, data) {
|
|
9162
9384
|
if (event === "send_message" && data?.text) {
|
|
9163
9385
|
void this.adapter.sendMessage(data.text).catch((e) => {
|
|
@@ -10221,6 +10443,15 @@ var DaemonCliManager = class {
|
|
|
10221
10443
|
const hash = __require("crypto").createHash("md5").update(__require("path").resolve(dir)).digest("hex").slice(0, 8);
|
|
10222
10444
|
return `${cliType}_${hash}`;
|
|
10223
10445
|
}
|
|
10446
|
+
getSessionPresentationMode(sessionId) {
|
|
10447
|
+
if (!sessionId) return null;
|
|
10448
|
+
const instance = this.deps.getInstanceManager()?.getInstance(sessionId);
|
|
10449
|
+
const mode = instance?.category === "cli" ? instance.getPresentationMode?.() : null;
|
|
10450
|
+
return mode === "chat" || mode === "terminal" ? mode : null;
|
|
10451
|
+
}
|
|
10452
|
+
isTerminalSession(sessionId) {
|
|
10453
|
+
return this.getSessionPresentationMode(sessionId) === "terminal";
|
|
10454
|
+
}
|
|
10224
10455
|
persistRecentActivity(entry) {
|
|
10225
10456
|
try {
|
|
10226
10457
|
saveConfig(appendRecentActivity(loadConfig(), entry));
|
|
@@ -10399,6 +10630,7 @@ ${installInfo}`
|
|
|
10399
10630
|
if (provider) {
|
|
10400
10631
|
console.log(colorize("cyan", ` \u{1F4E6} Using provider: ${provider.name} (${provider.type})`));
|
|
10401
10632
|
}
|
|
10633
|
+
const resolvedCliArgs = cliArgs;
|
|
10402
10634
|
const instanceManager = this.deps.getInstanceManager();
|
|
10403
10635
|
if (provider && instanceManager) {
|
|
10404
10636
|
const resolvedProvider = this.providerLoader.resolve(cliType, { version: cliInfo.version }) || provider;
|
|
@@ -10407,14 +10639,14 @@ ${installInfo}`
|
|
|
10407
10639
|
normalizedType,
|
|
10408
10640
|
cliType,
|
|
10409
10641
|
resolvedDir,
|
|
10410
|
-
|
|
10642
|
+
resolvedCliArgs,
|
|
10411
10643
|
resolvedProvider,
|
|
10412
10644
|
{},
|
|
10413
10645
|
false
|
|
10414
10646
|
);
|
|
10415
10647
|
console.log(colorize("green", ` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${resolvedDir}`));
|
|
10416
10648
|
} else {
|
|
10417
|
-
const adapter = this.createAdapter(cliType, resolvedDir,
|
|
10649
|
+
const adapter = this.createAdapter(cliType, resolvedDir, resolvedCliArgs, key, false);
|
|
10418
10650
|
try {
|
|
10419
10651
|
await adapter.spawn();
|
|
10420
10652
|
} catch (spawnErr) {
|
|
@@ -10564,6 +10796,14 @@ ${installInfo}`
|
|
|
10564
10796
|
}
|
|
10565
10797
|
return null;
|
|
10566
10798
|
}
|
|
10799
|
+
findAdapterBySessionId(instanceKey) {
|
|
10800
|
+
if (!instanceKey) return null;
|
|
10801
|
+
let ik = instanceKey;
|
|
10802
|
+
const colonIdx = ik.lastIndexOf(":");
|
|
10803
|
+
if (colonIdx >= 0) ik = ik.substring(colonIdx + 1);
|
|
10804
|
+
const adapter = this.adapters.get(ik);
|
|
10805
|
+
return adapter ? { adapter, key: ik } : null;
|
|
10806
|
+
}
|
|
10567
10807
|
// ─── CLI command handling ────────────────────────────
|
|
10568
10808
|
async handleCliCommand(cmd, args) {
|
|
10569
10809
|
switch (cmd) {
|
|
@@ -10614,6 +10854,23 @@ ${installInfo}`
|
|
|
10614
10854
|
}
|
|
10615
10855
|
return { success: true, cliType, dir, stopped: true, mode };
|
|
10616
10856
|
}
|
|
10857
|
+
case "set_cli_view_mode": {
|
|
10858
|
+
const mode = args?.mode === "chat" ? "chat" : "terminal";
|
|
10859
|
+
const targetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId : "";
|
|
10860
|
+
const cliType = args?.cliType || args?.agentType || "";
|
|
10861
|
+
const dir = args?.dir || "";
|
|
10862
|
+
const found = this.findAdapterBySessionId(targetSessionId) || (cliType ? this.findAdapter(cliType, { instanceKey: targetSessionId, dir }) : null);
|
|
10863
|
+
if (!found) {
|
|
10864
|
+
return { success: false, error: "CLI session not found", code: "CLI_SESSION_NOT_FOUND" };
|
|
10865
|
+
}
|
|
10866
|
+
const instance = this.deps.getInstanceManager()?.getInstance(found.key);
|
|
10867
|
+
if (!(instance instanceof CliProviderInstance)) {
|
|
10868
|
+
return { success: false, error: "CLI instance not found", code: "CLI_INSTANCE_NOT_FOUND" };
|
|
10869
|
+
}
|
|
10870
|
+
instance.setPresentationMode(mode);
|
|
10871
|
+
this.deps.onStatusChange();
|
|
10872
|
+
return { success: true, id: found.key, mode };
|
|
10873
|
+
}
|
|
10617
10874
|
case "restart_session": {
|
|
10618
10875
|
const cliType = args?.cliType || args?.agentType || args?.ideType;
|
|
10619
10876
|
const cfg = loadConfig();
|
|
@@ -11232,7 +11489,12 @@ var AgentStreamPoller = class {
|
|
|
11232
11489
|
} catch {
|
|
11233
11490
|
}
|
|
11234
11491
|
}
|
|
11235
|
-
if (!resolvedActiveSessionId || !parentSessionId)
|
|
11492
|
+
if (!resolvedActiveSessionId || !parentSessionId) {
|
|
11493
|
+
if (parentSessionId) {
|
|
11494
|
+
this.deps.onStreamsUpdated?.(ideType, []);
|
|
11495
|
+
}
|
|
11496
|
+
continue;
|
|
11497
|
+
}
|
|
11236
11498
|
try {
|
|
11237
11499
|
await agentStreamManager.syncActiveSession(cdp, parentSessionId);
|
|
11238
11500
|
const stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
|
|
@@ -11247,7 +11509,11 @@ var AgentStreamPoller = class {
|
|
|
11247
11509
|
function forwardAgentStreamsToIdeInstance(instanceManager, ideType, streams) {
|
|
11248
11510
|
const ideInstance = instanceManager.getInstance(`ide:${ideType}`);
|
|
11249
11511
|
if (!ideInstance?.onEvent) return;
|
|
11512
|
+
const seenExtensionTypes = /* @__PURE__ */ new Set();
|
|
11250
11513
|
for (const stream of streams) {
|
|
11514
|
+
if (typeof stream.agentType === "string" && stream.agentType) {
|
|
11515
|
+
seenExtensionTypes.add(stream.agentType);
|
|
11516
|
+
}
|
|
11251
11517
|
ideInstance.onEvent("stream_update", {
|
|
11252
11518
|
extensionType: stream.agentType,
|
|
11253
11519
|
streams: [stream],
|
|
@@ -11264,6 +11530,16 @@ function forwardAgentStreamsToIdeInstance(instanceManager, ideType, streams) {
|
|
|
11264
11530
|
inputContent: stream.inputContent || ""
|
|
11265
11531
|
});
|
|
11266
11532
|
}
|
|
11533
|
+
const extensionTypes = ideInstance.getExtensionTypes?.() || [];
|
|
11534
|
+
if (streams.length === 0) {
|
|
11535
|
+
ideInstance.onEvent("stream_reset_all");
|
|
11536
|
+
return;
|
|
11537
|
+
}
|
|
11538
|
+
for (const extensionType of extensionTypes) {
|
|
11539
|
+
if (!seenExtensionTypes.has(extensionType)) {
|
|
11540
|
+
ideInstance.onEvent("stream_reset", { extensionType });
|
|
11541
|
+
}
|
|
11542
|
+
}
|
|
11267
11543
|
}
|
|
11268
11544
|
|
|
11269
11545
|
// src/providers/provider-instance-manager.ts
|