@adhdev/daemon-core 0.8.73 → 0.8.74
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-shared.d.ts +2 -0
- package/dist/commands/stream-commands.d.ts +1 -1
- package/dist/config/chat-history.d.ts +5 -4
- package/dist/index.js +239 -111
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +239 -111
- package/dist/index.mjs.map +1 -1
- package/dist/providers/contracts.d.ts +2 -0
- package/node_modules/@adhdev/session-host-core/package.json +2 -2
- package/package.json +2 -2
- package/src/cli-adapters/provider-cli-adapter.ts +8 -2
- package/src/cli-adapters/provider-cli-shared.d.ts +2 -0
- package/src/cli-adapters/provider-cli-shared.ts +2 -0
- package/src/commands/chat-commands.ts +79 -3
- package/src/commands/stream-commands.ts +47 -26
- package/src/config/chat-history.d.ts +5 -4
- package/src/config/chat-history.ts +125 -74
- package/src/daemon/dev-server.ts +15 -1
- package/src/providers/approval-utils.ts +7 -6
- package/src/providers/contracts.d.ts +2 -0
- package/src/providers/contracts.ts +2 -0
|
@@ -106,6 +106,8 @@ export interface CliProviderModule {
|
|
|
106
106
|
sendDelayMs?: number;
|
|
107
107
|
sendKey?: string;
|
|
108
108
|
submitStrategy?: 'wait_for_echo' | 'immediate';
|
|
109
|
+
/** Allow sending another prompt while the CLI is still generating so users can intervene mid-turn. */
|
|
110
|
+
allowInputDuringGeneration?: boolean;
|
|
109
111
|
scripts?: CliScripts;
|
|
110
112
|
spawn: {
|
|
111
113
|
command: string;
|
|
@@ -6,7 +6,7 @@ import type { CommandResult, CommandHelpers } from './handler.js';
|
|
|
6
6
|
export declare function handleSelectSession(h: CommandHelpers, args: any): Promise<CommandResult>;
|
|
7
7
|
export declare function handleOpenPanel(h: CommandHelpers, args: any): Promise<CommandResult>;
|
|
8
8
|
export declare function handlePtyInput(h: CommandHelpers, args: any): CommandResult;
|
|
9
|
-
export declare function handlePtyResize(
|
|
9
|
+
export declare function handlePtyResize(_h: CommandHelpers, args: any): CommandResult;
|
|
10
10
|
export declare function handleGetProviderSettings(h: CommandHelpers, args: any): CommandResult;
|
|
11
11
|
export declare function handleSetProviderSetting(h: CommandHelpers, args: any): Promise<CommandResult>;
|
|
12
12
|
export declare function handleGetProviderSourceConfig(h: CommandHelpers, _args: any): CommandResult;
|
|
@@ -84,11 +84,12 @@ export declare class ChatHistoryWriter {
|
|
|
84
84
|
/**
|
|
85
85
|
* Read history (static — called from P2P commands)
|
|
86
86
|
*
|
|
87
|
-
* Read JSONL files
|
|
88
|
-
*
|
|
89
|
-
*
|
|
87
|
+
* Read JSONL files for a session and return a chronological page while paging
|
|
88
|
+
* backwards from the newest saved messages. When excludeRecentCount is set,
|
|
89
|
+
* the newest N messages are skipped so older-history pagination can avoid
|
|
90
|
+
* duplicating the live transcript tail already shown in the UI.
|
|
90
91
|
*/
|
|
91
|
-
export declare function readChatHistory(agentType: string, offset?: number, limit?: number, historySessionId?: string): {
|
|
92
|
+
export declare function readChatHistory(agentType: string, offset?: number, limit?: number, historySessionId?: string, excludeRecentCount?: number): {
|
|
92
93
|
messages: HistoryMessage[];
|
|
93
94
|
hasMore: boolean;
|
|
94
95
|
};
|
package/dist/index.js
CHANGED
|
@@ -3006,6 +3006,8 @@ ${data.message || ""}`.trim();
|
|
|
3006
3006
|
}
|
|
3007
3007
|
async sendMessage(text) {
|
|
3008
3008
|
if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
|
|
3009
|
+
const allowInputDuringGeneration = this.provider.allowInputDuringGeneration === true;
|
|
3010
|
+
const allowInterventionPrompt = allowInputDuringGeneration && this.isWaitingForResponse && this.currentStatus !== "waiting_approval";
|
|
3009
3011
|
if (this.startupParseGate) {
|
|
3010
3012
|
const deadline = Date.now() + 1e4;
|
|
3011
3013
|
while (this.startupParseGate && Date.now() < deadline) {
|
|
@@ -3013,7 +3015,9 @@ ${data.message || ""}`.trim();
|
|
|
3013
3015
|
await new Promise((resolve11) => setTimeout(resolve11, 50));
|
|
3014
3016
|
}
|
|
3015
3017
|
}
|
|
3016
|
-
|
|
3018
|
+
if (!allowInterventionPrompt) {
|
|
3019
|
+
await this.waitForInteractivePrompt();
|
|
3020
|
+
}
|
|
3017
3021
|
if (!this.ready) {
|
|
3018
3022
|
this.resolveStartupState("send_precheck");
|
|
3019
3023
|
const screenText = this.terminalScreen.getText() || "";
|
|
@@ -3025,7 +3029,7 @@ ${data.message || ""}`.trim();
|
|
|
3025
3029
|
}
|
|
3026
3030
|
}
|
|
3027
3031
|
if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
|
|
3028
|
-
if (this.isWaitingForResponse) {
|
|
3032
|
+
if (this.isWaitingForResponse && !allowInputDuringGeneration) {
|
|
3029
3033
|
throw new Error(`${this.cliName} is still processing the previous prompt`);
|
|
3030
3034
|
}
|
|
3031
3035
|
const blockingModal = this.activeModal || this.getStartupConfirmationModal(this.terminalScreen.getText() || "");
|
|
@@ -6058,6 +6062,7 @@ var os5 = __toESM(require("os"));
|
|
|
6058
6062
|
init_chat_message_normalization();
|
|
6059
6063
|
var HISTORY_DIR = path7.join(os5.homedir(), ".adhdev", "history");
|
|
6060
6064
|
var RETAIN_DAYS = 30;
|
|
6065
|
+
var savedHistorySessionCache = /* @__PURE__ */ new Map();
|
|
6061
6066
|
var CODEX_STARTER_PROMPT_RE = /^(?:[›❯]\s*)?(?:Find and fix a bug in @filename|Improve documentation in @filename|Write tests for @filename|Explain this codebase|Summarize recent commits|Implement \{feature\}|Use \/skills(?: to list available skills)?|Run \/review on my current changes)$/i;
|
|
6062
6067
|
function normalizeHistoryComparable(text) {
|
|
6063
6068
|
return String(text || "").replace(/\s+/g, " ").trim();
|
|
@@ -6115,6 +6120,85 @@ function sanitizeHistoryMessage(agentType, message) {
|
|
|
6115
6120
|
content
|
|
6116
6121
|
};
|
|
6117
6122
|
}
|
|
6123
|
+
function sanitizeHistoryFileSegment(value) {
|
|
6124
|
+
return String(value || "").replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
6125
|
+
}
|
|
6126
|
+
function listHistoryFiles(dir, historySessionId) {
|
|
6127
|
+
const sanitizedSessionId = historySessionId ? sanitizeHistoryFileSegment(historySessionId) : "";
|
|
6128
|
+
return fs3.readdirSync(dir).filter((file) => {
|
|
6129
|
+
if (!file.endsWith(".jsonl")) return false;
|
|
6130
|
+
if (sanitizedSessionId) {
|
|
6131
|
+
return file.startsWith(`${sanitizedSessionId}_`);
|
|
6132
|
+
}
|
|
6133
|
+
return true;
|
|
6134
|
+
}).sort().reverse();
|
|
6135
|
+
}
|
|
6136
|
+
function buildSavedHistoryCacheSignature(dir, files) {
|
|
6137
|
+
return files.map((file) => {
|
|
6138
|
+
try {
|
|
6139
|
+
const stat = fs3.statSync(path7.join(dir, file));
|
|
6140
|
+
return `${file}:${stat.size}:${Math.trunc(stat.mtimeMs)}`;
|
|
6141
|
+
} catch {
|
|
6142
|
+
return `${file}:missing`;
|
|
6143
|
+
}
|
|
6144
|
+
}).join("|");
|
|
6145
|
+
}
|
|
6146
|
+
function computeSavedHistorySessionSummaries(agentType, dir, files) {
|
|
6147
|
+
const groupedFiles = /* @__PURE__ */ new Map();
|
|
6148
|
+
const filePattern = /^([A-Za-z0-9_-]+)_\d{4}-\d{2}-\d{2}\.jsonl$/;
|
|
6149
|
+
for (const file of files) {
|
|
6150
|
+
const match = file.match(filePattern);
|
|
6151
|
+
if (!match?.[1]) continue;
|
|
6152
|
+
const historySessionId = match[1];
|
|
6153
|
+
const grouped = groupedFiles.get(historySessionId) || [];
|
|
6154
|
+
grouped.push(file);
|
|
6155
|
+
groupedFiles.set(historySessionId, grouped);
|
|
6156
|
+
}
|
|
6157
|
+
const summaries = [];
|
|
6158
|
+
for (const [historySessionId, grouped] of groupedFiles.entries()) {
|
|
6159
|
+
let messageCount = 0;
|
|
6160
|
+
let firstMessageAt = 0;
|
|
6161
|
+
let lastMessageAt = 0;
|
|
6162
|
+
let sessionTitle = "";
|
|
6163
|
+
let preview = "";
|
|
6164
|
+
let workspace = "";
|
|
6165
|
+
for (const file of grouped.sort()) {
|
|
6166
|
+
const filePath = path7.join(dir, file);
|
|
6167
|
+
const content = fs3.readFileSync(filePath, "utf-8");
|
|
6168
|
+
const lines = content.split("\n").filter(Boolean);
|
|
6169
|
+
for (const line of lines) {
|
|
6170
|
+
let parsed = null;
|
|
6171
|
+
try {
|
|
6172
|
+
parsed = JSON.parse(line);
|
|
6173
|
+
} catch {
|
|
6174
|
+
parsed = null;
|
|
6175
|
+
}
|
|
6176
|
+
if (!parsed || parsed.historySessionId !== historySessionId) continue;
|
|
6177
|
+
if (parsed.kind === "session_start") {
|
|
6178
|
+
if (!workspace && parsed.workspace) workspace = parsed.workspace;
|
|
6179
|
+
continue;
|
|
6180
|
+
}
|
|
6181
|
+
messageCount += 1;
|
|
6182
|
+
if (!firstMessageAt || parsed.receivedAt < firstMessageAt) firstMessageAt = parsed.receivedAt;
|
|
6183
|
+
if (!lastMessageAt || parsed.receivedAt > lastMessageAt) lastMessageAt = parsed.receivedAt;
|
|
6184
|
+
if (parsed.sessionTitle) sessionTitle = parsed.sessionTitle;
|
|
6185
|
+
if (parsed.role !== "system" && parsed.content.trim()) preview = parsed.content.trim();
|
|
6186
|
+
}
|
|
6187
|
+
}
|
|
6188
|
+
if (messageCount === 0 || !lastMessageAt) continue;
|
|
6189
|
+
summaries.push({
|
|
6190
|
+
historySessionId,
|
|
6191
|
+
sessionTitle: sessionTitle || void 0,
|
|
6192
|
+
messageCount,
|
|
6193
|
+
firstMessageAt,
|
|
6194
|
+
lastMessageAt,
|
|
6195
|
+
preview: preview || void 0,
|
|
6196
|
+
workspace: workspace || void 0
|
|
6197
|
+
});
|
|
6198
|
+
}
|
|
6199
|
+
summaries.sort((a, b) => b.lastMessageAt - a.lastMessageAt);
|
|
6200
|
+
return summaries;
|
|
6201
|
+
}
|
|
6118
6202
|
var ChatHistoryWriter = class {
|
|
6119
6203
|
/** Last seen message count per agent (deduplication) */
|
|
6120
6204
|
lastSeenCounts = /* @__PURE__ */ new Map();
|
|
@@ -6443,19 +6527,12 @@ var ChatHistoryWriter = class {
|
|
|
6443
6527
|
return name.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
6444
6528
|
}
|
|
6445
6529
|
};
|
|
6446
|
-
function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
|
|
6530
|
+
function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0) {
|
|
6447
6531
|
try {
|
|
6448
6532
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
6449
6533
|
const dir = path7.join(HISTORY_DIR, sanitized);
|
|
6450
6534
|
if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
|
|
6451
|
-
const
|
|
6452
|
-
const files = fs3.readdirSync(dir).filter((f) => {
|
|
6453
|
-
if (!f.endsWith(".jsonl")) return false;
|
|
6454
|
-
if (sanitizedInstance) {
|
|
6455
|
-
return f.startsWith(`${sanitizedInstance}_`);
|
|
6456
|
-
}
|
|
6457
|
-
return true;
|
|
6458
|
-
}).sort().reverse();
|
|
6535
|
+
const files = listHistoryFiles(dir, historySessionId);
|
|
6459
6536
|
const allMessages = [];
|
|
6460
6537
|
const seen = /* @__PURE__ */ new Set();
|
|
6461
6538
|
for (const file of files) {
|
|
@@ -6486,8 +6563,13 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
|
|
|
6486
6563
|
if (message.role !== "system") lastTurn = message;
|
|
6487
6564
|
}
|
|
6488
6565
|
const collapsed = collapseReplayAssistantTurns(agentType, chronological);
|
|
6489
|
-
const
|
|
6490
|
-
const
|
|
6566
|
+
const boundedLimit = Math.max(1, limit);
|
|
6567
|
+
const boundedOffset = Math.max(0, offset);
|
|
6568
|
+
const boundedExclude = Math.max(0, Math.min(excludeRecentCount, collapsed.length));
|
|
6569
|
+
const endExclusive = Math.max(0, collapsed.length - boundedExclude - boundedOffset);
|
|
6570
|
+
const startInclusive = Math.max(0, endExclusive - boundedLimit);
|
|
6571
|
+
const sliced = collapsed.slice(startInclusive, endExclusive);
|
|
6572
|
+
const hasMore = startInclusive > 0;
|
|
6491
6573
|
return { messages: sliced, hasMore };
|
|
6492
6574
|
} catch {
|
|
6493
6575
|
return { messages: [], hasMore: false };
|
|
@@ -6497,61 +6579,20 @@ function listSavedHistorySessions(agentType, options = {}) {
|
|
|
6497
6579
|
try {
|
|
6498
6580
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
6499
6581
|
const dir = path7.join(HISTORY_DIR, sanitized);
|
|
6500
|
-
if (!fs3.existsSync(dir))
|
|
6501
|
-
|
|
6502
|
-
|
|
6503
|
-
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
const summaries = [];
|
|
6513
|
-
for (const [historySessionId, files] of groupedFiles.entries()) {
|
|
6514
|
-
let messageCount = 0;
|
|
6515
|
-
let firstMessageAt = 0;
|
|
6516
|
-
let lastMessageAt = 0;
|
|
6517
|
-
let sessionTitle = "";
|
|
6518
|
-
let preview = "";
|
|
6519
|
-
let workspace = "";
|
|
6520
|
-
for (const file of files.sort()) {
|
|
6521
|
-
const filePath = path7.join(dir, file);
|
|
6522
|
-
const content = fs3.readFileSync(filePath, "utf-8");
|
|
6523
|
-
const lines = content.split("\n").filter(Boolean);
|
|
6524
|
-
for (const line of lines) {
|
|
6525
|
-
let parsed = null;
|
|
6526
|
-
try {
|
|
6527
|
-
parsed = JSON.parse(line);
|
|
6528
|
-
} catch {
|
|
6529
|
-
parsed = null;
|
|
6530
|
-
}
|
|
6531
|
-
if (!parsed || parsed.historySessionId !== historySessionId) continue;
|
|
6532
|
-
if (parsed.kind === "session_start") {
|
|
6533
|
-
if (!workspace && parsed.workspace) workspace = parsed.workspace;
|
|
6534
|
-
continue;
|
|
6535
|
-
}
|
|
6536
|
-
messageCount += 1;
|
|
6537
|
-
if (!firstMessageAt || parsed.receivedAt < firstMessageAt) firstMessageAt = parsed.receivedAt;
|
|
6538
|
-
if (!lastMessageAt || parsed.receivedAt > lastMessageAt) lastMessageAt = parsed.receivedAt;
|
|
6539
|
-
if (parsed.sessionTitle) sessionTitle = parsed.sessionTitle;
|
|
6540
|
-
if (parsed.role !== "system" && parsed.content.trim()) preview = parsed.content.trim();
|
|
6541
|
-
}
|
|
6542
|
-
}
|
|
6543
|
-
if (messageCount === 0 || !lastMessageAt) continue;
|
|
6544
|
-
summaries.push({
|
|
6545
|
-
historySessionId,
|
|
6546
|
-
sessionTitle: sessionTitle || void 0,
|
|
6547
|
-
messageCount,
|
|
6548
|
-
firstMessageAt,
|
|
6549
|
-
lastMessageAt,
|
|
6550
|
-
preview: preview || void 0,
|
|
6551
|
-
workspace: workspace || void 0
|
|
6582
|
+
if (!fs3.existsSync(dir)) {
|
|
6583
|
+
savedHistorySessionCache.delete(sanitized);
|
|
6584
|
+
return { sessions: [], hasMore: false };
|
|
6585
|
+
}
|
|
6586
|
+
const files = listHistoryFiles(dir);
|
|
6587
|
+
const signature = buildSavedHistoryCacheSignature(dir, files);
|
|
6588
|
+
const cached = savedHistorySessionCache.get(sanitized);
|
|
6589
|
+
const summaries = cached?.signature === signature ? cached.summaries : computeSavedHistorySessionSummaries(agentType, dir, files);
|
|
6590
|
+
if (!cached || cached.signature !== signature) {
|
|
6591
|
+
savedHistorySessionCache.set(sanitized, {
|
|
6592
|
+
signature,
|
|
6593
|
+
summaries
|
|
6552
6594
|
});
|
|
6553
6595
|
}
|
|
6554
|
-
summaries.sort((a, b) => b.lastMessageAt - a.lastMessageAt);
|
|
6555
6596
|
const offset = Math.max(0, options.offset || 0);
|
|
6556
6597
|
const limit = Math.max(1, options.limit || 30);
|
|
6557
6598
|
const sliced = summaries.slice(offset, offset + limit);
|
|
@@ -7052,22 +7093,22 @@ init_read_chat_contract();
|
|
|
7052
7093
|
|
|
7053
7094
|
// src/providers/approval-utils.ts
|
|
7054
7095
|
var DEFAULT_APPROVAL_POSITIVE_HINTS = [
|
|
7055
|
-
"
|
|
7096
|
+
"yes",
|
|
7097
|
+
"allow once",
|
|
7056
7098
|
"approve",
|
|
7057
7099
|
"accept",
|
|
7058
|
-
"allow once",
|
|
7059
|
-
"always allow",
|
|
7060
|
-
"allow",
|
|
7061
|
-
"yes",
|
|
7062
|
-
"proceed",
|
|
7063
7100
|
"continue",
|
|
7101
|
+
"run",
|
|
7102
|
+
"proceed",
|
|
7064
7103
|
"confirm",
|
|
7065
7104
|
"save",
|
|
7066
7105
|
"ok",
|
|
7067
|
-
"trust"
|
|
7106
|
+
"trust",
|
|
7107
|
+
"allow",
|
|
7108
|
+
"always allow"
|
|
7068
7109
|
];
|
|
7069
7110
|
function normalizeApprovalLabel(value) {
|
|
7070
|
-
return String(value || "").toLowerCase().replace(/[^\p{L}\p{N}]+/gu, " ").trim();
|
|
7111
|
+
return String(value || "").toLowerCase().replace(/^[\s\[(<{]*\d+(?:\s*[.)\]}>:-]|\s)+/, "").replace(/[^\p{L}\p{N}]+/gu, " ").trim();
|
|
7071
7112
|
}
|
|
7072
7113
|
function getApprovalPositiveHints(provider) {
|
|
7073
7114
|
const customHints = Array.isArray(provider?.approvalPositiveHints) ? provider.approvalPositiveHints.map((hint) => normalizeApprovalLabel(String(hint || ""))).filter(Boolean) : [];
|
|
@@ -8845,6 +8886,41 @@ function normalizeReadChatMessages(payload) {
|
|
|
8845
8886
|
const messages = Array.isArray(payload.messages) ? payload.messages : [];
|
|
8846
8887
|
return normalizeChatMessages(messages);
|
|
8847
8888
|
}
|
|
8889
|
+
function buildReadChatReplayCollapseSignature(message) {
|
|
8890
|
+
if (!message) return "";
|
|
8891
|
+
const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
|
|
8892
|
+
const kind = typeof message.kind === "string" ? message.kind.trim().toLowerCase() : "standard";
|
|
8893
|
+
const senderName = typeof message.senderName === "string" ? message.senderName.trim().toLowerCase() : "";
|
|
8894
|
+
const content = flattenContent(message.content || "").replace(/\s+/g, " ").trim();
|
|
8895
|
+
return `${role}:${kind}:${senderName}:${content}`;
|
|
8896
|
+
}
|
|
8897
|
+
function shouldCollapseReadChatReplayDuplicate(message) {
|
|
8898
|
+
if (!message) return false;
|
|
8899
|
+
const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
|
|
8900
|
+
if (role !== "assistant" && role !== "system") return false;
|
|
8901
|
+
const kind = typeof message.kind === "string" ? message.kind.trim().toLowerCase() : "standard";
|
|
8902
|
+
return kind === "tool" || kind === "terminal" || kind === "thought" || kind === "system";
|
|
8903
|
+
}
|
|
8904
|
+
function collapseReplayDuplicatesFromReadChat(messages) {
|
|
8905
|
+
const collapsed = [];
|
|
8906
|
+
let lastReplayTurnSignature = "";
|
|
8907
|
+
for (const message of messages) {
|
|
8908
|
+
const signature = buildReadChatReplayCollapseSignature(message);
|
|
8909
|
+
const previous = collapsed[collapsed.length - 1];
|
|
8910
|
+
const previousSignature = buildReadChatReplayCollapseSignature(previous);
|
|
8911
|
+
if (shouldCollapseReadChatReplayDuplicate(message) && signature) {
|
|
8912
|
+
if (previousSignature === signature) continue;
|
|
8913
|
+
if (lastReplayTurnSignature === signature) continue;
|
|
8914
|
+
}
|
|
8915
|
+
collapsed.push(message);
|
|
8916
|
+
if (shouldCollapseReadChatReplayDuplicate(message) && signature) {
|
|
8917
|
+
lastReplayTurnSignature = signature;
|
|
8918
|
+
} else if ((message.role || "").toLowerCase() === "user") {
|
|
8919
|
+
lastReplayTurnSignature = "";
|
|
8920
|
+
}
|
|
8921
|
+
}
|
|
8922
|
+
return collapsed;
|
|
8923
|
+
}
|
|
8848
8924
|
function deriveHistoryDedupKey(message) {
|
|
8849
8925
|
const unitKey = typeof message._unitKey === "string" ? message._unitKey.trim() : "";
|
|
8850
8926
|
if (unitKey) return `read_chat:${unitKey}`;
|
|
@@ -8920,14 +8996,38 @@ function computeReadChatSync(messages, cursor) {
|
|
|
8920
8996
|
lastMessageSignature
|
|
8921
8997
|
};
|
|
8922
8998
|
}
|
|
8999
|
+
function hasNonEmptyModalButtons(activeModal) {
|
|
9000
|
+
if (!activeModal || typeof activeModal !== "object") return false;
|
|
9001
|
+
const buttons = activeModal.buttons;
|
|
9002
|
+
return Array.isArray(buttons) && buttons.some((button) => typeof button === "string" && button.trim().length > 0);
|
|
9003
|
+
}
|
|
9004
|
+
function normalizeReadChatCommandStatus(status, activeModal) {
|
|
9005
|
+
const raw = typeof status === "string" ? status.trim() : "";
|
|
9006
|
+
if (!raw) {
|
|
9007
|
+
return hasNonEmptyModalButtons(activeModal) ? "waiting_approval" : "idle";
|
|
9008
|
+
}
|
|
9009
|
+
switch (raw) {
|
|
9010
|
+
case "starting":
|
|
9011
|
+
return hasNonEmptyModalButtons(activeModal) ? "waiting_approval" : "generating";
|
|
9012
|
+
case "stopped":
|
|
9013
|
+
case "disconnected":
|
|
9014
|
+
case "not_monitored":
|
|
9015
|
+
return "error";
|
|
9016
|
+
default:
|
|
9017
|
+
return raw;
|
|
9018
|
+
}
|
|
9019
|
+
}
|
|
8923
9020
|
function buildReadChatCommandResult(payload, args) {
|
|
8924
9021
|
let validatedPayload;
|
|
8925
9022
|
try {
|
|
8926
|
-
validatedPayload = validateReadChatResultPayload(
|
|
9023
|
+
validatedPayload = validateReadChatResultPayload({
|
|
9024
|
+
...payload,
|
|
9025
|
+
status: normalizeReadChatCommandStatus(payload?.status, payload?.activeModal)
|
|
9026
|
+
}, "read_chat command result");
|
|
8927
9027
|
} catch (error) {
|
|
8928
9028
|
return { success: false, error: error?.message || String(error) };
|
|
8929
9029
|
}
|
|
8930
|
-
const messages = normalizeReadChatMessages(validatedPayload);
|
|
9030
|
+
const messages = collapseReplayDuplicatesFromReadChat(normalizeReadChatMessages(validatedPayload));
|
|
8931
9031
|
const cursor = normalizeReadChatCursor(args);
|
|
8932
9032
|
if (!cursor.knownMessageCount && !cursor.lastMessageSignature && cursor.tailLimit > 0 && messages.length > cursor.tailLimit) {
|
|
8933
9033
|
const tailMessages = messages.slice(-cursor.tailLimit);
|
|
@@ -9009,7 +9109,15 @@ async function handleChatHistory(h, args) {
|
|
|
9009
9109
|
try {
|
|
9010
9110
|
const provider = h.getProvider(agentType);
|
|
9011
9111
|
const agentStr = provider?.type || agentType || getCurrentProviderType(h);
|
|
9012
|
-
const
|
|
9112
|
+
const transport = getTargetTransport(h, provider);
|
|
9113
|
+
let excludeRecentCount = Math.max(0, Number(args?.excludeRecentCount || 0));
|
|
9114
|
+
if (isCliLikeTransport(transport)) {
|
|
9115
|
+
const adapter = getTargetedCliAdapter(h, args, provider?.type);
|
|
9116
|
+
const status = adapter?.getStatus?.();
|
|
9117
|
+
const visibleCount = Array.isArray(status?.messages) ? status.messages.length : 0;
|
|
9118
|
+
if (visibleCount > excludeRecentCount) excludeRecentCount = visibleCount;
|
|
9119
|
+
}
|
|
9120
|
+
const result = readChatHistory(agentStr, offset || 0, limit || 30, historySessionId, excludeRecentCount);
|
|
9013
9121
|
return { success: true, ...result, agent: agentStr };
|
|
9014
9122
|
} catch (e) {
|
|
9015
9123
|
return { success: false, error: e.message };
|
|
@@ -10269,13 +10377,6 @@ function getCliScriptCommand(payload) {
|
|
|
10269
10377
|
|
|
10270
10378
|
// src/commands/stream-commands.ts
|
|
10271
10379
|
init_logger();
|
|
10272
|
-
function getCliPresentationMode(h, targetSessionId) {
|
|
10273
|
-
if (!targetSessionId) return null;
|
|
10274
|
-
const instance = h.ctx.instanceManager?.getInstance(targetSessionId);
|
|
10275
|
-
if (instance?.category !== "cli") return null;
|
|
10276
|
-
const mode = instance.getPresentationMode?.();
|
|
10277
|
-
return mode === "chat" || mode === "terminal" ? mode : null;
|
|
10278
|
-
}
|
|
10279
10380
|
function normalizeOpenPanelCommandResult(result) {
|
|
10280
10381
|
const payload = Object.prototype.hasOwnProperty.call(result, "result") ? result.result : result;
|
|
10281
10382
|
if (payload === true) return { opened: true, visible: true, focused: false };
|
|
@@ -10348,9 +10449,6 @@ async function handleOpenPanel(h, args) {
|
|
|
10348
10449
|
function handlePtyInput(h, args) {
|
|
10349
10450
|
const { cliType, data, targetSessionId } = args || {};
|
|
10350
10451
|
if (!data) return { success: false, error: "data required" };
|
|
10351
|
-
if (getCliPresentationMode(h, targetSessionId) === "chat") {
|
|
10352
|
-
return { success: false, error: "CLI session is in chat mode", code: "CLI_VIEW_MODE_NOT_TERMINAL" };
|
|
10353
|
-
}
|
|
10354
10452
|
const adapter = h.getCliAdapter(targetSessionId || cliType);
|
|
10355
10453
|
if (!adapter || typeof adapter.writeRaw !== "function") {
|
|
10356
10454
|
return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
|
|
@@ -10358,24 +10456,10 @@ function handlePtyInput(h, args) {
|
|
|
10358
10456
|
adapter.writeRaw(data);
|
|
10359
10457
|
return { success: true };
|
|
10360
10458
|
}
|
|
10361
|
-
function handlePtyResize(
|
|
10362
|
-
const {
|
|
10459
|
+
function handlePtyResize(_h, args) {
|
|
10460
|
+
const { cols, rows } = args || {};
|
|
10363
10461
|
if (!cols || !rows) return { success: false, error: "cols and rows required" };
|
|
10364
|
-
|
|
10365
|
-
return { success: false, error: "CLI session is in chat mode", code: "CLI_VIEW_MODE_NOT_TERMINAL" };
|
|
10366
|
-
}
|
|
10367
|
-
const adapter = h.getCliAdapter(targetSessionId || cliType);
|
|
10368
|
-
if (!adapter || typeof adapter.resize !== "function") {
|
|
10369
|
-
return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
|
|
10370
|
-
}
|
|
10371
|
-
const resize = adapter.resize;
|
|
10372
|
-
if (force) {
|
|
10373
|
-
resize(cols - 1, rows);
|
|
10374
|
-
setTimeout(() => resize(cols, rows), 50);
|
|
10375
|
-
} else {
|
|
10376
|
-
resize(cols, rows);
|
|
10377
|
-
}
|
|
10378
|
-
return { success: true };
|
|
10462
|
+
return { success: false, error: "PTY resize temporarily disabled", code: "PTY_RESIZE_DISABLED" };
|
|
10379
10463
|
}
|
|
10380
10464
|
function handleGetProviderSettings(h, args) {
|
|
10381
10465
|
const loader = h.ctx.providerLoader;
|
|
@@ -10462,15 +10546,45 @@ function normalizeProviderScriptArgs(args, scriptName) {
|
|
|
10462
10546
|
}
|
|
10463
10547
|
function buildControlScriptResult(scriptName, payload) {
|
|
10464
10548
|
if (!payload || typeof payload !== "object") return {};
|
|
10465
|
-
|
|
10466
|
-
|
|
10549
|
+
const legacyListPayload = (() => {
|
|
10550
|
+
if (Array.isArray(payload.options)) return payload;
|
|
10551
|
+
if (/^listmodels$/i.test(scriptName) && Array.isArray(payload.models)) {
|
|
10552
|
+
return {
|
|
10553
|
+
options: payload.models,
|
|
10554
|
+
currentValue: payload.currentValue ?? payload.current ?? payload.currentModel,
|
|
10555
|
+
...typeof payload.error === "string" ? { error: payload.error } : {}
|
|
10556
|
+
};
|
|
10557
|
+
}
|
|
10558
|
+
if (/^listmodes$/i.test(scriptName) && Array.isArray(payload.modes)) {
|
|
10559
|
+
return {
|
|
10560
|
+
options: payload.modes,
|
|
10561
|
+
currentValue: payload.currentValue ?? payload.current ?? payload.currentMode ?? payload.mode,
|
|
10562
|
+
...typeof payload.error === "string" ? { error: payload.error } : {}
|
|
10563
|
+
};
|
|
10564
|
+
}
|
|
10565
|
+
return null;
|
|
10566
|
+
})();
|
|
10567
|
+
if (legacyListPayload) {
|
|
10568
|
+
return { controlResult: normalizeControlListResult(legacyListPayload) };
|
|
10467
10569
|
}
|
|
10468
|
-
const
|
|
10570
|
+
const legacyMutationPayload = (() => {
|
|
10571
|
+
if (typeof payload.ok === "boolean") return payload;
|
|
10572
|
+
if (typeof payload.success === "boolean") {
|
|
10573
|
+
return {
|
|
10574
|
+
ok: payload.success,
|
|
10575
|
+
currentValue: payload.currentValue ?? payload.value ?? payload.model ?? payload.mode ?? payload.selectedModel ?? payload.selectedMode,
|
|
10576
|
+
...Array.isArray(payload.effects) ? { effects: payload.effects } : {},
|
|
10577
|
+
...typeof payload.error === "string" ? { error: payload.error } : {}
|
|
10578
|
+
};
|
|
10579
|
+
}
|
|
10580
|
+
return null;
|
|
10581
|
+
})();
|
|
10582
|
+
const looksLikeValueMutation = /^set|^change/i.test(scriptName) || payload.currentValue !== void 0 || payload.value !== void 0 || payload.success !== void 0;
|
|
10469
10583
|
if (looksLikeValueMutation) {
|
|
10470
|
-
return { controlResult: normalizeControlSetResult(payload) };
|
|
10584
|
+
return { controlResult: normalizeControlSetResult(legacyMutationPayload || payload) };
|
|
10471
10585
|
}
|
|
10472
10586
|
if (payload.ok !== void 0 || Array.isArray(payload.effects) || typeof payload.error === "string") {
|
|
10473
|
-
return { controlResult: normalizeControlInvokeResult(payload) };
|
|
10587
|
+
return { controlResult: normalizeControlInvokeResult(legacyMutationPayload || payload) };
|
|
10474
10588
|
}
|
|
10475
10589
|
return {};
|
|
10476
10590
|
}
|
|
@@ -10545,7 +10659,7 @@ async function executeProviderScript(h, args, scriptName) {
|
|
|
10545
10659
|
}
|
|
10546
10660
|
const managed = runtimeSessionId ? h.agentStream?.getManagedSession(runtimeSessionId) : null;
|
|
10547
10661
|
const targetSessionId = managed?.cdpSessionId || null;
|
|
10548
|
-
const IDE_LEVEL_SCRIPTS = provider.type === "claude-code-vscode" ? ["listModes", "setMode"] : ["listModes", "setMode", "listModels", "setModel"];
|
|
10662
|
+
const IDE_LEVEL_SCRIPTS = provider.type === "claude-code-vscode" ? ["listModes", "setMode", "listModels", "setModel", "setModelGui"] : ["listModes", "setMode", "listModels", "setModel"];
|
|
10549
10663
|
if (IDE_LEVEL_SCRIPTS.includes(scriptName)) {
|
|
10550
10664
|
if (targetSessionId) {
|
|
10551
10665
|
try {
|
|
@@ -22765,6 +22879,20 @@ var DevServer = class _DevServer {
|
|
|
22765
22879
|
async handleReload(_req, res) {
|
|
22766
22880
|
try {
|
|
22767
22881
|
this.providerLoader.reload();
|
|
22882
|
+
let refreshedInstances = 0;
|
|
22883
|
+
if (this.instanceManager) {
|
|
22884
|
+
for (const id of this.instanceManager.listInstanceIds()) {
|
|
22885
|
+
const instance = this.instanceManager.getInstance(id);
|
|
22886
|
+
const providerType = typeof instance?.type === "string" ? instance.type : "";
|
|
22887
|
+
if (!providerType) continue;
|
|
22888
|
+
const resolved = this.providerLoader.resolve(providerType);
|
|
22889
|
+
if (!resolved) continue;
|
|
22890
|
+
if (instance && typeof instance === "object" && "provider" in instance) {
|
|
22891
|
+
instance.provider = resolved;
|
|
22892
|
+
refreshedInstances += 1;
|
|
22893
|
+
}
|
|
22894
|
+
}
|
|
22895
|
+
}
|
|
22768
22896
|
const providers = this.providerLoader.getAll().map((p) => ({
|
|
22769
22897
|
type: p.type,
|
|
22770
22898
|
name: p.name,
|
|
@@ -22775,7 +22903,7 @@ var DevServer = class _DevServer {
|
|
|
22775
22903
|
cdp.clearTargetId();
|
|
22776
22904
|
}
|
|
22777
22905
|
}
|
|
22778
|
-
this.json(res, 200, { reloaded: true, providers });
|
|
22906
|
+
this.json(res, 200, { reloaded: true, refreshedInstances, providers });
|
|
22779
22907
|
} catch (e) {
|
|
22780
22908
|
this.json(res, 500, { error: e.message });
|
|
22781
22909
|
}
|