adhdev 0.8.22 → 0.8.25
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/index.js +1190 -275
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +1190 -275
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -84,7 +84,8 @@ function normalizeConfig(raw) {
|
|
|
84
84
|
providerSettings: isPlainObject(parsed.providerSettings) ? parsed.providerSettings : {},
|
|
85
85
|
ideSettings: isPlainObject(parsed.ideSettings) ? parsed.ideSettings : {},
|
|
86
86
|
disableUpstream: asBoolean(parsed.disableUpstream, DEFAULT_CONFIG.disableUpstream ?? false),
|
|
87
|
-
providerDir: asOptionalString(parsed.providerDir)
|
|
87
|
+
providerDir: asOptionalString(parsed.providerDir),
|
|
88
|
+
terminalSizingMode: parsed.terminalSizingMode === "fit" ? "fit" : "measured"
|
|
88
89
|
};
|
|
89
90
|
}
|
|
90
91
|
function generateMachineId() {
|
|
@@ -232,7 +233,8 @@ var init_config = __esm({
|
|
|
232
233
|
registeredMachineId: void 0,
|
|
233
234
|
providerSettings: {},
|
|
234
235
|
ideSettings: {},
|
|
235
|
-
disableUpstream: false
|
|
236
|
+
disableUpstream: false,
|
|
237
|
+
terminalSizingMode: "measured"
|
|
236
238
|
};
|
|
237
239
|
MACHINE_ID_PREFIX = "mach_";
|
|
238
240
|
}
|
|
@@ -2457,204 +2459,97 @@ var init_status_monitor = __esm({
|
|
|
2457
2459
|
}
|
|
2458
2460
|
});
|
|
2459
2461
|
|
|
2460
|
-
// ../../oss/packages/daemon-core/src/providers/
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
this.monitor.updateConfig({
|
|
2502
|
-
approvalAlert: this.settings.approvalAlert !== false,
|
|
2503
|
-
longGeneratingAlert: this.settings.longGeneratingAlert !== false,
|
|
2504
|
-
longGeneratingThresholdSec: this.settings.longGeneratingThresholdSec || 180
|
|
2505
|
-
});
|
|
2506
|
-
}
|
|
2507
|
-
async onTick() {
|
|
2508
|
-
if (!this.context?.cdp?.isConnected) return;
|
|
2509
|
-
}
|
|
2510
|
-
getState() {
|
|
2511
|
-
return {
|
|
2512
|
-
type: this.type,
|
|
2513
|
-
name: this.provider.name,
|
|
2514
|
-
category: "extension",
|
|
2515
|
-
status: this.currentStatus,
|
|
2516
|
-
activeChat: this.messages.length > 0 ? {
|
|
2517
|
-
id: this.chatId || this.instanceId,
|
|
2518
|
-
title: this.chatTitle || this.agentName || this.provider.name,
|
|
2519
|
-
status: this.currentStatus,
|
|
2520
|
-
messages: this.messages,
|
|
2521
|
-
activeModal: this.activeModal,
|
|
2522
|
-
inputContent: ""
|
|
2523
|
-
} : null,
|
|
2524
|
-
currentModel: this.currentModel || void 0,
|
|
2525
|
-
currentPlan: this.currentMode || void 0,
|
|
2526
|
-
controlValues: this.controlValues,
|
|
2527
|
-
providerControls: this.provider.controls,
|
|
2528
|
-
agentStreams: this.agentStreams,
|
|
2529
|
-
instanceId: this.instanceId,
|
|
2530
|
-
lastUpdated: Date.now(),
|
|
2531
|
-
settings: this.settings,
|
|
2532
|
-
pendingEvents: this.flushEvents()
|
|
2533
|
-
};
|
|
2534
|
-
}
|
|
2535
|
-
onEvent(event, data) {
|
|
2536
|
-
if (event === "stream_update") {
|
|
2537
|
-
if (data?.streams) this.agentStreams = data.streams;
|
|
2538
|
-
if (data?.messages) this.messages = data.messages;
|
|
2539
|
-
if (data?.activeModal !== void 0) this.activeModal = data.activeModal;
|
|
2540
|
-
if (data?.model) this.currentModel = data.model;
|
|
2541
|
-
if (data?.mode) this.currentMode = data.mode;
|
|
2542
|
-
if (data?.controlValues) this.controlValues = data.controlValues;
|
|
2543
|
-
if (typeof data?.sessionId === "string" && data.sessionId.trim()) this.chatId = data.sessionId;
|
|
2544
|
-
if (typeof data?.title === "string" && data.title.trim()) this.chatTitle = data.title;
|
|
2545
|
-
if (typeof data?.agentName === "string" && data.agentName.trim()) this.agentName = data.agentName;
|
|
2546
|
-
if (typeof data?.extensionId === "string" && data.extensionId.trim()) this.extensionId = data.extensionId;
|
|
2547
|
-
if (data?.status) {
|
|
2548
|
-
const newStatus = data.status;
|
|
2549
|
-
this.detectTransition(newStatus, data);
|
|
2550
|
-
this.currentStatus = newStatus;
|
|
2551
|
-
}
|
|
2552
|
-
} else if (event === "stream_reset") {
|
|
2553
|
-
this.resetStreamState();
|
|
2554
|
-
} else if (event === "extension_connected") {
|
|
2555
|
-
this.ideType = data?.ideType || "";
|
|
2462
|
+
// ../../oss/packages/daemon-core/src/providers/control-effects.ts
|
|
2463
|
+
function extractProviderControlValues(controls, data) {
|
|
2464
|
+
if (!data || typeof data !== "object") return void 0;
|
|
2465
|
+
const values = {};
|
|
2466
|
+
const explicit = data.controlValues;
|
|
2467
|
+
if (explicit && typeof explicit === "object") {
|
|
2468
|
+
for (const [key, value] of Object.entries(explicit)) {
|
|
2469
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
2470
|
+
values[key] = value;
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
for (const ctrl of controls || []) {
|
|
2475
|
+
if (!ctrl.readFrom) continue;
|
|
2476
|
+
const rawValue = data[ctrl.readFrom];
|
|
2477
|
+
if (rawValue === void 0 || rawValue === null) continue;
|
|
2478
|
+
values[ctrl.id] = normalizeControlValue(rawValue);
|
|
2479
|
+
}
|
|
2480
|
+
if (data.model !== void 0 && values.model === void 0) values.model = normalizeControlValue(data.model);
|
|
2481
|
+
if (data.mode !== void 0 && values.mode === void 0) values.mode = normalizeControlValue(data.mode);
|
|
2482
|
+
return Object.keys(values).length > 0 ? values : void 0;
|
|
2483
|
+
}
|
|
2484
|
+
function normalizeProviderEffects(data) {
|
|
2485
|
+
const rawEffects = Array.isArray(data?.effects) ? data.effects : [];
|
|
2486
|
+
const effects = [];
|
|
2487
|
+
for (const raw of rawEffects) {
|
|
2488
|
+
if (!raw || typeof raw !== "object") continue;
|
|
2489
|
+
const type = raw.type;
|
|
2490
|
+
if (type === "message" && raw.message && typeof raw.message === "object") {
|
|
2491
|
+
const content = raw.message.content;
|
|
2492
|
+
if (typeof content !== "string" && !Array.isArray(content)) continue;
|
|
2493
|
+
effects.push({
|
|
2494
|
+
type: "message",
|
|
2495
|
+
id: typeof raw.id === "string" ? raw.id : void 0,
|
|
2496
|
+
when: raw.when === "turn_completed" ? "turn_completed" : "immediate",
|
|
2497
|
+
persist: raw.persist !== false,
|
|
2498
|
+
message: {
|
|
2499
|
+
role: raw.message.role === "assistant" || raw.message.role === "user" ? raw.message.role : "system",
|
|
2500
|
+
content,
|
|
2501
|
+
kind: typeof raw.message.kind === "string" ? raw.message.kind : void 0,
|
|
2502
|
+
senderName: typeof raw.message.senderName === "string" ? raw.message.senderName : void 0
|
|
2556
2503
|
}
|
|
2557
|
-
}
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
const now = Date.now();
|
|
2570
|
-
const agentStatus = newStatus === "streaming" || newStatus === "generating" ? "generating" : newStatus === "waiting_approval" ? "waiting_approval" : "idle";
|
|
2571
|
-
const lastMsg = Array.isArray(data?.messages) && data.messages.length > 0 ? data.messages[data.messages.length - 1] : null;
|
|
2572
|
-
const progressFingerprint = agentStatus === "generating" ? `${lastMsg?.role || ""}:${typeof lastMsg?.content === "string" ? lastMsg.content : JSON.stringify(lastMsg?.content || "")}`.slice(-2e3) : void 0;
|
|
2573
|
-
if (agentStatus !== this.lastAgentStatus) {
|
|
2574
|
-
if (this.lastAgentStatus === "idle" && agentStatus === "generating") {
|
|
2575
|
-
this.generatingStartedAt = now;
|
|
2576
|
-
this.pushEvent({
|
|
2577
|
-
event: "agent:generating_started",
|
|
2578
|
-
chatTitle: this.resolveChatTitle(data),
|
|
2579
|
-
timestamp: now,
|
|
2580
|
-
ideType: this.ideType || this.type,
|
|
2581
|
-
agentType: this.type,
|
|
2582
|
-
agentName: this.agentName || this.provider.name,
|
|
2583
|
-
extensionId: this.extensionId || this.type
|
|
2584
|
-
});
|
|
2585
|
-
} else if (agentStatus === "waiting_approval") {
|
|
2586
|
-
if (!this.generatingStartedAt) this.generatingStartedAt = now;
|
|
2587
|
-
this.pushEvent({
|
|
2588
|
-
event: "agent:waiting_approval",
|
|
2589
|
-
chatTitle: this.resolveChatTitle(data),
|
|
2590
|
-
timestamp: now,
|
|
2591
|
-
ideType: this.ideType || this.type,
|
|
2592
|
-
agentType: this.type,
|
|
2593
|
-
agentName: this.agentName || this.provider.name,
|
|
2594
|
-
extensionId: this.extensionId || this.type,
|
|
2595
|
-
modalMessage: data?.activeModal?.message,
|
|
2596
|
-
modalButtons: data?.activeModal?.buttons
|
|
2597
|
-
});
|
|
2598
|
-
} else if (agentStatus === "idle" && (this.lastAgentStatus === "generating" || this.lastAgentStatus === "waiting_approval")) {
|
|
2599
|
-
const duration3 = this.generatingStartedAt ? Math.round((now - this.generatingStartedAt) / 1e3) : 0;
|
|
2600
|
-
this.pushEvent({
|
|
2601
|
-
event: "agent:generating_completed",
|
|
2602
|
-
chatTitle: this.resolveChatTitle(data),
|
|
2603
|
-
duration: duration3,
|
|
2604
|
-
timestamp: now,
|
|
2605
|
-
ideType: this.ideType || this.type,
|
|
2606
|
-
agentType: this.type,
|
|
2607
|
-
agentName: this.agentName || this.provider.name,
|
|
2608
|
-
extensionId: this.extensionId || this.type
|
|
2609
|
-
});
|
|
2610
|
-
this.generatingStartedAt = 0;
|
|
2611
|
-
}
|
|
2612
|
-
this.lastAgentStatus = agentStatus;
|
|
2613
|
-
}
|
|
2614
|
-
const agentKey = `${this.type}:ext`;
|
|
2615
|
-
const monitorEvents = this.monitor.check(agentKey, agentStatus, now, progressFingerprint);
|
|
2616
|
-
for (const me of monitorEvents) {
|
|
2617
|
-
this.pushEvent({ event: me.type, agentKey: me.agentKey, message: me.message, elapsedSec: me.elapsedSec, timestamp: me.timestamp });
|
|
2504
|
+
});
|
|
2505
|
+
continue;
|
|
2506
|
+
}
|
|
2507
|
+
if (type === "toast" && raw.toast && typeof raw.toast.message === "string") {
|
|
2508
|
+
effects.push({
|
|
2509
|
+
type: "toast",
|
|
2510
|
+
id: typeof raw.id === "string" ? raw.id : void 0,
|
|
2511
|
+
when: raw.when === "turn_completed" ? "turn_completed" : "immediate",
|
|
2512
|
+
persist: raw.persist !== false,
|
|
2513
|
+
toast: {
|
|
2514
|
+
level: raw.toast.level === "success" || raw.toast.level === "warning" ? raw.toast.level : "info",
|
|
2515
|
+
message: raw.toast.message
|
|
2618
2516
|
}
|
|
2619
|
-
}
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
this.detectTransition("idle", {
|
|
2636
|
-
title: this.chatTitle,
|
|
2637
|
-
agentName: this.agentName,
|
|
2638
|
-
extensionId: this.extensionId,
|
|
2639
|
-
messages: this.messages
|
|
2640
|
-
});
|
|
2517
|
+
});
|
|
2518
|
+
continue;
|
|
2519
|
+
}
|
|
2520
|
+
if (type === "notification" && raw.notification && typeof raw.notification.body === "string") {
|
|
2521
|
+
effects.push({
|
|
2522
|
+
type: "notification",
|
|
2523
|
+
id: typeof raw.id === "string" ? raw.id : void 0,
|
|
2524
|
+
when: raw.when === "turn_completed" ? "turn_completed" : "immediate",
|
|
2525
|
+
persist: raw.persist !== false,
|
|
2526
|
+
notification: {
|
|
2527
|
+
title: typeof raw.notification.title === "string" ? raw.notification.title : void 0,
|
|
2528
|
+
body: raw.notification.body,
|
|
2529
|
+
level: raw.notification.level === "success" || raw.notification.level === "warning" ? raw.notification.level : "info",
|
|
2530
|
+
channels: Array.isArray(raw.notification.channels) ? raw.notification.channels.filter((channel) => channel === "bubble" || channel === "toast" || channel === "browser") : void 0,
|
|
2531
|
+
preferenceKey: raw.notification.preferenceKey === "disconnect" || raw.notification.preferenceKey === "completion" || raw.notification.preferenceKey === "approval" || raw.notification.preferenceKey === "browser" ? raw.notification.preferenceKey : void 0,
|
|
2532
|
+
bubbleContent: typeof raw.notification.bubbleContent === "string" || Array.isArray(raw.notification.bubbleContent) ? raw.notification.bubbleContent : void 0
|
|
2641
2533
|
}
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2534
|
+
});
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
return effects;
|
|
2538
|
+
}
|
|
2539
|
+
function normalizeControlValue(value) {
|
|
2540
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
2541
|
+
return value;
|
|
2542
|
+
}
|
|
2543
|
+
if (value && typeof value === "object") {
|
|
2544
|
+
if (typeof value.label === "string") return value.label;
|
|
2545
|
+
if (typeof value.name === "string") return value.name;
|
|
2546
|
+
if (typeof value.id === "string") return value.id;
|
|
2547
|
+
}
|
|
2548
|
+
return String(value);
|
|
2549
|
+
}
|
|
2550
|
+
var init_control_effects = __esm({
|
|
2551
|
+
"../../oss/packages/daemon-core/src/providers/control-effects.ts"() {
|
|
2552
|
+
"use strict";
|
|
2658
2553
|
}
|
|
2659
2554
|
});
|
|
2660
2555
|
|
|
@@ -2938,6 +2833,344 @@ var init_chat_history = __esm({
|
|
|
2938
2833
|
}
|
|
2939
2834
|
});
|
|
2940
2835
|
|
|
2836
|
+
// ../../oss/packages/daemon-core/src/providers/extension-provider-instance.ts
|
|
2837
|
+
var ExtensionProviderInstance;
|
|
2838
|
+
var init_extension_provider_instance = __esm({
|
|
2839
|
+
"../../oss/packages/daemon-core/src/providers/extension-provider-instance.ts"() {
|
|
2840
|
+
"use strict";
|
|
2841
|
+
init_status_monitor();
|
|
2842
|
+
init_control_effects();
|
|
2843
|
+
init_chat_history();
|
|
2844
|
+
ExtensionProviderInstance = class {
|
|
2845
|
+
type;
|
|
2846
|
+
category = "extension";
|
|
2847
|
+
provider;
|
|
2848
|
+
context = null;
|
|
2849
|
+
settings = {};
|
|
2850
|
+
events = [];
|
|
2851
|
+
// status
|
|
2852
|
+
currentStatus = "idle";
|
|
2853
|
+
agentStreams = [];
|
|
2854
|
+
messages = [];
|
|
2855
|
+
activeModal = null;
|
|
2856
|
+
currentModel = "";
|
|
2857
|
+
currentMode = "";
|
|
2858
|
+
controlValues = {};
|
|
2859
|
+
appliedEffectKeys = /* @__PURE__ */ new Set();
|
|
2860
|
+
runtimeMessages = [];
|
|
2861
|
+
lastAgentStatus = "idle";
|
|
2862
|
+
generatingStartedAt = 0;
|
|
2863
|
+
monitor;
|
|
2864
|
+
historyWriter;
|
|
2865
|
+
// meta
|
|
2866
|
+
instanceId;
|
|
2867
|
+
ideType = "";
|
|
2868
|
+
chatId = null;
|
|
2869
|
+
chatTitle = null;
|
|
2870
|
+
agentName = "";
|
|
2871
|
+
extensionId = "";
|
|
2872
|
+
constructor(provider) {
|
|
2873
|
+
this.type = provider.type;
|
|
2874
|
+
this.provider = provider;
|
|
2875
|
+
this.instanceId = crypto.randomUUID();
|
|
2876
|
+
this.monitor = new StatusMonitor();
|
|
2877
|
+
this.historyWriter = new ChatHistoryWriter();
|
|
2878
|
+
}
|
|
2879
|
+
// ─── Lifecycle ──────────────────────────────────
|
|
2880
|
+
async init(context) {
|
|
2881
|
+
this.context = context;
|
|
2882
|
+
this.settings = context.settings || {};
|
|
2883
|
+
this.monitor.updateConfig({
|
|
2884
|
+
approvalAlert: this.settings.approvalAlert !== false,
|
|
2885
|
+
longGeneratingAlert: this.settings.longGeneratingAlert !== false,
|
|
2886
|
+
longGeneratingThresholdSec: this.settings.longGeneratingThresholdSec || 180
|
|
2887
|
+
});
|
|
2888
|
+
}
|
|
2889
|
+
async onTick() {
|
|
2890
|
+
if (!this.context?.cdp?.isConnected) return;
|
|
2891
|
+
}
|
|
2892
|
+
getState() {
|
|
2893
|
+
return {
|
|
2894
|
+
type: this.type,
|
|
2895
|
+
name: this.provider.name,
|
|
2896
|
+
category: "extension",
|
|
2897
|
+
status: this.currentStatus,
|
|
2898
|
+
activeChat: this.messages.length > 0 || this.runtimeMessages.length > 0 ? {
|
|
2899
|
+
id: this.chatId || this.instanceId,
|
|
2900
|
+
title: this.chatTitle || this.agentName || this.provider.name,
|
|
2901
|
+
status: this.currentStatus,
|
|
2902
|
+
messages: this.mergeConversationMessages(this.messages),
|
|
2903
|
+
activeModal: this.activeModal,
|
|
2904
|
+
inputContent: ""
|
|
2905
|
+
} : null,
|
|
2906
|
+
currentModel: this.currentModel || void 0,
|
|
2907
|
+
currentPlan: this.currentMode || void 0,
|
|
2908
|
+
controlValues: this.controlValues,
|
|
2909
|
+
providerControls: this.provider.controls,
|
|
2910
|
+
agentStreams: this.agentStreams,
|
|
2911
|
+
instanceId: this.instanceId,
|
|
2912
|
+
lastUpdated: Date.now(),
|
|
2913
|
+
settings: this.settings,
|
|
2914
|
+
pendingEvents: this.flushEvents()
|
|
2915
|
+
};
|
|
2916
|
+
}
|
|
2917
|
+
onEvent(event, data) {
|
|
2918
|
+
if (event === "stream_update") {
|
|
2919
|
+
if (data?.streams) this.agentStreams = data.streams;
|
|
2920
|
+
if (data?.messages) this.messages = data.messages;
|
|
2921
|
+
if (data?.activeModal !== void 0) this.activeModal = data.activeModal;
|
|
2922
|
+
if (data?.model) this.currentModel = data.model;
|
|
2923
|
+
if (data?.mode) this.currentMode = data.mode;
|
|
2924
|
+
const controlValues = extractProviderControlValues(this.provider.controls, data) || data?.controlValues;
|
|
2925
|
+
if (controlValues) this.controlValues = controlValues;
|
|
2926
|
+
if (typeof data?.sessionId === "string" && data.sessionId.trim()) this.chatId = data.sessionId;
|
|
2927
|
+
if (typeof data?.title === "string" && data.title.trim()) this.chatTitle = data.title;
|
|
2928
|
+
if (typeof data?.agentName === "string" && data.agentName.trim()) this.agentName = data.agentName;
|
|
2929
|
+
if (typeof data?.extensionId === "string" && data.extensionId.trim()) this.extensionId = data.extensionId;
|
|
2930
|
+
if (data?.status) {
|
|
2931
|
+
const newStatus = data.status;
|
|
2932
|
+
this.detectTransition(newStatus, data);
|
|
2933
|
+
this.currentStatus = newStatus;
|
|
2934
|
+
}
|
|
2935
|
+
} else if (event === "stream_reset") {
|
|
2936
|
+
this.resetStreamState();
|
|
2937
|
+
} else if (event === "extension_connected") {
|
|
2938
|
+
this.ideType = data?.ideType || "";
|
|
2939
|
+
} else if (event === "provider_state_patch" && data && typeof data === "object") {
|
|
2940
|
+
this.applyProviderResponse(data, { phase: "immediate" });
|
|
2941
|
+
}
|
|
2942
|
+
}
|
|
2943
|
+
dispose() {
|
|
2944
|
+
this.agentStreams = [];
|
|
2945
|
+
this.messages = [];
|
|
2946
|
+
this.monitor.reset();
|
|
2947
|
+
this.appliedEffectKeys.clear();
|
|
2948
|
+
this.runtimeMessages = [];
|
|
2949
|
+
}
|
|
2950
|
+
updateSettings(newSettings) {
|
|
2951
|
+
this.settings = { ...newSettings };
|
|
2952
|
+
this.monitor.updateConfig({
|
|
2953
|
+
approvalAlert: this.settings.approvalAlert !== false,
|
|
2954
|
+
longGeneratingAlert: this.settings.longGeneratingAlert !== false,
|
|
2955
|
+
longGeneratingThresholdSec: this.settings.longGeneratingThresholdSec || 180
|
|
2956
|
+
});
|
|
2957
|
+
}
|
|
2958
|
+
/** Query UUID instanceId */
|
|
2959
|
+
getInstanceId() {
|
|
2960
|
+
return this.instanceId;
|
|
2961
|
+
}
|
|
2962
|
+
// ─── status transition detect ──────────────────────────────
|
|
2963
|
+
detectTransition(newStatus, data) {
|
|
2964
|
+
const now = Date.now();
|
|
2965
|
+
const agentStatus = newStatus === "streaming" || newStatus === "generating" ? "generating" : newStatus === "waiting_approval" ? "waiting_approval" : "idle";
|
|
2966
|
+
const lastMsg = Array.isArray(data?.messages) && data.messages.length > 0 ? data.messages[data.messages.length - 1] : null;
|
|
2967
|
+
const progressFingerprint = agentStatus === "generating" ? `${lastMsg?.role || ""}:${typeof lastMsg?.content === "string" ? lastMsg.content : JSON.stringify(lastMsg?.content || "")}`.slice(-2e3) : void 0;
|
|
2968
|
+
const previousStatus = this.lastAgentStatus;
|
|
2969
|
+
if (agentStatus !== this.lastAgentStatus) {
|
|
2970
|
+
if (this.lastAgentStatus === "idle" && agentStatus === "generating") {
|
|
2971
|
+
this.generatingStartedAt = now;
|
|
2972
|
+
this.pushEvent({
|
|
2973
|
+
event: "agent:generating_started",
|
|
2974
|
+
chatTitle: this.resolveChatTitle(data),
|
|
2975
|
+
timestamp: now,
|
|
2976
|
+
ideType: this.ideType || this.type,
|
|
2977
|
+
agentType: this.type,
|
|
2978
|
+
agentName: this.agentName || this.provider.name,
|
|
2979
|
+
extensionId: this.extensionId || this.type
|
|
2980
|
+
});
|
|
2981
|
+
} else if (agentStatus === "waiting_approval") {
|
|
2982
|
+
if (!this.generatingStartedAt) this.generatingStartedAt = now;
|
|
2983
|
+
this.pushEvent({
|
|
2984
|
+
event: "agent:waiting_approval",
|
|
2985
|
+
chatTitle: this.resolveChatTitle(data),
|
|
2986
|
+
timestamp: now,
|
|
2987
|
+
ideType: this.ideType || this.type,
|
|
2988
|
+
agentType: this.type,
|
|
2989
|
+
agentName: this.agentName || this.provider.name,
|
|
2990
|
+
extensionId: this.extensionId || this.type,
|
|
2991
|
+
modalMessage: data?.activeModal?.message,
|
|
2992
|
+
modalButtons: data?.activeModal?.buttons
|
|
2993
|
+
});
|
|
2994
|
+
} else if (agentStatus === "idle" && (this.lastAgentStatus === "generating" || this.lastAgentStatus === "waiting_approval")) {
|
|
2995
|
+
const duration3 = this.generatingStartedAt ? Math.round((now - this.generatingStartedAt) / 1e3) : 0;
|
|
2996
|
+
this.pushEvent({
|
|
2997
|
+
event: "agent:generating_completed",
|
|
2998
|
+
chatTitle: this.resolveChatTitle(data),
|
|
2999
|
+
duration: duration3,
|
|
3000
|
+
timestamp: now,
|
|
3001
|
+
ideType: this.ideType || this.type,
|
|
3002
|
+
agentType: this.type,
|
|
3003
|
+
agentName: this.agentName || this.provider.name,
|
|
3004
|
+
extensionId: this.extensionId || this.type
|
|
3005
|
+
});
|
|
3006
|
+
this.generatingStartedAt = 0;
|
|
3007
|
+
}
|
|
3008
|
+
this.lastAgentStatus = agentStatus;
|
|
3009
|
+
}
|
|
3010
|
+
this.applyProviderResponse(data, {
|
|
3011
|
+
phase: agentStatus === "idle" && (previousStatus === "generating" || previousStatus === "waiting_approval") ? "turn_completed" : "immediate"
|
|
3012
|
+
});
|
|
3013
|
+
const agentKey = `${this.type}:ext`;
|
|
3014
|
+
const monitorEvents = this.monitor.check(agentKey, agentStatus, now, progressFingerprint);
|
|
3015
|
+
for (const me of monitorEvents) {
|
|
3016
|
+
this.pushEvent({ event: me.type, agentKey: me.agentKey, message: me.message, elapsedSec: me.elapsedSec, timestamp: me.timestamp });
|
|
3017
|
+
}
|
|
3018
|
+
}
|
|
3019
|
+
pushEvent(event) {
|
|
3020
|
+
this.events.push(event);
|
|
3021
|
+
if (this.events.length > 50) this.events = this.events.slice(-50);
|
|
3022
|
+
}
|
|
3023
|
+
applyProviderResponse(data, options) {
|
|
3024
|
+
if (!data || typeof data !== "object") return;
|
|
3025
|
+
const controlValues = extractProviderControlValues(this.provider.controls, data);
|
|
3026
|
+
if (controlValues) this.controlValues = { ...this.controlValues, ...controlValues };
|
|
3027
|
+
const effects = normalizeProviderEffects(data);
|
|
3028
|
+
for (const effect of effects) {
|
|
3029
|
+
const effectWhen = effect.when || "immediate";
|
|
3030
|
+
if (effectWhen === "turn_completed" && options.phase !== "turn_completed") continue;
|
|
3031
|
+
if (effectWhen === "immediate" && options.phase === "turn_completed") continue;
|
|
3032
|
+
const effectKey = this.getEffectDedupKey(effect);
|
|
3033
|
+
if (this.appliedEffectKeys.has(effectKey)) continue;
|
|
3034
|
+
this.appliedEffectKeys.add(effectKey);
|
|
3035
|
+
if (effect.persist !== false) {
|
|
3036
|
+
const persisted = this.getPersistedEffectContent(effect);
|
|
3037
|
+
if (persisted) this.appendRuntimeSystemMessage(persisted, effectKey);
|
|
3038
|
+
}
|
|
3039
|
+
if (effect.type === "message" && effect.message) {
|
|
3040
|
+
this.pushEvent({
|
|
3041
|
+
event: "provider:message",
|
|
3042
|
+
timestamp: Date.now(),
|
|
3043
|
+
content: typeof effect.message.content === "string" ? effect.message.content : JSON.stringify(effect.message.content),
|
|
3044
|
+
role: effect.message.role || "system",
|
|
3045
|
+
kind: effect.message.kind,
|
|
3046
|
+
senderName: effect.message.senderName
|
|
3047
|
+
});
|
|
3048
|
+
} else if (effect.type === "toast" && effect.toast) {
|
|
3049
|
+
this.pushEvent({
|
|
3050
|
+
event: "provider:toast",
|
|
3051
|
+
effectId: effect.id || effectKey,
|
|
3052
|
+
timestamp: Date.now(),
|
|
3053
|
+
message: effect.toast.message,
|
|
3054
|
+
level: effect.toast.level || "info"
|
|
3055
|
+
});
|
|
3056
|
+
} else if (effect.type === "notification" && effect.notification) {
|
|
3057
|
+
this.pushEvent({
|
|
3058
|
+
event: "provider:notification",
|
|
3059
|
+
effectId: effect.id || effectKey,
|
|
3060
|
+
timestamp: Date.now(),
|
|
3061
|
+
title: effect.notification.title,
|
|
3062
|
+
message: effect.notification.body,
|
|
3063
|
+
content: typeof effect.notification.bubbleContent === "string" ? effect.notification.bubbleContent : effect.notification.body,
|
|
3064
|
+
level: effect.notification.level || "info",
|
|
3065
|
+
channels: effect.notification.channels || ["toast"],
|
|
3066
|
+
preferenceKey: effect.notification.preferenceKey
|
|
3067
|
+
});
|
|
3068
|
+
}
|
|
3069
|
+
}
|
|
3070
|
+
}
|
|
3071
|
+
appendRuntimeSystemMessage(content, dedupKey, receivedAt = Date.now()) {
|
|
3072
|
+
const normalizedContent = String(content || "").trim();
|
|
3073
|
+
if (!normalizedContent) return;
|
|
3074
|
+
if (this.runtimeMessages.some((entry) => entry.key === dedupKey)) return;
|
|
3075
|
+
this.runtimeMessages.push({
|
|
3076
|
+
key: dedupKey,
|
|
3077
|
+
message: {
|
|
3078
|
+
role: "system",
|
|
3079
|
+
senderName: "System",
|
|
3080
|
+
content: normalizedContent,
|
|
3081
|
+
receivedAt,
|
|
3082
|
+
timestamp: receivedAt
|
|
3083
|
+
}
|
|
3084
|
+
});
|
|
3085
|
+
if (this.runtimeMessages.length > 50) this.runtimeMessages = this.runtimeMessages.slice(-50);
|
|
3086
|
+
this.historyWriter.appendNewMessages(
|
|
3087
|
+
this.type,
|
|
3088
|
+
[{
|
|
3089
|
+
role: "system",
|
|
3090
|
+
senderName: "System",
|
|
3091
|
+
content: normalizedContent,
|
|
3092
|
+
kind: "system",
|
|
3093
|
+
receivedAt,
|
|
3094
|
+
historyDedupKey: dedupKey
|
|
3095
|
+
}],
|
|
3096
|
+
this.chatTitle || this.agentName || this.provider.name,
|
|
3097
|
+
this.instanceId,
|
|
3098
|
+
this.chatId || this.instanceId
|
|
3099
|
+
);
|
|
3100
|
+
}
|
|
3101
|
+
mergeConversationMessages(messages) {
|
|
3102
|
+
if (this.runtimeMessages.length === 0) return messages;
|
|
3103
|
+
return [...messages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b) => {
|
|
3104
|
+
const aTime = a.message.receivedAt || a.message.timestamp || 0;
|
|
3105
|
+
const bTime = b.message.receivedAt || b.message.timestamp || 0;
|
|
3106
|
+
if (aTime !== bTime) return aTime - bTime;
|
|
3107
|
+
return a.index - b.index;
|
|
3108
|
+
}).map((entry) => entry.message);
|
|
3109
|
+
}
|
|
3110
|
+
getPersistedEffectContent(effect) {
|
|
3111
|
+
if (effect.type === "message") {
|
|
3112
|
+
return typeof effect.message?.content === "string" ? effect.message.content : JSON.stringify(effect.message?.content || "");
|
|
3113
|
+
}
|
|
3114
|
+
if (effect.type === "toast") {
|
|
3115
|
+
return effect.toast?.message || null;
|
|
3116
|
+
}
|
|
3117
|
+
if (effect.type === "notification") {
|
|
3118
|
+
if (typeof effect.notification?.bubbleContent === "string") return effect.notification.bubbleContent;
|
|
3119
|
+
if (typeof effect.notification?.title === "string" && effect.notification.title.trim()) {
|
|
3120
|
+
return `${effect.notification.title}
|
|
3121
|
+
${effect.notification.body || ""}`.trim();
|
|
3122
|
+
}
|
|
3123
|
+
return effect.notification?.body || null;
|
|
3124
|
+
}
|
|
3125
|
+
return null;
|
|
3126
|
+
}
|
|
3127
|
+
getEffectDedupKey(effect) {
|
|
3128
|
+
if (effect.id) return `provider_effect:${effect.id}`;
|
|
3129
|
+
if (effect.type === "message") {
|
|
3130
|
+
return `provider_effect:message:${typeof effect.message?.content === "string" ? effect.message.content : JSON.stringify(effect.message?.content || "")}`;
|
|
3131
|
+
}
|
|
3132
|
+
if (effect.type === "notification") {
|
|
3133
|
+
return `provider_effect:notification:${effect.notification?.title || ""}:${effect.notification?.body || ""}`;
|
|
3134
|
+
}
|
|
3135
|
+
return `provider_effect:toast:${effect.toast?.message || ""}`;
|
|
3136
|
+
}
|
|
3137
|
+
flushEvents() {
|
|
3138
|
+
const events = [...this.events];
|
|
3139
|
+
this.events = [];
|
|
3140
|
+
return events;
|
|
3141
|
+
}
|
|
3142
|
+
resolveChatTitle(data) {
|
|
3143
|
+
const title = typeof data?.title === "string" && data.title.trim() ? data.title.trim() : this.chatTitle;
|
|
3144
|
+
return title || this.agentName || this.provider.name;
|
|
3145
|
+
}
|
|
3146
|
+
resetStreamState() {
|
|
3147
|
+
if (this.currentStatus !== "idle") {
|
|
3148
|
+
this.detectTransition("idle", {
|
|
3149
|
+
title: this.chatTitle,
|
|
3150
|
+
agentName: this.agentName,
|
|
3151
|
+
extensionId: this.extensionId,
|
|
3152
|
+
messages: this.messages
|
|
3153
|
+
});
|
|
3154
|
+
}
|
|
3155
|
+
this.agentStreams = [];
|
|
3156
|
+
this.messages = [];
|
|
3157
|
+
this.activeModal = null;
|
|
3158
|
+
this.currentModel = "";
|
|
3159
|
+
this.currentMode = "";
|
|
3160
|
+
this.controlValues = {};
|
|
3161
|
+
this.currentStatus = "idle";
|
|
3162
|
+
this.chatId = null;
|
|
3163
|
+
this.chatTitle = null;
|
|
3164
|
+
this.agentName = "";
|
|
3165
|
+
this.extensionId = "";
|
|
3166
|
+
this.lastAgentStatus = "idle";
|
|
3167
|
+
this.generatingStartedAt = 0;
|
|
3168
|
+
this.monitor.reset();
|
|
3169
|
+
}
|
|
3170
|
+
};
|
|
3171
|
+
}
|
|
3172
|
+
});
|
|
3173
|
+
|
|
2941
3174
|
// ../../oss/packages/daemon-core/src/providers/ide-provider-instance.ts
|
|
2942
3175
|
var crypto2, IdeProviderInstance;
|
|
2943
3176
|
var init_ide_provider_instance = __esm({
|
|
@@ -2948,6 +3181,7 @@ var init_ide_provider_instance = __esm({
|
|
|
2948
3181
|
init_status_monitor();
|
|
2949
3182
|
init_chat_history();
|
|
2950
3183
|
init_logger();
|
|
3184
|
+
init_control_effects();
|
|
2951
3185
|
IdeProviderInstance = class {
|
|
2952
3186
|
type;
|
|
2953
3187
|
category = "ide";
|
|
@@ -2965,6 +3199,8 @@ var init_ide_provider_instance = __esm({
|
|
|
2965
3199
|
monitor;
|
|
2966
3200
|
historyWriter;
|
|
2967
3201
|
autoApproveBusy = false;
|
|
3202
|
+
appliedEffectKeys = /* @__PURE__ */ new Set();
|
|
3203
|
+
runtimeMessages = [];
|
|
2968
3204
|
// IDE meta
|
|
2969
3205
|
ideVersion = "";
|
|
2970
3206
|
instanceId;
|
|
@@ -3025,7 +3261,7 @@ var init_ide_provider_instance = __esm({
|
|
|
3025
3261
|
id: this.cachedChat.id || "active_session",
|
|
3026
3262
|
title: this.cachedChat.title || this.type,
|
|
3027
3263
|
status: this.cachedChat.status || this.currentStatus,
|
|
3028
|
-
messages: this.cachedChat.messages || [],
|
|
3264
|
+
messages: this.mergeConversationMessages(this.cachedChat.messages || []),
|
|
3029
3265
|
activeModal: this.cachedChat.activeModal || null,
|
|
3030
3266
|
inputContent: this.cachedChat.inputContent || ""
|
|
3031
3267
|
} : null,
|
|
@@ -3065,6 +3301,13 @@ var init_ide_provider_instance = __esm({
|
|
|
3065
3301
|
for (const ext of this.extensions.values()) {
|
|
3066
3302
|
ext.onEvent("stream_reset");
|
|
3067
3303
|
}
|
|
3304
|
+
} else if (event === "provider_state_patch" && data && typeof data === "object") {
|
|
3305
|
+
const extType = typeof data.extensionType === "string" ? data.extensionType : "";
|
|
3306
|
+
if (extType && this.extensions.has(extType)) {
|
|
3307
|
+
this.extensions.get(extType).onEvent("provider_state_patch", data);
|
|
3308
|
+
} else {
|
|
3309
|
+
this.applyProviderResponse(data, { phase: "immediate" });
|
|
3310
|
+
}
|
|
3068
3311
|
}
|
|
3069
3312
|
}
|
|
3070
3313
|
dispose() {
|
|
@@ -3072,11 +3315,21 @@ var init_ide_provider_instance = __esm({
|
|
|
3072
3315
|
this.lastAgentStatuses.clear();
|
|
3073
3316
|
this.generatingStartedAt.clear();
|
|
3074
3317
|
this.monitor.reset();
|
|
3318
|
+
this.appliedEffectKeys.clear();
|
|
3319
|
+
this.runtimeMessages = [];
|
|
3075
3320
|
for (const ext of this.extensions.values()) {
|
|
3076
3321
|
ext.dispose();
|
|
3077
3322
|
}
|
|
3078
3323
|
this.extensions.clear();
|
|
3079
3324
|
}
|
|
3325
|
+
updateSettings(newSettings) {
|
|
3326
|
+
this.settings = { ...newSettings };
|
|
3327
|
+
this.monitor.updateConfig({
|
|
3328
|
+
approvalAlert: this.settings.approvalAlert !== false,
|
|
3329
|
+
longGeneratingAlert: this.settings.longGeneratingAlert !== false,
|
|
3330
|
+
longGeneratingThresholdSec: this.settings.longGeneratingThresholdSec || 180
|
|
3331
|
+
});
|
|
3332
|
+
}
|
|
3080
3333
|
// ─── Extension manage ─────────────────────────────
|
|
3081
3334
|
/** Extension Instance add */
|
|
3082
3335
|
async addExtension(provider, settings) {
|
|
@@ -3189,6 +3442,8 @@ var init_ide_provider_instance = __esm({
|
|
|
3189
3442
|
raw.messages = raw.messages.filter((m) => !hiddenKinds.has(m.kind));
|
|
3190
3443
|
}
|
|
3191
3444
|
}
|
|
3445
|
+
const controlValues = extractProviderControlValues(this.provider.controls, raw);
|
|
3446
|
+
if (controlValues) raw.controlValues = controlValues;
|
|
3192
3447
|
this.cachedChat = { ...raw, activeModal };
|
|
3193
3448
|
this.detectAgentTransitions(raw, now);
|
|
3194
3449
|
if (raw.messages?.length > 0) {
|
|
@@ -3255,6 +3510,9 @@ var init_ide_provider_instance = __esm({
|
|
|
3255
3510
|
}
|
|
3256
3511
|
this.lastAgentStatuses.set(agentKey, agentStatus);
|
|
3257
3512
|
}
|
|
3513
|
+
this.applyProviderResponse(chatData, {
|
|
3514
|
+
phase: agentStatus === "idle" && (lastStatus === "generating" || lastStatus === "waiting_approval") ? "turn_completed" : "immediate"
|
|
3515
|
+
});
|
|
3258
3516
|
if (agentStatus === "waiting_approval" && this.settings.autoApprove && !this.autoApproveBusy) {
|
|
3259
3517
|
this.autoApproveViaScript(chatData);
|
|
3260
3518
|
}
|
|
@@ -3267,6 +3525,136 @@ var init_ide_provider_instance = __esm({
|
|
|
3267
3525
|
this.events.push(event);
|
|
3268
3526
|
if (this.events.length > 50) this.events = this.events.slice(-50);
|
|
3269
3527
|
}
|
|
3528
|
+
applyProviderResponse(data, options) {
|
|
3529
|
+
if (!data || typeof data !== "object") return;
|
|
3530
|
+
const controlValues = extractProviderControlValues(this.provider.controls, data);
|
|
3531
|
+
if (controlValues) {
|
|
3532
|
+
this.cachedChat = {
|
|
3533
|
+
...this.cachedChat || {},
|
|
3534
|
+
...data,
|
|
3535
|
+
controlValues: { ...this.cachedChat?.controlValues || {}, ...controlValues }
|
|
3536
|
+
};
|
|
3537
|
+
}
|
|
3538
|
+
const effects = normalizeProviderEffects(data);
|
|
3539
|
+
for (const effect of effects) {
|
|
3540
|
+
const effectWhen = effect.when || "immediate";
|
|
3541
|
+
if (effectWhen === "turn_completed" && options.phase !== "turn_completed") continue;
|
|
3542
|
+
if (effectWhen === "immediate" && options.phase === "turn_completed") continue;
|
|
3543
|
+
const effectKey = this.getEffectDedupKey(effect);
|
|
3544
|
+
if (this.appliedEffectKeys.has(effectKey)) continue;
|
|
3545
|
+
this.appliedEffectKeys.add(effectKey);
|
|
3546
|
+
if (effect.persist !== false) {
|
|
3547
|
+
const persisted = this.getPersistedEffectContent(effect);
|
|
3548
|
+
if (persisted) this.appendRuntimeSystemMessage(persisted, effectKey);
|
|
3549
|
+
}
|
|
3550
|
+
if (effect.type === "message" && effect.message) {
|
|
3551
|
+
this.pushEvent({
|
|
3552
|
+
event: "provider:message",
|
|
3553
|
+
timestamp: Date.now(),
|
|
3554
|
+
content: typeof effect.message.content === "string" ? effect.message.content : JSON.stringify(effect.message.content),
|
|
3555
|
+
role: effect.message.role || "system",
|
|
3556
|
+
kind: effect.message.kind,
|
|
3557
|
+
senderName: effect.message.senderName
|
|
3558
|
+
});
|
|
3559
|
+
} else if (effect.type === "toast" && effect.toast) {
|
|
3560
|
+
this.pushEvent({
|
|
3561
|
+
event: "provider:toast",
|
|
3562
|
+
effectId: effect.id || effectKey,
|
|
3563
|
+
timestamp: Date.now(),
|
|
3564
|
+
message: effect.toast.message,
|
|
3565
|
+
level: effect.toast.level || "info"
|
|
3566
|
+
});
|
|
3567
|
+
} else if (effect.type === "notification" && effect.notification) {
|
|
3568
|
+
this.pushEvent({
|
|
3569
|
+
event: "provider:notification",
|
|
3570
|
+
effectId: effect.id || effectKey,
|
|
3571
|
+
timestamp: Date.now(),
|
|
3572
|
+
title: effect.notification.title,
|
|
3573
|
+
message: effect.notification.body,
|
|
3574
|
+
content: typeof effect.notification.bubbleContent === "string" ? effect.notification.bubbleContent : effect.notification.body,
|
|
3575
|
+
level: effect.notification.level || "info",
|
|
3576
|
+
channels: effect.notification.channels || ["toast"],
|
|
3577
|
+
preferenceKey: effect.notification.preferenceKey
|
|
3578
|
+
});
|
|
3579
|
+
}
|
|
3580
|
+
}
|
|
3581
|
+
}
|
|
3582
|
+
appendRuntimeSystemMessage(content, dedupKey, receivedAt = Date.now()) {
|
|
3583
|
+
const normalizedContent = String(content || "").trim();
|
|
3584
|
+
if (!normalizedContent) return;
|
|
3585
|
+
if (this.runtimeMessages.some((entry) => entry.key === dedupKey)) return;
|
|
3586
|
+
if (!this.cachedChat) {
|
|
3587
|
+
this.cachedChat = {
|
|
3588
|
+
id: "active_session",
|
|
3589
|
+
title: this.provider.name,
|
|
3590
|
+
status: this.currentStatus,
|
|
3591
|
+
messages: [],
|
|
3592
|
+
activeModal: null,
|
|
3593
|
+
inputContent: ""
|
|
3594
|
+
};
|
|
3595
|
+
}
|
|
3596
|
+
this.runtimeMessages.push({
|
|
3597
|
+
key: dedupKey,
|
|
3598
|
+
message: {
|
|
3599
|
+
role: "system",
|
|
3600
|
+
senderName: "System",
|
|
3601
|
+
content: normalizedContent,
|
|
3602
|
+
receivedAt,
|
|
3603
|
+
timestamp: receivedAt
|
|
3604
|
+
}
|
|
3605
|
+
});
|
|
3606
|
+
if (this.runtimeMessages.length > 50) this.runtimeMessages = this.runtimeMessages.slice(-50);
|
|
3607
|
+
this.historyWriter.appendNewMessages(
|
|
3608
|
+
this.type,
|
|
3609
|
+
[{
|
|
3610
|
+
role: "system",
|
|
3611
|
+
senderName: "System",
|
|
3612
|
+
content: normalizedContent,
|
|
3613
|
+
kind: "system",
|
|
3614
|
+
receivedAt,
|
|
3615
|
+
historyDedupKey: dedupKey
|
|
3616
|
+
}],
|
|
3617
|
+
this.cachedChat?.title || this.provider.name,
|
|
3618
|
+
this.instanceId,
|
|
3619
|
+
this.cachedChat?.id || this.instanceId
|
|
3620
|
+
);
|
|
3621
|
+
}
|
|
3622
|
+
mergeConversationMessages(messages) {
|
|
3623
|
+
if (this.runtimeMessages.length === 0) return messages;
|
|
3624
|
+
return [...messages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b) => {
|
|
3625
|
+
const aTime = a.message.receivedAt || a.message.timestamp || 0;
|
|
3626
|
+
const bTime = b.message.receivedAt || b.message.timestamp || 0;
|
|
3627
|
+
if (aTime !== bTime) return aTime - bTime;
|
|
3628
|
+
return a.index - b.index;
|
|
3629
|
+
}).map((entry) => entry.message);
|
|
3630
|
+
}
|
|
3631
|
+
getPersistedEffectContent(effect) {
|
|
3632
|
+
if (effect.type === "message") {
|
|
3633
|
+
return typeof effect.message?.content === "string" ? effect.message.content : JSON.stringify(effect.message?.content || "");
|
|
3634
|
+
}
|
|
3635
|
+
if (effect.type === "toast") {
|
|
3636
|
+
return effect.toast?.message || null;
|
|
3637
|
+
}
|
|
3638
|
+
if (effect.type === "notification") {
|
|
3639
|
+
if (typeof effect.notification?.bubbleContent === "string") return effect.notification.bubbleContent;
|
|
3640
|
+
if (typeof effect.notification?.title === "string" && effect.notification.title.trim()) {
|
|
3641
|
+
return `${effect.notification.title}
|
|
3642
|
+
${effect.notification.body || ""}`.trim();
|
|
3643
|
+
}
|
|
3644
|
+
return effect.notification?.body || null;
|
|
3645
|
+
}
|
|
3646
|
+
return null;
|
|
3647
|
+
}
|
|
3648
|
+
getEffectDedupKey(effect) {
|
|
3649
|
+
if (effect.id) return `provider_effect:${effect.id}`;
|
|
3650
|
+
if (effect.type === "message") {
|
|
3651
|
+
return `provider_effect:message:${typeof effect.message?.content === "string" ? effect.message.content : JSON.stringify(effect.message?.content || "")}`;
|
|
3652
|
+
}
|
|
3653
|
+
if (effect.type === "notification") {
|
|
3654
|
+
return `provider_effect:notification:${effect.notification?.title || ""}:${effect.notification?.body || ""}`;
|
|
3655
|
+
}
|
|
3656
|
+
return `provider_effect:toast:${effect.toast?.message || ""}`;
|
|
3657
|
+
}
|
|
3270
3658
|
flushEvents() {
|
|
3271
3659
|
const events = [...this.events];
|
|
3272
3660
|
this.events = [];
|
|
@@ -4122,6 +4510,56 @@ var init_builders = __esm({
|
|
|
4122
4510
|
}
|
|
4123
4511
|
});
|
|
4124
4512
|
|
|
4513
|
+
// ../../oss/packages/daemon-core/src/sessions/reconcile.ts
|
|
4514
|
+
function upsertSessionTarget(sessionRegistry, target) {
|
|
4515
|
+
const existing = sessionRegistry.get(target.sessionId);
|
|
4516
|
+
if (existing && existing.parentSessionId === target.parentSessionId && existing.providerType === target.providerType && existing.transport === target.transport && existing.cdpManagerKey === target.cdpManagerKey && existing.instanceKey === target.instanceKey) {
|
|
4517
|
+
return;
|
|
4518
|
+
}
|
|
4519
|
+
sessionRegistry.register(target);
|
|
4520
|
+
}
|
|
4521
|
+
function reconcileIdeRuntimeSessions(instanceManager, sessionRegistry) {
|
|
4522
|
+
if (!instanceManager || !sessionRegistry) return;
|
|
4523
|
+
for (const instanceKey of instanceManager.listInstanceIds()) {
|
|
4524
|
+
if (!instanceKey.startsWith("ide:")) continue;
|
|
4525
|
+
const ideInstance = instanceManager.getInstance(instanceKey);
|
|
4526
|
+
if (!ideInstance || ideInstance.category !== "ide" || typeof ideInstance.getInstanceId !== "function") {
|
|
4527
|
+
continue;
|
|
4528
|
+
}
|
|
4529
|
+
const managerKey = instanceKey.slice(4);
|
|
4530
|
+
const ideType = typeof ideInstance.type === "string" && ideInstance.type.trim() ? ideInstance.type.trim() : managerKey.split("_")[0];
|
|
4531
|
+
const parentSessionId = ideInstance.getInstanceId();
|
|
4532
|
+
if (!parentSessionId) continue;
|
|
4533
|
+
upsertSessionTarget(sessionRegistry, {
|
|
4534
|
+
sessionId: parentSessionId,
|
|
4535
|
+
parentSessionId: null,
|
|
4536
|
+
providerType: ideType,
|
|
4537
|
+
transport: "cdp-page",
|
|
4538
|
+
cdpManagerKey: managerKey,
|
|
4539
|
+
instanceKey
|
|
4540
|
+
});
|
|
4541
|
+
const extensions = ideInstance.getExtensionInstances?.() || [];
|
|
4542
|
+
for (const ext of extensions) {
|
|
4543
|
+
const extType = typeof ext?.type === "string" ? ext.type.trim() : "";
|
|
4544
|
+
const extSessionId = ext?.getInstanceId?.();
|
|
4545
|
+
if (!extType || !extSessionId) continue;
|
|
4546
|
+
upsertSessionTarget(sessionRegistry, {
|
|
4547
|
+
sessionId: extSessionId,
|
|
4548
|
+
parentSessionId,
|
|
4549
|
+
providerType: extType,
|
|
4550
|
+
transport: "cdp-webview",
|
|
4551
|
+
cdpManagerKey: managerKey,
|
|
4552
|
+
instanceKey
|
|
4553
|
+
});
|
|
4554
|
+
}
|
|
4555
|
+
}
|
|
4556
|
+
}
|
|
4557
|
+
var init_reconcile = __esm({
|
|
4558
|
+
"../../oss/packages/daemon-core/src/sessions/reconcile.ts"() {
|
|
4559
|
+
"use strict";
|
|
4560
|
+
}
|
|
4561
|
+
});
|
|
4562
|
+
|
|
4125
4563
|
// ../../oss/packages/daemon-core/src/commands/chat-commands.ts
|
|
4126
4564
|
function getCurrentProviderType(h, fallback = "") {
|
|
4127
4565
|
return h.currentSession?.providerType || h.currentProviderType || fallback;
|
|
@@ -5388,7 +5826,56 @@ function handleSetProviderSetting(h, args) {
|
|
|
5388
5826
|
}
|
|
5389
5827
|
return { success: false, error: `Failed to set ${providerType}.${key} \u2014 invalid key, value, or not a public setting` };
|
|
5390
5828
|
}
|
|
5391
|
-
|
|
5829
|
+
function normalizeProviderScriptArgs(args) {
|
|
5830
|
+
const normalizedArgs = { ...args || {} };
|
|
5831
|
+
for (const key of ["mode", "model", "message", "action", "button", "text", "sessionId", "value"]) {
|
|
5832
|
+
if (key in normalizedArgs && !(key.toUpperCase() in normalizedArgs)) {
|
|
5833
|
+
normalizedArgs[key.toUpperCase()] = normalizedArgs[key];
|
|
5834
|
+
}
|
|
5835
|
+
}
|
|
5836
|
+
return normalizedArgs;
|
|
5837
|
+
}
|
|
5838
|
+
function parseScriptResult(result) {
|
|
5839
|
+
if (typeof result === "string") {
|
|
5840
|
+
try {
|
|
5841
|
+
const parsed = JSON.parse(result);
|
|
5842
|
+
if (parsed && typeof parsed === "object" && parsed.success === false) {
|
|
5843
|
+
return { success: false, payload: parsed };
|
|
5844
|
+
}
|
|
5845
|
+
return { success: true, payload: parsed };
|
|
5846
|
+
} catch {
|
|
5847
|
+
return { success: true, payload: { result } };
|
|
5848
|
+
}
|
|
5849
|
+
}
|
|
5850
|
+
if (result && typeof result === "object" && result.success === false) {
|
|
5851
|
+
return { success: false, payload: result };
|
|
5852
|
+
}
|
|
5853
|
+
return { success: true, payload: result };
|
|
5854
|
+
}
|
|
5855
|
+
function getCliScriptCommand(payload) {
|
|
5856
|
+
if (!payload || typeof payload !== "object") return null;
|
|
5857
|
+
if (typeof payload.sendMessage === "string" && payload.sendMessage.trim()) {
|
|
5858
|
+
return { type: "send_message", text: payload.sendMessage.trim() };
|
|
5859
|
+
}
|
|
5860
|
+
const command = payload.command;
|
|
5861
|
+
if (!command || typeof command !== "object") return null;
|
|
5862
|
+
if (command.type !== "send_message") return null;
|
|
5863
|
+
const text = typeof command.text === "string" ? command.text.trim() : typeof command.message === "string" ? command.message.trim() : "";
|
|
5864
|
+
if (!text) return null;
|
|
5865
|
+
return { type: "send_message", text };
|
|
5866
|
+
}
|
|
5867
|
+
function applyProviderPatch(h, args, payload) {
|
|
5868
|
+
if (!payload || typeof payload !== "object") return;
|
|
5869
|
+
const targetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
|
|
5870
|
+
const targetSession = targetSessionId ? h.ctx.sessionRegistry?.get(targetSessionId) : void 0;
|
|
5871
|
+
const instanceKey = targetSession?.instanceKey || targetSessionId;
|
|
5872
|
+
if (!instanceKey) return;
|
|
5873
|
+
h.ctx.instanceManager?.sendEvent(instanceKey, "provider_state_patch", {
|
|
5874
|
+
...payload,
|
|
5875
|
+
extensionType: targetSession?.transport === "cdp-webview" ? targetSession.providerType : void 0
|
|
5876
|
+
});
|
|
5877
|
+
}
|
|
5878
|
+
async function executeProviderScript(h, args, scriptName) {
|
|
5392
5879
|
const { agentType, ideType } = args || {};
|
|
5393
5880
|
if (!agentType) return { success: false, error: "agentType is required" };
|
|
5394
5881
|
const loader = h.ctx.providerLoader;
|
|
@@ -5401,13 +5888,29 @@ async function handleExtensionScript(h, args, scriptName) {
|
|
|
5401
5888
|
if (!provider.scripts?.[actualScriptName]) {
|
|
5402
5889
|
return { success: false, error: `Script '${actualScriptName}' not available for ${agentType}` };
|
|
5403
5890
|
}
|
|
5404
|
-
const
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
if (
|
|
5408
|
-
|
|
5891
|
+
const normalizedArgs = normalizeProviderScriptArgs(args);
|
|
5892
|
+
if (provider.category === "cli") {
|
|
5893
|
+
const adapter = h.getCliAdapter(args?.targetSessionId || agentType);
|
|
5894
|
+
if (!adapter?.invokeScript) {
|
|
5895
|
+
return { success: false, error: `CLI adapter does not support script '${actualScriptName}'` };
|
|
5896
|
+
}
|
|
5897
|
+
try {
|
|
5898
|
+
const raw = await adapter.invokeScript(actualScriptName, normalizedArgs);
|
|
5899
|
+
const parsed = parseScriptResult(raw);
|
|
5900
|
+
if (!parsed.success) {
|
|
5901
|
+
return { success: false, ...parsed.payload || {} };
|
|
5902
|
+
}
|
|
5903
|
+
const cliCommand = getCliScriptCommand(parsed.payload);
|
|
5904
|
+
if (cliCommand?.type === "send_message" && cliCommand.text) {
|
|
5905
|
+
await adapter.sendMessage(cliCommand.text);
|
|
5906
|
+
}
|
|
5907
|
+
applyProviderPatch(h, args, parsed.payload);
|
|
5908
|
+
return { success: true, ...parsed.payload && typeof parsed.payload === "object" ? parsed.payload : { result: parsed.payload } };
|
|
5909
|
+
} catch (e) {
|
|
5910
|
+
return { success: false, error: `Script execution failed: ${e.message}` };
|
|
5409
5911
|
}
|
|
5410
5912
|
}
|
|
5913
|
+
const scriptFn = provider.scripts[actualScriptName];
|
|
5411
5914
|
const scriptCode = scriptFn(normalizedArgs);
|
|
5412
5915
|
if (!scriptCode) return { success: false, error: `Script '${actualScriptName}' returned null` };
|
|
5413
5916
|
const cdpKey = provider.category === "ide" ? h.currentSession?.cdpManagerKey || h.currentManagerKey || agentType : h.currentSession?.cdpManagerKey || h.currentManagerKey || ideType;
|
|
@@ -5461,16 +5964,29 @@ async function handleExtensionScript(h, args, scriptName) {
|
|
|
5461
5964
|
if (typeof result === "string") {
|
|
5462
5965
|
try {
|
|
5463
5966
|
const parsed = JSON.parse(result);
|
|
5967
|
+
applyProviderPatch(h, args, parsed);
|
|
5968
|
+
if (parsed && typeof parsed === "object" && parsed.success === false) {
|
|
5969
|
+
return { success: false, ...parsed };
|
|
5970
|
+
}
|
|
5464
5971
|
return { success: true, ...parsed };
|
|
5465
5972
|
} catch {
|
|
5466
5973
|
return { success: true, result };
|
|
5467
5974
|
}
|
|
5468
5975
|
}
|
|
5976
|
+
applyProviderPatch(h, args, result);
|
|
5469
5977
|
return { success: true, result };
|
|
5470
5978
|
} catch (e) {
|
|
5471
5979
|
return { success: false, error: `Script execution failed: ${e.message}` };
|
|
5472
5980
|
}
|
|
5473
5981
|
}
|
|
5982
|
+
async function handleExtensionScript(h, args, scriptName) {
|
|
5983
|
+
return executeProviderScript(h, args, scriptName);
|
|
5984
|
+
}
|
|
5985
|
+
async function handleProviderScript(h, args) {
|
|
5986
|
+
const scriptName = typeof args?.scriptName === "string" ? args.scriptName.trim() : "";
|
|
5987
|
+
if (!scriptName) return { success: false, error: "scriptName is required" };
|
|
5988
|
+
return executeProviderScript(h, args, scriptName);
|
|
5989
|
+
}
|
|
5474
5990
|
function handleGetIdeExtensions(h, args) {
|
|
5475
5991
|
const { ideType } = args || {};
|
|
5476
5992
|
const loader = h.ctx.providerLoader;
|
|
@@ -5700,6 +6216,7 @@ var init_handler = __esm({
|
|
|
5700
6216
|
init_devtools();
|
|
5701
6217
|
init_builders();
|
|
5702
6218
|
init_chat_history();
|
|
6219
|
+
init_reconcile();
|
|
5703
6220
|
init_logger();
|
|
5704
6221
|
init_chat_commands();
|
|
5705
6222
|
init_cdp_commands();
|
|
@@ -5834,17 +6351,27 @@ var init_handler = __esm({
|
|
|
5834
6351
|
return key.split("_")[0];
|
|
5835
6352
|
}
|
|
5836
6353
|
resolveRoute(args) {
|
|
5837
|
-
const
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
6354
|
+
const targetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
|
|
6355
|
+
let session = targetSessionId ? this._ctx.sessionRegistry?.get(targetSessionId) : void 0;
|
|
6356
|
+
if (targetSessionId && !session) {
|
|
6357
|
+
reconcileIdeRuntimeSessions(this._ctx.instanceManager, this._ctx.sessionRegistry);
|
|
6358
|
+
session = this._ctx.sessionRegistry?.get(targetSessionId);
|
|
6359
|
+
}
|
|
6360
|
+
const sessionLookupFailed = !!targetSessionId && !session;
|
|
6361
|
+
const managerKey = this.extractIdeType(args, sessionLookupFailed);
|
|
6362
|
+
let providerType;
|
|
6363
|
+
if (!sessionLookupFailed) {
|
|
6364
|
+
providerType = session?.providerType || args?.agentType || args?.providerType || this.inferProviderType(managerKey);
|
|
6365
|
+
}
|
|
6366
|
+
return { session, managerKey, providerType, sessionLookupFailed };
|
|
5841
6367
|
}
|
|
5842
6368
|
/** Extract CDP scope key from target session or explicit ideType */
|
|
5843
|
-
extractIdeType(args) {
|
|
6369
|
+
extractIdeType(args, sessionLookupFailed = false) {
|
|
5844
6370
|
if (args?.targetSessionId) {
|
|
5845
6371
|
const target = this._ctx.sessionRegistry?.get(args.targetSessionId);
|
|
5846
6372
|
if (target?.cdpManagerKey) return target.cdpManagerKey;
|
|
5847
6373
|
if (this._ctx.cdpManagers.has(args.targetSessionId)) return args.targetSessionId;
|
|
6374
|
+
if (sessionLookupFailed) return void 0;
|
|
5848
6375
|
}
|
|
5849
6376
|
if (args?.ideType) {
|
|
5850
6377
|
const target = this._ctx.sessionRegistry?.get(args.ideType);
|
|
@@ -5891,6 +6418,33 @@ var init_handler = __esm({
|
|
|
5891
6418
|
this._currentRoute = this.resolveRoute(args);
|
|
5892
6419
|
const startedAt = Date.now();
|
|
5893
6420
|
this.logCommandStart(cmd, args);
|
|
6421
|
+
const sessionScopedCommands = /* @__PURE__ */ new Set([
|
|
6422
|
+
"read_chat",
|
|
6423
|
+
"send_chat",
|
|
6424
|
+
"list_chats",
|
|
6425
|
+
"new_chat",
|
|
6426
|
+
"switch_chat",
|
|
6427
|
+
"set_mode",
|
|
6428
|
+
"change_model",
|
|
6429
|
+
"set_thought_level",
|
|
6430
|
+
"resolve_action",
|
|
6431
|
+
"focus_session",
|
|
6432
|
+
"pty_input",
|
|
6433
|
+
"pty_resize",
|
|
6434
|
+
"invoke_provider_script",
|
|
6435
|
+
"list_extension_models",
|
|
6436
|
+
"set_extension_model",
|
|
6437
|
+
"list_extension_modes",
|
|
6438
|
+
"set_extension_mode"
|
|
6439
|
+
]);
|
|
6440
|
+
if (this._currentRoute.sessionLookupFailed && sessionScopedCommands.has(cmd)) {
|
|
6441
|
+
const result2 = {
|
|
6442
|
+
success: false,
|
|
6443
|
+
error: `Live session not found for targetSessionId: ${String(args?.targetSessionId || "").trim() || "unknown"}`
|
|
6444
|
+
};
|
|
6445
|
+
this.logCommandEnd(cmd, result2, startedAt);
|
|
6446
|
+
return result2;
|
|
6447
|
+
}
|
|
5894
6448
|
let result;
|
|
5895
6449
|
if (!this._currentRoute.session && !this._currentRoute.managerKey && !this._currentRoute.providerType) {
|
|
5896
6450
|
const cdpCommands = ["send_chat", "read_chat", "list_chats", "new_chat", "switch_chat", "set_mode", "change_model", "set_thought_level", "resolve_action"];
|
|
@@ -5994,6 +6548,8 @@ var init_handler = __esm({
|
|
|
5994
6548
|
case "set_ide_extension":
|
|
5995
6549
|
return handleSetIdeExtension(this, args);
|
|
5996
6550
|
// ─── Extension Model / Mode Control (stream-commands.ts) ──────────
|
|
6551
|
+
case "invoke_provider_script":
|
|
6552
|
+
return handleProviderScript(this, args);
|
|
5997
6553
|
case "list_extension_models":
|
|
5998
6554
|
return handleExtensionScript(this, args, "listModels");
|
|
5999
6555
|
case "set_extension_model":
|
|
@@ -6678,6 +7234,53 @@ function stripTerminalNoise(str) {
|
|
|
6678
7234
|
function sanitizeTerminalText(str) {
|
|
6679
7235
|
return stripTerminalNoise(stripAnsi(str));
|
|
6680
7236
|
}
|
|
7237
|
+
function splitCliScreenLines(text) {
|
|
7238
|
+
return String(text || "").replace(/\u0007/g, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n").map((line) => line.replace(/\s+$/, ""));
|
|
7239
|
+
}
|
|
7240
|
+
function isPromptLikeCliLine(line) {
|
|
7241
|
+
const trimmed = String(line || "").trim();
|
|
7242
|
+
if (!trimmed) return false;
|
|
7243
|
+
return /^[❯›>]\s*(?:$|\S.*)$/.test(trimmed);
|
|
7244
|
+
}
|
|
7245
|
+
function buildCliScreenSnapshot(text) {
|
|
7246
|
+
const normalizedText = String(text || "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
7247
|
+
const rawLines = splitCliScreenLines(normalizedText);
|
|
7248
|
+
const lines = rawLines.map((line, index, arr) => {
|
|
7249
|
+
const trimmed = String(line || "").trim();
|
|
7250
|
+
return {
|
|
7251
|
+
index,
|
|
7252
|
+
fromTop: index,
|
|
7253
|
+
fromBottom: arr.length - index - 1,
|
|
7254
|
+
text: line,
|
|
7255
|
+
trimmed,
|
|
7256
|
+
isEmpty: trimmed.length === 0
|
|
7257
|
+
};
|
|
7258
|
+
});
|
|
7259
|
+
const nonEmptyLines = lines.filter((line) => !line.isEmpty);
|
|
7260
|
+
const firstNonEmptyLine = nonEmptyLines[0] ?? null;
|
|
7261
|
+
const lastNonEmptyLine = nonEmptyLines[nonEmptyLines.length - 1] ?? null;
|
|
7262
|
+
let promptLineIndex = -1;
|
|
7263
|
+
for (let i = lines.length - 1; i >= 0; i -= 1) {
|
|
7264
|
+
if (isPromptLikeCliLine(lines[i].text)) {
|
|
7265
|
+
promptLineIndex = i;
|
|
7266
|
+
break;
|
|
7267
|
+
}
|
|
7268
|
+
}
|
|
7269
|
+
return {
|
|
7270
|
+
text: normalizedText,
|
|
7271
|
+
lineCount: lines.length,
|
|
7272
|
+
lines,
|
|
7273
|
+
nonEmptyLines,
|
|
7274
|
+
firstNonEmptyLineIndex: firstNonEmptyLine?.index ?? -1,
|
|
7275
|
+
lastNonEmptyLineIndex: lastNonEmptyLine?.index ?? -1,
|
|
7276
|
+
firstNonEmptyLine,
|
|
7277
|
+
lastNonEmptyLine,
|
|
7278
|
+
promptLineIndex,
|
|
7279
|
+
promptLine: promptLineIndex >= 0 ? lines[promptLineIndex] : null,
|
|
7280
|
+
linesAbovePrompt: promptLineIndex >= 0 ? lines.slice(0, promptLineIndex) : [...lines],
|
|
7281
|
+
linesBelowPrompt: promptLineIndex >= 0 ? lines.slice(promptLineIndex + 1) : []
|
|
7282
|
+
};
|
|
7283
|
+
}
|
|
6681
7284
|
function computeTerminalQueryTail(buffer) {
|
|
6682
7285
|
const prefixes = ["\x1B[6n", "\x1B[?6n"];
|
|
6683
7286
|
const maxLength = prefixes.reduce((n, value) => Math.max(n, value.length), 0) - 1;
|
|
@@ -6919,7 +7522,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
6919
7522
|
ready = false;
|
|
6920
7523
|
startupBuffer = "";
|
|
6921
7524
|
startupParseGate = false;
|
|
7525
|
+
startupSettleTimer = null;
|
|
6922
7526
|
spawnAt = 0;
|
|
7527
|
+
startupFirstOutputAt = 0;
|
|
6923
7528
|
// PTY I/O
|
|
6924
7529
|
onPtyDataCallback = null;
|
|
6925
7530
|
pendingOutputParseBuffer = "";
|
|
@@ -6960,6 +7565,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
6960
7565
|
statusHistory = [];
|
|
6961
7566
|
// ─── CLI Scripts (script-based parsing) ───
|
|
6962
7567
|
cliScripts;
|
|
7568
|
+
runtimeSettings = {};
|
|
6963
7569
|
/** Full accumulated ANSI-stripped PTY output */
|
|
6964
7570
|
accumulatedBuffer = "";
|
|
6965
7571
|
/** Full accumulated raw PTY output (with ANSI) */
|
|
@@ -6974,14 +7580,15 @@ var init_provider_cli_adapter = __esm({
|
|
|
6974
7580
|
traceSessionId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
6975
7581
|
static MAX_TRACE_ENTRIES = 250;
|
|
6976
7582
|
providerResolutionMeta;
|
|
6977
|
-
static IDLE_FINISH_CONFIRM_MS =
|
|
7583
|
+
static IDLE_FINISH_CONFIRM_MS = 2e3;
|
|
7584
|
+
static STATUS_ACTIVITY_HOLD_MS = 2e3;
|
|
6978
7585
|
static FINISH_RETRY_DELAY_MS = 300;
|
|
6979
7586
|
static MAX_FINISH_RETRIES = 2;
|
|
6980
7587
|
syncMessageViews() {
|
|
6981
7588
|
this.messages = [...this.committedMessages];
|
|
6982
7589
|
this.structuredMessages = [...this.committedMessages];
|
|
6983
7590
|
}
|
|
6984
|
-
|
|
7591
|
+
hydrateParsedMessages(parsedMessages, scope) {
|
|
6985
7592
|
const referenceMessages = [...this.committedMessages];
|
|
6986
7593
|
const usedReferenceIndexes = /* @__PURE__ */ new Set();
|
|
6987
7594
|
const now = Date.now();
|
|
@@ -7014,13 +7621,30 @@ var init_provider_cli_adapter = __esm({
|
|
|
7014
7621
|
const content = typeof message.content === "string" ? message.content : String(message.content || "");
|
|
7015
7622
|
const parsedTimestamp = typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : void 0;
|
|
7016
7623
|
const referenceTimestamp = parsedTimestamp ?? findReferenceTimestamp(role, content, index);
|
|
7624
|
+
const fallbackTimestamp = role === "user" ? scope?.startedAt || now : this.lastOutputAt || scope?.startedAt || now;
|
|
7625
|
+
const timestamp = referenceTimestamp ?? fallbackTimestamp;
|
|
7017
7626
|
return {
|
|
7627
|
+
...message,
|
|
7018
7628
|
role,
|
|
7019
7629
|
content,
|
|
7020
|
-
timestamp
|
|
7630
|
+
timestamp,
|
|
7631
|
+
receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : timestamp
|
|
7021
7632
|
};
|
|
7022
7633
|
});
|
|
7023
7634
|
}
|
|
7635
|
+
normalizeParsedMessages(parsedMessages, scope) {
|
|
7636
|
+
return this.hydrateParsedMessages(parsedMessages, scope).map((message) => ({
|
|
7637
|
+
role: message.role,
|
|
7638
|
+
content: message.content,
|
|
7639
|
+
timestamp: message.timestamp,
|
|
7640
|
+
receivedAt: message.receivedAt,
|
|
7641
|
+
kind: message.kind,
|
|
7642
|
+
id: message.id,
|
|
7643
|
+
index: message.index,
|
|
7644
|
+
meta: message.meta,
|
|
7645
|
+
senderName: message.senderName
|
|
7646
|
+
}));
|
|
7647
|
+
}
|
|
7024
7648
|
sliceFromOffset(text, start) {
|
|
7025
7649
|
if (!text) return "";
|
|
7026
7650
|
if (!Number.isFinite(start) || start <= 0) return text;
|
|
@@ -7030,14 +7654,20 @@ var init_provider_cli_adapter = __esm({
|
|
|
7030
7654
|
buildParseInput(baseMessages, partialResponse, scope) {
|
|
7031
7655
|
const buffer = scope ? this.sliceFromOffset(this.accumulatedBuffer, scope.bufferStart) || this.accumulatedBuffer : this.accumulatedBuffer;
|
|
7032
7656
|
const rawBuffer = scope ? this.sliceFromOffset(this.accumulatedRawBuffer, scope.rawBufferStart) || this.accumulatedRawBuffer : this.accumulatedRawBuffer;
|
|
7657
|
+
const screenText = this.terminalScreen.getText();
|
|
7658
|
+
const recentBuffer = buffer.slice(-1e3) || this.recentOutputBuffer;
|
|
7033
7659
|
return {
|
|
7034
7660
|
buffer,
|
|
7035
7661
|
rawBuffer,
|
|
7036
|
-
recentBuffer
|
|
7037
|
-
screenText
|
|
7662
|
+
recentBuffer,
|
|
7663
|
+
screenText,
|
|
7664
|
+
screen: buildCliScreenSnapshot(screenText),
|
|
7665
|
+
bufferScreen: buildCliScreenSnapshot(buffer),
|
|
7666
|
+
recentScreen: buildCliScreenSnapshot(recentBuffer),
|
|
7038
7667
|
messages: [...baseMessages],
|
|
7039
7668
|
partialResponse,
|
|
7040
|
-
promptText: scope?.prompt || ""
|
|
7669
|
+
promptText: scope?.prompt || "",
|
|
7670
|
+
settings: { ...this.runtimeSettings }
|
|
7041
7671
|
};
|
|
7042
7672
|
}
|
|
7043
7673
|
setStatus(status, trigger) {
|
|
@@ -7143,6 +7773,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
7143
7773
|
const scriptNames = Object.keys(scripts).filter((k) => typeof scripts[k] === "function");
|
|
7144
7774
|
LOG.info("CLI", `[${this.cliType}] CLI scripts injected: [${scriptNames.join(", ")}]`);
|
|
7145
7775
|
}
|
|
7776
|
+
updateRuntimeSettings(settings) {
|
|
7777
|
+
this.runtimeSettings = { ...settings };
|
|
7778
|
+
}
|
|
7146
7779
|
// ─── Lifecycle ─────────────────────────────────
|
|
7147
7780
|
setServerConn(serverConn) {
|
|
7148
7781
|
this.serverConn = serverConn;
|
|
@@ -7277,6 +7910,11 @@ var init_provider_cli_adapter = __esm({
|
|
|
7277
7910
|
this.spawnAt = Date.now();
|
|
7278
7911
|
this.startupParseGate = true;
|
|
7279
7912
|
this.startupBuffer = "";
|
|
7913
|
+
this.startupFirstOutputAt = 0;
|
|
7914
|
+
if (this.startupSettleTimer) {
|
|
7915
|
+
clearTimeout(this.startupSettleTimer);
|
|
7916
|
+
this.startupSettleTimer = null;
|
|
7917
|
+
}
|
|
7280
7918
|
this.terminalScreen.reset(24, 80);
|
|
7281
7919
|
this.pendingTerminalQueryTail = "";
|
|
7282
7920
|
this.currentTurnScope = null;
|
|
@@ -7290,7 +7928,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
7290
7928
|
this.recordTrace("ready", {
|
|
7291
7929
|
runtimeMeta: this.getRuntimeMetadata()
|
|
7292
7930
|
});
|
|
7293
|
-
this.setStatus("
|
|
7931
|
+
this.setStatus("starting", "pty_ready");
|
|
7932
|
+
this.scheduleStartupSettleCheck();
|
|
7294
7933
|
this.onStatusChange?.();
|
|
7295
7934
|
}
|
|
7296
7935
|
// ─── Output Handling ────────────────────────────
|
|
@@ -7305,6 +7944,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
7305
7944
|
this.lastScreenSnapshot = normalizedScreenSnapshot;
|
|
7306
7945
|
this.lastScreenChangeAt = now;
|
|
7307
7946
|
}
|
|
7947
|
+
if (this.startupParseGate && !this.startupFirstOutputAt && (cleanData.trim() || normalizedScreenSnapshot.trim())) {
|
|
7948
|
+
this.startupFirstOutputAt = now;
|
|
7949
|
+
}
|
|
7308
7950
|
if (this.idleFinishCandidate && (rawData.length > 0 || cleanData.length > 0)) {
|
|
7309
7951
|
this.clearIdleFinishCandidate("new_output");
|
|
7310
7952
|
}
|
|
@@ -7315,6 +7957,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
7315
7957
|
cleanPreview: this.summarizeTraceText(cleanData, 300),
|
|
7316
7958
|
screenText: this.summarizeTraceText(this.terminalScreen.getText(), 1200)
|
|
7317
7959
|
});
|
|
7960
|
+
if (this.startupParseGate) {
|
|
7961
|
+
this.scheduleStartupSettleCheck();
|
|
7962
|
+
}
|
|
7318
7963
|
if (this.isWaitingForResponse && cleanData) {
|
|
7319
7964
|
this.responseBuffer = (this.responseBuffer + cleanData).slice(-8e3);
|
|
7320
7965
|
}
|
|
@@ -7328,27 +7973,51 @@ var init_provider_cli_adapter = __esm({
|
|
|
7328
7973
|
this.recentOutputBuffer = (this.recentOutputBuffer + cleanData).slice(-1e3);
|
|
7329
7974
|
this.accumulatedBuffer = (this.accumulatedBuffer + cleanData).slice(-_ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
|
|
7330
7975
|
this.accumulatedRawBuffer = (this.accumulatedRawBuffer + rawData).slice(-_ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
|
|
7331
|
-
|
|
7332
|
-
this.startupBuffer += cleanData;
|
|
7333
|
-
const elapsed = Date.now() - this.spawnAt;
|
|
7334
|
-
const screenText = this.terminalScreen.getText() || "";
|
|
7335
|
-
const startupModal = this.getStartupConfirmationModal(screenText);
|
|
7336
|
-
const scriptStatus = startupModal ? "waiting_approval" : this.runDetectStatus(this.startupBuffer);
|
|
7337
|
-
const hasInteractivePrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
7338
|
-
const startupStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
7339
|
-
const isReady = (scriptStatus === "idle" || scriptStatus === "waiting_approval") && hasInteractivePrompt && startupStableMs >= 700 || !!startupModal && startupStableMs >= 700 || elapsed > 8e3 || this.startupBuffer.length > 12e3;
|
|
7340
|
-
if (isReady) {
|
|
7341
|
-
this.startupParseGate = false;
|
|
7342
|
-
this.ready = true;
|
|
7343
|
-
LOG.info(
|
|
7344
|
-
"CLI",
|
|
7345
|
-
`[${this.cliType}] Startup ready (${elapsed}ms, scriptStatus=${scriptStatus}, prompt=${hasInteractivePrompt}, stableMs=${startupStableMs}) providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"} scriptsPath=${this.providerResolutionMeta.scriptsPath || "-"}`
|
|
7346
|
-
);
|
|
7347
|
-
this.onStatusChange?.();
|
|
7348
|
-
}
|
|
7349
|
-
}
|
|
7976
|
+
this.resolveStartupState("output");
|
|
7350
7977
|
this.scheduleSettle();
|
|
7351
7978
|
}
|
|
7979
|
+
resolveStartupState(trigger) {
|
|
7980
|
+
if (!this.startupParseGate) return;
|
|
7981
|
+
const now = Date.now();
|
|
7982
|
+
const screenText = this.terminalScreen.getText() || "";
|
|
7983
|
+
const normalizedScreen = normalizeScreenSnapshot(screenText);
|
|
7984
|
+
const hasStartupOutput = !!this.startupFirstOutputAt || !!normalizedScreen.trim();
|
|
7985
|
+
if (!hasStartupOutput) return;
|
|
7986
|
+
const stableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
7987
|
+
if (stableMs < 2e3) return;
|
|
7988
|
+
const startupModal = this.getStartupConfirmationModal(screenText);
|
|
7989
|
+
this.startupParseGate = false;
|
|
7990
|
+
if (this.startupSettleTimer) {
|
|
7991
|
+
clearTimeout(this.startupSettleTimer);
|
|
7992
|
+
this.startupSettleTimer = null;
|
|
7993
|
+
}
|
|
7994
|
+
this.ready = true;
|
|
7995
|
+
if (startupModal) {
|
|
7996
|
+
this.activeModal = startupModal;
|
|
7997
|
+
this.setStatus("waiting_approval", `startup_ready:${trigger}`);
|
|
7998
|
+
} else {
|
|
7999
|
+
this.setStatus("idle", `startup_ready:${trigger}`);
|
|
8000
|
+
}
|
|
8001
|
+
LOG.info(
|
|
8002
|
+
"CLI",
|
|
8003
|
+
`[${this.cliType}] Startup settled (${trigger}, stableMs=${stableMs}, modal=${!!startupModal}) providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"} scriptsPath=${this.providerResolutionMeta.scriptsPath || "-"}`
|
|
8004
|
+
);
|
|
8005
|
+
this.onStatusChange?.();
|
|
8006
|
+
}
|
|
8007
|
+
scheduleStartupSettleCheck() {
|
|
8008
|
+
if (!this.startupParseGate) return;
|
|
8009
|
+
if (this.startupSettleTimer) clearTimeout(this.startupSettleTimer);
|
|
8010
|
+
const now = Date.now();
|
|
8011
|
+
const stableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
8012
|
+
const delayMs = Math.max(250, 2050 - stableMs);
|
|
8013
|
+
this.startupSettleTimer = setTimeout(() => {
|
|
8014
|
+
this.startupSettleTimer = null;
|
|
8015
|
+
this.resolveStartupState("startup_timer");
|
|
8016
|
+
if (this.startupParseGate && Date.now() - this.spawnAt < 1e4) {
|
|
8017
|
+
this.scheduleStartupSettleCheck();
|
|
8018
|
+
}
|
|
8019
|
+
}, delayMs);
|
|
8020
|
+
}
|
|
7352
8021
|
scheduleSettle() {
|
|
7353
8022
|
if (this.settleTimer) clearTimeout(this.settleTimer);
|
|
7354
8023
|
const settleEpoch = this.responseEpoch;
|
|
@@ -7415,11 +8084,14 @@ var init_provider_cli_adapter = __esm({
|
|
|
7415
8084
|
if (allLines.length === 0) return false;
|
|
7416
8085
|
const recentLines = allLines.slice(-12);
|
|
7417
8086
|
const promptIndex = this.findLastMatchingLineIndex(recentLines, (line) => /^[❯›>]\s*$/.test(line));
|
|
7418
|
-
const activeRegion = promptIndex >= 0 ? recentLines.slice(promptIndex
|
|
8087
|
+
const activeRegion = promptIndex >= 0 ? recentLines.slice(Math.max(0, promptIndex - 2), promptIndex) : recentLines;
|
|
7419
8088
|
if (activeRegion.length === 0) return false;
|
|
7420
8089
|
return activeRegion.some((line) => this.looksLikeClaudeGeneratingLine(line));
|
|
7421
8090
|
}
|
|
7422
8091
|
refineDetectedStatus(status, tail, screenText) {
|
|
8092
|
+
if (this.startupParseGate) {
|
|
8093
|
+
return this.getStartupConfirmationModal(screenText || "") ? "waiting_approval" : "starting";
|
|
8094
|
+
}
|
|
7423
8095
|
if (status === "waiting_approval") return status;
|
|
7424
8096
|
if (this.detectClaudeGeneratingOverride(screenText || "", tail)) return "generating";
|
|
7425
8097
|
return status;
|
|
@@ -7458,6 +8130,11 @@ var init_provider_cli_adapter = __esm({
|
|
|
7458
8130
|
const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
7459
8131
|
return quietForMs < 1200 || screenStableMs < 1200 || !commitResult.hasAssistant;
|
|
7460
8132
|
}
|
|
8133
|
+
hasRecentInteractiveActivity(now) {
|
|
8134
|
+
const quietForMs = this.lastNonEmptyOutputAt ? now - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
|
|
8135
|
+
const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : Number.MAX_SAFE_INTEGER;
|
|
8136
|
+
return quietForMs < _ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS || screenStableMs < _ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS;
|
|
8137
|
+
}
|
|
7461
8138
|
getStartupConfirmationModal(screenText) {
|
|
7462
8139
|
const text = sanitizeTerminalText(String(screenText || ""));
|
|
7463
8140
|
if (!text.trim()) return null;
|
|
@@ -7485,13 +8162,14 @@ var init_provider_cli_adapter = __esm({
|
|
|
7485
8162
|
const startedAt = Date.now();
|
|
7486
8163
|
let loggedWait = false;
|
|
7487
8164
|
while (Date.now() - startedAt < maxWaitMs) {
|
|
8165
|
+
this.resolveStartupState("interactive_wait");
|
|
7488
8166
|
const screenText = this.terminalScreen.getText() || "";
|
|
7489
8167
|
const hasPrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
7490
8168
|
const stableMs = this.lastScreenChangeAt ? Date.now() - this.lastScreenChangeAt : 0;
|
|
7491
8169
|
const recentlyOutput = this.lastNonEmptyOutputAt ? Date.now() - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
|
|
7492
8170
|
const status = this.runDetectStatus(this.recentOutputBuffer) || this.currentStatus;
|
|
7493
8171
|
const startupLikelyActive = /Welcome back|Tips for getting|Recent activity|Claude Code v\d/i.test(screenText);
|
|
7494
|
-
const interactiveReady = hasPrompt && stableMs >= 700 && recentlyOutput >= 350 && status !== "
|
|
8172
|
+
const interactiveReady = hasPrompt && stableMs >= 700 && recentlyOutput >= 350 && status !== "generating";
|
|
7495
8173
|
if (interactiveReady) {
|
|
7496
8174
|
if (loggedWait) {
|
|
7497
8175
|
LOG.info(
|
|
@@ -7530,6 +8208,10 @@ var init_provider_cli_adapter = __esm({
|
|
|
7530
8208
|
}
|
|
7531
8209
|
const tail = this.settledBuffer;
|
|
7532
8210
|
const screenText = this.terminalScreen.getText() || "";
|
|
8211
|
+
this.resolveStartupState("settled");
|
|
8212
|
+
if (this.startupParseGate) {
|
|
8213
|
+
return;
|
|
8214
|
+
}
|
|
7533
8215
|
const startupModal = this.getStartupConfirmationModal(screenText);
|
|
7534
8216
|
const modal = this.runParseApproval(tail) || startupModal;
|
|
7535
8217
|
const rawScriptStatus = this.runDetectStatus(tail);
|
|
@@ -7592,6 +8274,28 @@ var init_provider_cli_adapter = __esm({
|
|
|
7592
8274
|
} else {
|
|
7593
8275
|
clearPendingScriptStatus();
|
|
7594
8276
|
}
|
|
8277
|
+
const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
|
|
8278
|
+
const shouldHoldGenerating = scriptStatus === "idle" && this.isWaitingForResponse && !modal && recentInteractiveActivity;
|
|
8279
|
+
if (shouldHoldGenerating) {
|
|
8280
|
+
this.clearIdleFinishCandidate("hold_generating_recent_activity");
|
|
8281
|
+
this.setStatus("generating", "recent_activity_hold");
|
|
8282
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
8283
|
+
this.idleTimeout = setTimeout(() => {
|
|
8284
|
+
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
8285
|
+
this.finishResponse();
|
|
8286
|
+
}
|
|
8287
|
+
}, this.timeouts.generatingIdle);
|
|
8288
|
+
this.recordTrace("hold_generating_recent_activity", {
|
|
8289
|
+
scriptStatus,
|
|
8290
|
+
recentInteractiveActivity,
|
|
8291
|
+
lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
|
|
8292
|
+
lastScreenChangeAt: this.lastScreenChangeAt,
|
|
8293
|
+
holdMs: _ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS,
|
|
8294
|
+
...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
|
|
8295
|
+
});
|
|
8296
|
+
this.onStatusChange?.();
|
|
8297
|
+
return;
|
|
8298
|
+
}
|
|
7595
8299
|
if (scriptStatus === "waiting_approval") {
|
|
7596
8300
|
this.clearIdleFinishCandidate("waiting_approval");
|
|
7597
8301
|
const inCooldown = this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
|
|
@@ -7669,8 +8373,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
7669
8373
|
const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
7670
8374
|
const hasAssistantTurn = !!lastParsedAssistant;
|
|
7671
8375
|
const assistantLength = lastParsedAssistant?.content?.length || 0;
|
|
7672
|
-
const idleQuietThresholdMs = Math.max(
|
|
7673
|
-
const idleStableThresholdMs =
|
|
8376
|
+
const idleQuietThresholdMs = Math.max(2e3, this.timeouts.outputSettle);
|
|
8377
|
+
const idleStableThresholdMs = 2e3;
|
|
7674
8378
|
const idleReady = visibleIdlePrompt && !modal && hasAssistantTurn && quietForMs >= idleQuietThresholdMs && screenStableMs >= idleStableThresholdMs;
|
|
7675
8379
|
const candidate = this.idleFinishCandidate;
|
|
7676
8380
|
const candidateQuiet = !!candidate && candidate.responseEpoch === this.responseEpoch && candidate.lastOutputAt === this.lastOutputAt && candidate.lastScreenChangeAt === this.lastScreenChangeAt && assistantLength >= candidate.assistantLength && now - candidate.armedAt >= _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS;
|
|
@@ -7784,7 +8488,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
7784
8488
|
this.currentTurnScope
|
|
7785
8489
|
);
|
|
7786
8490
|
if (parsed && Array.isArray(parsed.messages)) {
|
|
7787
|
-
this.committedMessages = this.normalizeParsedMessages(parsed.messages);
|
|
8491
|
+
this.committedMessages = this.normalizeParsedMessages(parsed.messages, this.currentTurnScope);
|
|
7788
8492
|
const promptForTrim = this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages);
|
|
7789
8493
|
if (promptForTrim) {
|
|
7790
8494
|
const lastAssistantForTrim = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
|
|
@@ -7825,7 +8529,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
7825
8529
|
const status = this.cliScripts.detectStatus({
|
|
7826
8530
|
tail: text.slice(-500),
|
|
7827
8531
|
screenText,
|
|
7828
|
-
rawBuffer: this.accumulatedRawBuffer
|
|
8532
|
+
rawBuffer: this.accumulatedRawBuffer,
|
|
8533
|
+
screen: buildCliScreenSnapshot(screenText),
|
|
8534
|
+
tailScreen: buildCliScreenSnapshot(text.slice(-500))
|
|
7829
8535
|
});
|
|
7830
8536
|
return this.refineDetectedStatus(status, text, screenText || "");
|
|
7831
8537
|
} catch (e) {
|
|
@@ -7836,11 +8542,16 @@ var init_provider_cli_adapter = __esm({
|
|
|
7836
8542
|
runParseApproval(tail) {
|
|
7837
8543
|
if (!this.cliScripts?.parseApproval) return null;
|
|
7838
8544
|
try {
|
|
8545
|
+
const screenText = this.terminalScreen.getText();
|
|
8546
|
+
const buffer = screenText || this.accumulatedBuffer;
|
|
7839
8547
|
return this.cliScripts.parseApproval({
|
|
7840
|
-
buffer
|
|
7841
|
-
screenText
|
|
8548
|
+
buffer,
|
|
8549
|
+
screenText,
|
|
7842
8550
|
rawBuffer: this.accumulatedRawBuffer,
|
|
7843
|
-
tail
|
|
8551
|
+
tail,
|
|
8552
|
+
screen: buildCliScreenSnapshot(screenText),
|
|
8553
|
+
bufferScreen: buildCliScreenSnapshot(buffer),
|
|
8554
|
+
tailScreen: buildCliScreenSnapshot(tail)
|
|
7844
8555
|
});
|
|
7845
8556
|
} catch (e) {
|
|
7846
8557
|
LOG.warn("CLI", `[${this.cliType}] parseApproval error: ${e.message}`);
|
|
@@ -7856,6 +8567,21 @@ var init_provider_cli_adapter = __esm({
|
|
|
7856
8567
|
activeModal: this.activeModal
|
|
7857
8568
|
};
|
|
7858
8569
|
}
|
|
8570
|
+
seedCommittedMessages(messages) {
|
|
8571
|
+
const normalized = (Array.isArray(messages) ? messages : []).filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message) => ({
|
|
8572
|
+
role: message.role,
|
|
8573
|
+
content: typeof message.content === "string" ? message.content : String(message.content || ""),
|
|
8574
|
+
timestamp: typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : void 0,
|
|
8575
|
+
receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : void 0,
|
|
8576
|
+
kind: typeof message.kind === "string" ? message.kind : void 0,
|
|
8577
|
+
id: typeof message.id === "string" ? message.id : void 0,
|
|
8578
|
+
index: typeof message.index === "number" ? message.index : void 0,
|
|
8579
|
+
meta: message.meta && typeof message.meta === "object" ? { ...message.meta } : void 0,
|
|
8580
|
+
senderName: typeof message.senderName === "string" ? message.senderName : void 0
|
|
8581
|
+
}));
|
|
8582
|
+
this.committedMessages = normalized;
|
|
8583
|
+
this.syncMessageViews();
|
|
8584
|
+
}
|
|
7859
8585
|
/**
|
|
7860
8586
|
* Script-based full parse — returns ReadChatResult.
|
|
7861
8587
|
* Called by command handler / dashboard for rich content rendering.
|
|
@@ -7866,12 +8592,20 @@ var init_provider_cli_adapter = __esm({
|
|
|
7866
8592
|
this.responseBuffer,
|
|
7867
8593
|
this.currentTurnScope
|
|
7868
8594
|
);
|
|
8595
|
+
const shouldPreferCommittedMessages = !this.currentTurnScope && this.currentStatus === "idle" && !this.activeModal;
|
|
7869
8596
|
if (parsed && Array.isArray(parsed.messages)) {
|
|
8597
|
+
const hydratedMessages = shouldPreferCommittedMessages ? this.committedMessages.map((message, index) => ({
|
|
8598
|
+
...message,
|
|
8599
|
+
id: message.id || `msg_${index}`,
|
|
8600
|
+
index: typeof message.index === "number" ? message.index : index,
|
|
8601
|
+
kind: message.kind || "standard",
|
|
8602
|
+
receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
|
|
8603
|
+
})) : this.hydrateParsedMessages(parsed.messages, this.currentTurnScope);
|
|
7870
8604
|
return {
|
|
7871
8605
|
id: parsed.id || "cli_session",
|
|
7872
8606
|
status: parsed.status || this.currentStatus,
|
|
7873
8607
|
title: parsed.title || this.cliName,
|
|
7874
|
-
messages:
|
|
8608
|
+
messages: hydratedMessages,
|
|
7875
8609
|
activeModal: parsed.activeModal ?? this.activeModal,
|
|
7876
8610
|
providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0
|
|
7877
8611
|
};
|
|
@@ -7892,6 +8626,21 @@ var init_provider_cli_adapter = __esm({
|
|
|
7892
8626
|
activeModal: this.activeModal
|
|
7893
8627
|
};
|
|
7894
8628
|
}
|
|
8629
|
+
async invokeScript(scriptName, args) {
|
|
8630
|
+
const fn = this.cliScripts?.[scriptName];
|
|
8631
|
+
if (typeof fn !== "function") {
|
|
8632
|
+
throw new Error(`CLI script '${scriptName}' not available`);
|
|
8633
|
+
}
|
|
8634
|
+
const input = this.buildParseInput(
|
|
8635
|
+
this.committedMessages,
|
|
8636
|
+
this.responseBuffer,
|
|
8637
|
+
this.currentTurnScope
|
|
8638
|
+
);
|
|
8639
|
+
return await Promise.resolve(fn({
|
|
8640
|
+
...input,
|
|
8641
|
+
args: args && typeof args === "object" ? { ...args } : {}
|
|
8642
|
+
}));
|
|
8643
|
+
}
|
|
7895
8644
|
parseCurrentTranscript(baseMessages, partialResponse, scope) {
|
|
7896
8645
|
if (!this.cliScripts?.parseOutput) return null;
|
|
7897
8646
|
try {
|
|
@@ -7947,12 +8696,23 @@ ${data.message || ""}`.trim();
|
|
|
7947
8696
|
if (this.startupParseGate) {
|
|
7948
8697
|
const deadline = Date.now() + 1e4;
|
|
7949
8698
|
while (this.startupParseGate && Date.now() < deadline) {
|
|
8699
|
+
this.resolveStartupState("send_wait");
|
|
7950
8700
|
await new Promise((resolve14) => setTimeout(resolve14, 50));
|
|
7951
8701
|
}
|
|
7952
8702
|
}
|
|
8703
|
+
await this.waitForInteractivePrompt();
|
|
8704
|
+
if (!this.ready) {
|
|
8705
|
+
this.resolveStartupState("send_precheck");
|
|
8706
|
+
const screenText = this.terminalScreen.getText() || "";
|
|
8707
|
+
const hasPrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
8708
|
+
if (hasPrompt && this.currentStatus === "idle") {
|
|
8709
|
+
this.ready = true;
|
|
8710
|
+
this.startupParseGate = false;
|
|
8711
|
+
LOG.info("CLI", `[${this.cliType}] sendMessage recovered idle prompt readiness`);
|
|
8712
|
+
}
|
|
8713
|
+
}
|
|
7953
8714
|
if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
|
|
7954
8715
|
if (this.isWaitingForResponse) return;
|
|
7955
|
-
await this.waitForInteractivePrompt();
|
|
7956
8716
|
const blockingModal = this.activeModal || this.getStartupConfirmationModal(this.terminalScreen.getText() || "");
|
|
7957
8717
|
if (blockingModal || this.currentStatus === "waiting_approval") {
|
|
7958
8718
|
throw new Error(`${this.cliName} is awaiting confirmation before it can accept a prompt`);
|
|
@@ -7996,8 +8756,6 @@ ${data.message || ""}`.trim();
|
|
|
7996
8756
|
}
|
|
7997
8757
|
this.responseEpoch += 1;
|
|
7998
8758
|
this.responseSettleIgnoreUntil = Date.now() + submitDelayMs + this.timeouts.outputSettle + 250;
|
|
7999
|
-
this.setStatus("generating", "sendMessage");
|
|
8000
|
-
this.onStatusChange?.();
|
|
8001
8759
|
const startResponseTimeout = () => {
|
|
8002
8760
|
if (this.responseTimeout) clearTimeout(this.responseTimeout);
|
|
8003
8761
|
this.responseTimeout = setTimeout(() => {
|
|
@@ -8016,7 +8774,7 @@ ${data.message || ""}`.trim();
|
|
|
8016
8774
|
const retrySubmitIfStuck = (attempt) => {
|
|
8017
8775
|
this.submitRetryTimer = null;
|
|
8018
8776
|
if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
|
|
8019
|
-
if (this.currentStatus
|
|
8777
|
+
if (this.currentStatus === "waiting_approval") return;
|
|
8020
8778
|
if ((this.responseBuffer || "").trim()) return;
|
|
8021
8779
|
const screenText = this.terminalScreen.getText();
|
|
8022
8780
|
if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
|
|
@@ -8051,7 +8809,7 @@ ${data.message || ""}`.trim();
|
|
|
8051
8809
|
this.submitRetryTimer = setTimeout(() => {
|
|
8052
8810
|
this.submitRetryTimer = null;
|
|
8053
8811
|
if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
|
|
8054
|
-
if (this.currentStatus
|
|
8812
|
+
if (this.currentStatus === "waiting_approval") return;
|
|
8055
8813
|
if ((this.responseBuffer || "").trim()) return;
|
|
8056
8814
|
const screenText = this.terminalScreen.getText();
|
|
8057
8815
|
if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
|
|
@@ -8483,6 +9241,7 @@ var init_cli_provider_instance = __esm({
|
|
|
8483
9241
|
init_status_monitor();
|
|
8484
9242
|
init_chat_history();
|
|
8485
9243
|
init_logger();
|
|
9244
|
+
init_control_effects();
|
|
8486
9245
|
CachedDatabaseSync = null;
|
|
8487
9246
|
CliProviderInstance = class {
|
|
8488
9247
|
constructor(provider, workingDir, cliArgs = [], instanceId, transportFactory, options) {
|
|
@@ -8511,6 +9270,8 @@ var init_cli_provider_instance = __esm({
|
|
|
8511
9270
|
generatingDebounceTimer = null;
|
|
8512
9271
|
generatingDebouncePending = null;
|
|
8513
9272
|
lastApprovalEventAt = 0;
|
|
9273
|
+
controlValues = {};
|
|
9274
|
+
appliedEffectKeys = /* @__PURE__ */ new Set();
|
|
8514
9275
|
historyWriter;
|
|
8515
9276
|
runtimeMessages = [];
|
|
8516
9277
|
instanceId;
|
|
@@ -8523,6 +9284,7 @@ var init_cli_provider_instance = __esm({
|
|
|
8523
9284
|
async init(context) {
|
|
8524
9285
|
this.context = context;
|
|
8525
9286
|
this.settings = context.settings || {};
|
|
9287
|
+
this.adapter.updateRuntimeSettings?.(this.settings);
|
|
8526
9288
|
this.monitor.updateConfig({
|
|
8527
9289
|
approvalAlert: this.settings.approvalAlert !== false,
|
|
8528
9290
|
longGeneratingAlert: this.settings.longGeneratingAlert !== false,
|
|
@@ -8538,6 +9300,21 @@ var init_cli_provider_instance = __esm({
|
|
|
8538
9300
|
this.detectStatusTransition();
|
|
8539
9301
|
});
|
|
8540
9302
|
await this.adapter.spawn();
|
|
9303
|
+
if (this.providerSessionId) {
|
|
9304
|
+
const restoredHistory = readChatHistory(this.type, 0, 200, this.providerSessionId);
|
|
9305
|
+
if (restoredHistory.messages.length > 0) {
|
|
9306
|
+
this.adapter.seedCommittedMessages(
|
|
9307
|
+
restoredHistory.messages.map((message) => ({
|
|
9308
|
+
role: message.role,
|
|
9309
|
+
content: message.content,
|
|
9310
|
+
timestamp: message.receivedAt,
|
|
9311
|
+
receivedAt: message.receivedAt,
|
|
9312
|
+
kind: message.kind,
|
|
9313
|
+
senderName: message.senderName
|
|
9314
|
+
}))
|
|
9315
|
+
);
|
|
9316
|
+
}
|
|
9317
|
+
}
|
|
8541
9318
|
if (this.providerSessionId && this.launchMode === "resume") {
|
|
8542
9319
|
const resumedAt = Date.now();
|
|
8543
9320
|
this.historyWriter.appendSystemMarker(
|
|
@@ -8618,6 +9395,12 @@ var init_cli_provider_instance = __esm({
|
|
|
8618
9395
|
}
|
|
8619
9396
|
const runtime = this.adapter.getRuntimeMetadata();
|
|
8620
9397
|
const parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [];
|
|
9398
|
+
const controlValues = extractProviderControlValues(this.provider.controls, parsedStatus);
|
|
9399
|
+
if (controlValues) {
|
|
9400
|
+
this.controlValues = controlValues;
|
|
9401
|
+
} else if (Object.keys(this.controlValues).length > 0) {
|
|
9402
|
+
this.controlValues = {};
|
|
9403
|
+
}
|
|
8621
9404
|
const mergedMessages = this.mergeConversationMessages(parsedMessages);
|
|
8622
9405
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
8623
9406
|
if (parsedMessages.length > 0) {
|
|
@@ -8638,6 +9421,7 @@ var init_cli_provider_instance = __esm({
|
|
|
8638
9421
|
);
|
|
8639
9422
|
}
|
|
8640
9423
|
}
|
|
9424
|
+
this.applyProviderResponse(parsedStatus, { phase: "immediate" });
|
|
8641
9425
|
return {
|
|
8642
9426
|
type: this.type,
|
|
8643
9427
|
name: this.provider.name,
|
|
@@ -8667,8 +9451,7 @@ var init_cli_provider_instance = __esm({
|
|
|
8667
9451
|
attachedClients: runtime.attachedClients || []
|
|
8668
9452
|
} : void 0,
|
|
8669
9453
|
resume: this.provider.resume,
|
|
8670
|
-
controlValues:
|
|
8671
|
-
// CLI controls not yet wired from stream
|
|
9454
|
+
controlValues: this.controlValues,
|
|
8672
9455
|
providerControls: this.provider.controls
|
|
8673
9456
|
};
|
|
8674
9457
|
}
|
|
@@ -8679,6 +9462,15 @@ var init_cli_provider_instance = __esm({
|
|
|
8679
9462
|
getPresentationMode() {
|
|
8680
9463
|
return this.presentationMode;
|
|
8681
9464
|
}
|
|
9465
|
+
updateSettings(newSettings) {
|
|
9466
|
+
this.settings = { ...newSettings };
|
|
9467
|
+
this.adapter.updateRuntimeSettings?.(this.settings);
|
|
9468
|
+
this.monitor.updateConfig({
|
|
9469
|
+
approvalAlert: this.settings.approvalAlert !== false,
|
|
9470
|
+
longGeneratingAlert: this.settings.longGeneratingAlert !== false,
|
|
9471
|
+
longGeneratingThresholdSec: this.settings.longGeneratingThresholdSec || 180
|
|
9472
|
+
});
|
|
9473
|
+
}
|
|
8682
9474
|
onEvent(event, data) {
|
|
8683
9475
|
if (event === "send_message" && data?.text) {
|
|
8684
9476
|
void this.adapter.sendMessage(data.text).catch((e) => {
|
|
@@ -8690,22 +9482,27 @@ var init_cli_provider_instance = __esm({
|
|
|
8690
9482
|
void this.adapter.resolveAction(data).catch((e) => {
|
|
8691
9483
|
LOG.warn("CLI", `[${this.type}] resolve_action failed: ${e?.message || e}`);
|
|
8692
9484
|
});
|
|
9485
|
+
} else if (event === "provider_state_patch" && data && typeof data === "object") {
|
|
9486
|
+
this.applyProviderResponse(data, { phase: "immediate" });
|
|
8693
9487
|
}
|
|
8694
9488
|
}
|
|
8695
9489
|
dispose() {
|
|
8696
9490
|
this.adapter.shutdown();
|
|
8697
9491
|
this.monitor.reset();
|
|
9492
|
+
this.appliedEffectKeys.clear();
|
|
8698
9493
|
}
|
|
8699
9494
|
completedDebounceTimer = null;
|
|
8700
9495
|
completedDebouncePending = null;
|
|
8701
9496
|
detectStatusTransition() {
|
|
8702
9497
|
const now = Date.now();
|
|
8703
9498
|
const adapterStatus = this.adapter.getStatus();
|
|
9499
|
+
const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
|
|
8704
9500
|
const newStatus = adapterStatus.status;
|
|
8705
9501
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
8706
9502
|
const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
|
|
8707
9503
|
const partial2 = this.adapter.getPartialResponse();
|
|
8708
9504
|
const progressFingerprint = newStatus === "generating" ? `${partial2 || ""}::${adapterStatus.messages.at(-1)?.content || ""}`.slice(-2e3) : void 0;
|
|
9505
|
+
const previousStatus = this.lastStatus;
|
|
8709
9506
|
if (newStatus !== this.lastStatus) {
|
|
8710
9507
|
LOG.info("CLI", `[${this.type}] status: ${this.lastStatus} \u2192 ${newStatus}`);
|
|
8711
9508
|
if (this.lastStatus === "idle" && newStatus === "generating") {
|
|
@@ -8798,6 +9595,9 @@ var init_cli_provider_instance = __esm({
|
|
|
8798
9595
|
}
|
|
8799
9596
|
this.lastStatus = newStatus;
|
|
8800
9597
|
}
|
|
9598
|
+
this.applyProviderResponse(parsedStatus, {
|
|
9599
|
+
phase: newStatus === "idle" && (previousStatus === "generating" || previousStatus === "waiting_approval") ? "turn_completed" : "immediate"
|
|
9600
|
+
});
|
|
8801
9601
|
const agentKey = `${this.type}:cli`;
|
|
8802
9602
|
const monitorEvents = this.monitor.check(agentKey, newStatus, now, progressFingerprint);
|
|
8803
9603
|
for (const me of monitorEvents) {
|
|
@@ -8813,6 +9613,88 @@ var init_cli_provider_instance = __esm({
|
|
|
8813
9613
|
this.events = [];
|
|
8814
9614
|
return events;
|
|
8815
9615
|
}
|
|
9616
|
+
applyProviderResponse(data, options) {
|
|
9617
|
+
if (!data || typeof data !== "object") return;
|
|
9618
|
+
const controlValues = extractProviderControlValues(this.provider.controls, data);
|
|
9619
|
+
if (controlValues) {
|
|
9620
|
+
this.controlValues = { ...this.controlValues, ...controlValues };
|
|
9621
|
+
}
|
|
9622
|
+
const effects = normalizeProviderEffects(data);
|
|
9623
|
+
for (const effect of effects) {
|
|
9624
|
+
const effectWhen = effect.when || "immediate";
|
|
9625
|
+
if (effectWhen === "turn_completed" && options.phase !== "turn_completed") continue;
|
|
9626
|
+
if (effectWhen === "immediate" && options.phase === "turn_completed") continue;
|
|
9627
|
+
const effectKey = this.getEffectDedupKey(effect);
|
|
9628
|
+
if (this.appliedEffectKeys.has(effectKey)) continue;
|
|
9629
|
+
this.appliedEffectKeys.add(effectKey);
|
|
9630
|
+
if (effect.persist !== false) {
|
|
9631
|
+
const persisted = this.getPersistedEffectContent(effect);
|
|
9632
|
+
if (persisted) this.appendRuntimeSystemMessage(persisted, effectKey);
|
|
9633
|
+
}
|
|
9634
|
+
if (effect.type === "message" && effect.message) {
|
|
9635
|
+
const content = typeof effect.message.content === "string" ? effect.message.content : JSON.stringify(effect.message.content);
|
|
9636
|
+
this.pushEvent({
|
|
9637
|
+
event: "provider:message",
|
|
9638
|
+
timestamp: Date.now(),
|
|
9639
|
+
content,
|
|
9640
|
+
role: effect.message.role || "system",
|
|
9641
|
+
kind: effect.message.kind,
|
|
9642
|
+
senderName: effect.message.senderName
|
|
9643
|
+
});
|
|
9644
|
+
} else if (effect.type === "toast" && effect.toast) {
|
|
9645
|
+
this.pushEvent({
|
|
9646
|
+
event: "provider:toast",
|
|
9647
|
+
effectId: effect.id || effectKey,
|
|
9648
|
+
timestamp: Date.now(),
|
|
9649
|
+
message: effect.toast.message,
|
|
9650
|
+
level: effect.toast.level || "info"
|
|
9651
|
+
});
|
|
9652
|
+
} else if (effect.type === "notification" && effect.notification) {
|
|
9653
|
+
this.pushEvent({
|
|
9654
|
+
event: "provider:notification",
|
|
9655
|
+
effectId: effect.id || effectKey,
|
|
9656
|
+
timestamp: Date.now(),
|
|
9657
|
+
title: effect.notification.title,
|
|
9658
|
+
message: effect.notification.body,
|
|
9659
|
+
content: typeof effect.notification.bubbleContent === "string" ? effect.notification.bubbleContent : effect.notification.body,
|
|
9660
|
+
level: effect.notification.level || "info",
|
|
9661
|
+
channels: effect.notification.channels || ["toast"],
|
|
9662
|
+
preferenceKey: effect.notification.preferenceKey
|
|
9663
|
+
});
|
|
9664
|
+
}
|
|
9665
|
+
}
|
|
9666
|
+
if (this.appliedEffectKeys.size > 200) {
|
|
9667
|
+
this.appliedEffectKeys = new Set(Array.from(this.appliedEffectKeys).slice(-100));
|
|
9668
|
+
}
|
|
9669
|
+
}
|
|
9670
|
+
getEffectDedupKey(effect) {
|
|
9671
|
+
if (effect.id) return `provider_effect:${effect.id}`;
|
|
9672
|
+
if (effect.type === "message") {
|
|
9673
|
+
const content = typeof effect.message?.content === "string" ? effect.message.content : JSON.stringify(effect.message?.content || "");
|
|
9674
|
+
return `provider_effect:message:${content}`;
|
|
9675
|
+
}
|
|
9676
|
+
if (effect.type === "notification") {
|
|
9677
|
+
return `provider_effect:notification:${effect.notification?.title || ""}:${effect.notification?.body || ""}`;
|
|
9678
|
+
}
|
|
9679
|
+
return `provider_effect:toast:${effect.toast?.message || ""}`;
|
|
9680
|
+
}
|
|
9681
|
+
getPersistedEffectContent(effect) {
|
|
9682
|
+
if (effect.type === "message") {
|
|
9683
|
+
return typeof effect.message?.content === "string" ? effect.message.content : JSON.stringify(effect.message?.content || "");
|
|
9684
|
+
}
|
|
9685
|
+
if (effect.type === "toast") {
|
|
9686
|
+
return effect.toast?.message || null;
|
|
9687
|
+
}
|
|
9688
|
+
if (effect.type === "notification") {
|
|
9689
|
+
if (typeof effect.notification?.bubbleContent === "string") return effect.notification.bubbleContent;
|
|
9690
|
+
if (typeof effect.notification?.title === "string" && effect.notification.title.trim()) {
|
|
9691
|
+
return `${effect.notification.title}
|
|
9692
|
+
${effect.notification.body || ""}`.trim();
|
|
9693
|
+
}
|
|
9694
|
+
return effect.notification?.body || null;
|
|
9695
|
+
}
|
|
9696
|
+
return null;
|
|
9697
|
+
}
|
|
8816
9698
|
// ─── Adapter access (backward compat) ──────────────────
|
|
8817
9699
|
getAdapter() {
|
|
8818
9700
|
return this.adapter;
|
|
@@ -29667,6 +30549,22 @@ function getMacAppIdentifiers() {
|
|
|
29667
30549
|
function getWinProcessNames() {
|
|
29668
30550
|
return getProviderLoader().getWinProcessNames();
|
|
29669
30551
|
}
|
|
30552
|
+
function getProviderMeta(ideId) {
|
|
30553
|
+
return getProviderLoader().getMeta(ideId);
|
|
30554
|
+
}
|
|
30555
|
+
function getPreferredLaunchMethod(ideId, platform11) {
|
|
30556
|
+
const prefer = getProviderMeta(ideId)?.launch?.prefer;
|
|
30557
|
+
const value = prefer?.[platform11];
|
|
30558
|
+
return value === "cli" || value === "app" || value === "auto" ? value : "auto";
|
|
30559
|
+
}
|
|
30560
|
+
function getCdpStartupTimeoutMs(ideId) {
|
|
30561
|
+
const value = getProviderMeta(ideId)?.launch?.cdpStartupTimeoutMs;
|
|
30562
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return 15e3;
|
|
30563
|
+
return Math.max(1e3, Math.floor(value));
|
|
30564
|
+
}
|
|
30565
|
+
function escapeForAppleScript(value) {
|
|
30566
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
30567
|
+
}
|
|
29670
30568
|
async function findFreePort(ports) {
|
|
29671
30569
|
for (const port2 of ports) {
|
|
29672
30570
|
const free = await checkPortFree(port2);
|
|
@@ -29719,12 +30617,12 @@ async function killIdeProcess(ideId) {
|
|
|
29719
30617
|
try {
|
|
29720
30618
|
if (plat === "darwin" && appName) {
|
|
29721
30619
|
try {
|
|
29722
|
-
(0, import_child_process6.execSync)(`osascript -e 'tell application "${appName}" to quit' 2>/dev/null`, {
|
|
30620
|
+
(0, import_child_process6.execSync)(`osascript -e 'tell application "${escapeForAppleScript(appName)}" to quit' 2>/dev/null`, {
|
|
29723
30621
|
timeout: 5e3
|
|
29724
30622
|
});
|
|
29725
30623
|
} catch {
|
|
29726
30624
|
try {
|
|
29727
|
-
(0, import_child_process6.execSync)(`pkill -
|
|
30625
|
+
(0, import_child_process6.execSync)(`pkill -x "${appName}" 2>/dev/null`, { timeout: 5e3 });
|
|
29728
30626
|
} catch {
|
|
29729
30627
|
}
|
|
29730
30628
|
}
|
|
@@ -29754,7 +30652,7 @@ async function killIdeProcess(ideId) {
|
|
|
29754
30652
|
}
|
|
29755
30653
|
if (plat === "darwin" && appName) {
|
|
29756
30654
|
try {
|
|
29757
|
-
(0, import_child_process6.execSync)(`pkill -9 -
|
|
30655
|
+
(0, import_child_process6.execSync)(`pkill -9 -x "${appName}" 2>/dev/null`, { timeout: 5e3 });
|
|
29758
30656
|
} catch {
|
|
29759
30657
|
}
|
|
29760
30658
|
} else if (plat === "win32" && winProcesses) {
|
|
@@ -29777,8 +30675,23 @@ function isIdeRunning(ideId) {
|
|
|
29777
30675
|
if (plat === "darwin") {
|
|
29778
30676
|
const appName = getMacAppIdentifiers()[ideId];
|
|
29779
30677
|
if (!appName) return false;
|
|
29780
|
-
|
|
29781
|
-
|
|
30678
|
+
try {
|
|
30679
|
+
const result = (0, import_child_process6.execSync)(`pgrep -x "${appName}" 2>/dev/null`, {
|
|
30680
|
+
encoding: "utf-8",
|
|
30681
|
+
timeout: 3e3
|
|
30682
|
+
});
|
|
30683
|
+
return result.trim().length > 0;
|
|
30684
|
+
} catch {
|
|
30685
|
+
const result = (0, import_child_process6.execSync)(
|
|
30686
|
+
`osascript -e 'tell application "System Events" to count (every process whose name is "${escapeForAppleScript(appName)}")'`,
|
|
30687
|
+
{
|
|
30688
|
+
encoding: "utf-8",
|
|
30689
|
+
timeout: 3e3,
|
|
30690
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
30691
|
+
}
|
|
30692
|
+
);
|
|
30693
|
+
return Number.parseInt(result.trim() || "0", 10) > 0;
|
|
30694
|
+
}
|
|
29782
30695
|
} else if (plat === "win32") {
|
|
29783
30696
|
const winProcesses = getWinProcessNames()[ideId];
|
|
29784
30697
|
if (!winProcesses) return false;
|
|
@@ -29927,7 +30840,8 @@ async function launchWithCdp(options = {}) {
|
|
|
29927
30840
|
await launchLinux(targetIde, port, workspace, options.newWindow);
|
|
29928
30841
|
}
|
|
29929
30842
|
let cdpReady = false;
|
|
29930
|
-
|
|
30843
|
+
const waitDeadline = Date.now() + getCdpStartupTimeoutMs(targetIde.id);
|
|
30844
|
+
while (Date.now() < waitDeadline) {
|
|
29931
30845
|
await new Promise((r) => setTimeout(r, 500));
|
|
29932
30846
|
if (await isCdpActive(port)) {
|
|
29933
30847
|
cdpReady = true;
|
|
@@ -29956,14 +30870,18 @@ async function launchWithCdp(options = {}) {
|
|
|
29956
30870
|
}
|
|
29957
30871
|
async function launchMacOS(ide, port, workspace, newWindow) {
|
|
29958
30872
|
const appName = getMacAppIdentifiers()[ide.id];
|
|
30873
|
+
const preferredMethod = getPreferredLaunchMethod(ide.id, "darwin");
|
|
29959
30874
|
const args = ["--remote-debugging-port=" + port];
|
|
29960
30875
|
if (newWindow) args.push("--new-window");
|
|
29961
30876
|
if (workspace) args.push(workspace);
|
|
29962
|
-
|
|
30877
|
+
const canUseCli = !!ide.cliCommand;
|
|
30878
|
+
const canUseAppLauncher = !!appName;
|
|
30879
|
+
const useAppLauncher = preferredMethod === "app" ? canUseAppLauncher : preferredMethod === "cli" ? false : !canUseCli && canUseAppLauncher;
|
|
30880
|
+
if (!useAppLauncher && ide.cliCommand) {
|
|
30881
|
+
(0, import_child_process6.spawn)(ide.cliCommand, args, { detached: true, stdio: "ignore" }).unref();
|
|
30882
|
+
} else if (appName) {
|
|
29963
30883
|
const openArgs = ["-a", appName, "--args", ...args];
|
|
29964
30884
|
(0, import_child_process6.spawn)("open", openArgs, { detached: true, stdio: "ignore" }).unref();
|
|
29965
|
-
} else if (ide.cliCommand) {
|
|
29966
|
-
(0, import_child_process6.spawn)(ide.cliCommand, args, { detached: true, stdio: "ignore" }).unref();
|
|
29967
30885
|
} else {
|
|
29968
30886
|
throw new Error(`No app identifier or CLI for ${ide.displayName}`);
|
|
29969
30887
|
}
|
|
@@ -30281,6 +31199,7 @@ function buildStatusSnapshot(options) {
|
|
|
30281
31199
|
workspaces: wsState.workspaces,
|
|
30282
31200
|
defaultWorkspaceId: wsState.defaultWorkspaceId,
|
|
30283
31201
|
defaultWorkspacePath: wsState.defaultWorkspacePath,
|
|
31202
|
+
terminalSizingMode: cfg.terminalSizingMode || "measured",
|
|
30284
31203
|
recentLaunches: buildRecentLaunches(recentActivity),
|
|
30285
31204
|
terminalBackend,
|
|
30286
31205
|
availableProviders: buildAvailableProviders(options.providerLoader)
|
|
@@ -31129,6 +32048,7 @@ var ProviderStreamAdapter;
|
|
|
31129
32048
|
var init_provider_adapter = __esm({
|
|
31130
32049
|
"../../oss/packages/daemon-core/src/agent-stream/provider-adapter.ts"() {
|
|
31131
32050
|
"use strict";
|
|
32051
|
+
init_control_effects();
|
|
31132
32052
|
ProviderStreamAdapter = class {
|
|
31133
32053
|
agentType;
|
|
31134
32054
|
agentName;
|
|
@@ -31188,19 +32108,10 @@ var init_provider_adapter = __esm({
|
|
|
31188
32108
|
mode: data.mode,
|
|
31189
32109
|
activeModal: data.activeModal
|
|
31190
32110
|
};
|
|
31191
|
-
|
|
31192
|
-
|
|
31193
|
-
|
|
31194
|
-
|
|
31195
|
-
const val = data[ctrl.readFrom];
|
|
31196
|
-
if (val !== void 0 && val !== null) {
|
|
31197
|
-
cv[ctrl.id] = typeof val === "object" ? val.name || val.id || String(val) : val;
|
|
31198
|
-
}
|
|
31199
|
-
}
|
|
31200
|
-
if (data.model && !cv["model"]) cv["model"] = data.model;
|
|
31201
|
-
if (data.mode && !cv["mode"]) cv["mode"] = data.mode;
|
|
31202
|
-
if (Object.keys(cv).length > 0) state.controlValues = cv;
|
|
31203
|
-
}
|
|
32111
|
+
const controlValues = extractProviderControlValues(this.provider.controls, data);
|
|
32112
|
+
if (controlValues) state.controlValues = controlValues;
|
|
32113
|
+
const effects = normalizeProviderEffects(data);
|
|
32114
|
+
if (effects.length > 0) state.effects = effects;
|
|
31204
32115
|
if (state.messages.length > 0) {
|
|
31205
32116
|
this.lastSuccessState = state;
|
|
31206
32117
|
}
|
|
@@ -31592,6 +32503,7 @@ var init_poller = __esm({
|
|
|
31592
32503
|
"../../oss/packages/daemon-core/src/agent-stream/poller.ts"() {
|
|
31593
32504
|
"use strict";
|
|
31594
32505
|
init_setup();
|
|
32506
|
+
init_reconcile();
|
|
31595
32507
|
init_logger();
|
|
31596
32508
|
AgentStreamPoller = class {
|
|
31597
32509
|
deps;
|
|
@@ -31631,6 +32543,7 @@ var init_poller = __esm({
|
|
|
31631
32543
|
sessionRegistry
|
|
31632
32544
|
} = this.deps;
|
|
31633
32545
|
if (!agentStreamManager || cdpManagers.size === 0) return;
|
|
32546
|
+
reconcileIdeRuntimeSessions(instanceManager, sessionRegistry);
|
|
31634
32547
|
for (const [ideType, cdp] of cdpManagers) {
|
|
31635
32548
|
registerExtensionProviders(providerLoader, cdp, ideType);
|
|
31636
32549
|
const ideInstance = instanceManager.getInstance(`ide:${ideType}`);
|
|
@@ -31760,6 +32673,8 @@ function forwardAgentStreamsToIdeInstance(instanceManager, ideType, streams) {
|
|
|
31760
32673
|
activeModal: stream.activeModal || null,
|
|
31761
32674
|
model: stream.model || void 0,
|
|
31762
32675
|
mode: stream.mode || void 0,
|
|
32676
|
+
controlValues: stream.controlValues || void 0,
|
|
32677
|
+
effects: stream.effects || void 0,
|
|
31763
32678
|
sessionId: stream.sessionId || stream.instanceId || void 0,
|
|
31764
32679
|
title: stream.title || stream.agentName || void 0,
|
|
31765
32680
|
agentType: stream.agentType || void 0,
|
|
@@ -46625,7 +47540,7 @@ var init_adhdev_daemon = __esm({
|
|
|
46625
47540
|
import_ws3 = require("ws");
|
|
46626
47541
|
import_chalk2 = __toESM(require("chalk"));
|
|
46627
47542
|
init_version();
|
|
46628
|
-
pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.
|
|
47543
|
+
pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.25" });
|
|
46629
47544
|
DANGEROUS_PATTERNS = [
|
|
46630
47545
|
/\brm\s+(-[a-z]*f|-[a-z]*r|--force|--recursive)/i,
|
|
46631
47546
|
/\bsudo\b/i,
|