@adhdev/daemon-core 0.8.93 → 0.8.95
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/config/provider-source-config.d.ts +9 -0
- package/dist/index.js +411 -141
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +411 -141
- package/dist/index.mjs.map +1 -1
- package/dist/providers/cli-provider-instance.d.ts +3 -0
- package/dist/providers/provider-loader.d.ts +17 -0
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/cli-adapters/provider-cli-adapter.ts +51 -4
- package/src/commands/chat-commands.ts +20 -3
- package/src/config/provider-source-config.ts +10 -0
- package/src/providers/cli-provider-instance.ts +66 -31
- package/src/providers/provider-loader.ts +89 -3
package/dist/index.mjs
CHANGED
|
@@ -2504,7 +2504,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
2504
2504
|
`[${this.cliType}] Waiting for interactive prompt: hasPrompt=${hasPrompt} stableMs=${stableMs} recentOutputMs=${recentlyOutput} status=${status} startup=${startupLikelyActive} screen=${JSON.stringify(summarizeCliTraceText(screenText, 220)).slice(0, 260)}`
|
|
2505
2505
|
);
|
|
2506
2506
|
}
|
|
2507
|
-
await new Promise((
|
|
2507
|
+
await new Promise((resolve12) => setTimeout(resolve12, 50));
|
|
2508
2508
|
}
|
|
2509
2509
|
const finalScreenText = this.terminalScreen.getText() || "";
|
|
2510
2510
|
LOG.warn(
|
|
@@ -3092,7 +3092,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
3092
3092
|
}
|
|
3093
3093
|
projectEffectiveStatus(startupModal = null) {
|
|
3094
3094
|
if (this.parseErrorMessage) return "error";
|
|
3095
|
-
if (startupModal) return "waiting_approval";
|
|
3095
|
+
if (startupModal || this.activeModal) return "waiting_approval";
|
|
3096
3096
|
if (this.isWaitingForResponse && this.currentTurnScope && this.currentStatus === "idle") return "generating";
|
|
3097
3097
|
return this.currentStatus;
|
|
3098
3098
|
}
|
|
@@ -3100,12 +3100,24 @@ var init_provider_cli_adapter = __esm({
|
|
|
3100
3100
|
getStatus() {
|
|
3101
3101
|
const screenText = this.terminalScreen.getText() || "";
|
|
3102
3102
|
const startupModal = this.startupParseGate ? this.getStartupConfirmationModal(screenText) : null;
|
|
3103
|
-
|
|
3103
|
+
let effectiveStatus = this.projectEffectiveStatus(startupModal);
|
|
3104
|
+
let effectiveModal = startupModal || this.activeModal;
|
|
3105
|
+
if (!startupModal && !effectiveModal && typeof this.cliScripts?.parseOutput === "function") {
|
|
3106
|
+
try {
|
|
3107
|
+
const parsed = this.getScriptParsedStatus();
|
|
3108
|
+
const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
|
|
3109
|
+
if (parsed?.status === "waiting_approval" && parsedModal) {
|
|
3110
|
+
effectiveStatus = "waiting_approval";
|
|
3111
|
+
effectiveModal = parsedModal;
|
|
3112
|
+
}
|
|
3113
|
+
} catch {
|
|
3114
|
+
}
|
|
3115
|
+
}
|
|
3104
3116
|
return {
|
|
3105
3117
|
status: effectiveStatus,
|
|
3106
3118
|
messages: [...this.committedMessages],
|
|
3107
3119
|
workingDir: this.workingDir,
|
|
3108
|
-
activeModal:
|
|
3120
|
+
activeModal: effectiveModal,
|
|
3109
3121
|
errorMessage: this.parseErrorMessage || void 0,
|
|
3110
3122
|
errorReason: this.parseErrorMessage ? "parse_error" : void 0
|
|
3111
3123
|
};
|
|
@@ -3141,6 +3153,15 @@ var init_provider_cli_adapter = __esm({
|
|
|
3141
3153
|
this.currentTurnScope,
|
|
3142
3154
|
screenText
|
|
3143
3155
|
);
|
|
3156
|
+
const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
|
|
3157
|
+
if (parsedModal && parsed?.status === "waiting_approval") {
|
|
3158
|
+
this.activeModal = parsedModal;
|
|
3159
|
+
this.isWaitingForResponse = true;
|
|
3160
|
+
if (this.currentStatus !== "waiting_approval") {
|
|
3161
|
+
this.setStatus("waiting_approval", "parsed_waiting_approval");
|
|
3162
|
+
this.onStatusChange?.();
|
|
3163
|
+
}
|
|
3164
|
+
}
|
|
3144
3165
|
if (this.maybeCommitVisibleIdleTranscript(parsed)) {
|
|
3145
3166
|
return this.getScriptParsedStatus();
|
|
3146
3167
|
}
|
|
@@ -3345,7 +3366,7 @@ ${data.message || ""}`.trim();
|
|
|
3345
3366
|
const deadline = Date.now() + 1e4;
|
|
3346
3367
|
while (this.startupParseGate && Date.now() < deadline) {
|
|
3347
3368
|
this.resolveStartupState("send_wait");
|
|
3348
|
-
await new Promise((
|
|
3369
|
+
await new Promise((resolve12) => setTimeout(resolve12, 50));
|
|
3349
3370
|
}
|
|
3350
3371
|
}
|
|
3351
3372
|
if (!allowInterventionPrompt) {
|
|
@@ -3437,12 +3458,12 @@ ${data.message || ""}`.trim();
|
|
|
3437
3458
|
if (this.isWaitingForResponse) this.finishResponse();
|
|
3438
3459
|
}, this.timeouts.maxResponse);
|
|
3439
3460
|
};
|
|
3440
|
-
await new Promise((
|
|
3461
|
+
await new Promise((resolve12) => {
|
|
3441
3462
|
let resolved = false;
|
|
3442
3463
|
const resolveOnce = () => {
|
|
3443
3464
|
if (resolved) return;
|
|
3444
3465
|
resolved = true;
|
|
3445
|
-
|
|
3466
|
+
resolve12();
|
|
3446
3467
|
};
|
|
3447
3468
|
const submit = () => {
|
|
3448
3469
|
if (!this.ptyProcess) {
|
|
@@ -3616,17 +3637,17 @@ ${data.message || ""}`.trim();
|
|
|
3616
3637
|
}
|
|
3617
3638
|
}
|
|
3618
3639
|
waitForStopped(timeoutMs) {
|
|
3619
|
-
return new Promise((
|
|
3640
|
+
return new Promise((resolve12) => {
|
|
3620
3641
|
const startedAt = Date.now();
|
|
3621
3642
|
const timer = setInterval(() => {
|
|
3622
3643
|
if (!this.ptyProcess || this.currentStatus === "stopped") {
|
|
3623
3644
|
clearInterval(timer);
|
|
3624
|
-
|
|
3645
|
+
resolve12(true);
|
|
3625
3646
|
return;
|
|
3626
3647
|
}
|
|
3627
3648
|
if (Date.now() - startedAt >= timeoutMs) {
|
|
3628
3649
|
clearInterval(timer);
|
|
3629
|
-
|
|
3650
|
+
resolve12(false);
|
|
3630
3651
|
}
|
|
3631
3652
|
}, 100);
|
|
3632
3653
|
});
|
|
@@ -3791,7 +3812,22 @@ ${data.message || ""}`.trim();
|
|
|
3791
3812
|
}
|
|
3792
3813
|
resolveModal(buttonIndex) {
|
|
3793
3814
|
const screenText = this.terminalScreen.getText() || "";
|
|
3794
|
-
|
|
3815
|
+
let modal = this.activeModal || this.getStartupConfirmationModal(screenText);
|
|
3816
|
+
if (!modal && typeof this.cliScripts?.parseOutput === "function") {
|
|
3817
|
+
try {
|
|
3818
|
+
const parsed = this.getScriptParsedStatus();
|
|
3819
|
+
const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
|
|
3820
|
+
if (parsed?.status === "waiting_approval" && parsedModal) {
|
|
3821
|
+
modal = parsedModal;
|
|
3822
|
+
this.activeModal = parsedModal;
|
|
3823
|
+
if (this.currentStatus !== "waiting_approval") {
|
|
3824
|
+
this.setStatus("waiting_approval", "resolve_modal_parse");
|
|
3825
|
+
this.onStatusChange?.();
|
|
3826
|
+
}
|
|
3827
|
+
}
|
|
3828
|
+
} catch {
|
|
3829
|
+
}
|
|
3830
|
+
}
|
|
3795
3831
|
if (!this.ptyProcess || this.currentStatus !== "waiting_approval" && !modal) return;
|
|
3796
3832
|
this.clearIdleFinishCandidate("resolve_modal");
|
|
3797
3833
|
this.recordTrace("resolve_modal", {
|
|
@@ -4605,15 +4641,15 @@ function resolveCommandPath(command) {
|
|
|
4605
4641
|
return null;
|
|
4606
4642
|
}
|
|
4607
4643
|
function execAsync(cmd, timeoutMs = 5e3) {
|
|
4608
|
-
return new Promise((
|
|
4644
|
+
return new Promise((resolve12) => {
|
|
4609
4645
|
const child = exec(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
|
|
4610
4646
|
if (err || !stdout?.trim()) {
|
|
4611
|
-
|
|
4647
|
+
resolve12(null);
|
|
4612
4648
|
} else {
|
|
4613
|
-
|
|
4649
|
+
resolve12(stdout.trim());
|
|
4614
4650
|
}
|
|
4615
4651
|
});
|
|
4616
|
-
child.on("error", () =>
|
|
4652
|
+
child.on("error", () => resolve12(null));
|
|
4617
4653
|
});
|
|
4618
4654
|
}
|
|
4619
4655
|
async function detectCLIs(providerLoader, options) {
|
|
@@ -4973,7 +5009,7 @@ var DaemonCdpManager = class {
|
|
|
4973
5009
|
* Returns multiple entries if multiple IDE windows are open on same port
|
|
4974
5010
|
*/
|
|
4975
5011
|
static listAllTargets(port) {
|
|
4976
|
-
return new Promise((
|
|
5012
|
+
return new Promise((resolve12) => {
|
|
4977
5013
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
4978
5014
|
let data = "";
|
|
4979
5015
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -4989,16 +5025,16 @@ var DaemonCdpManager = class {
|
|
|
4989
5025
|
(t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
|
|
4990
5026
|
);
|
|
4991
5027
|
const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
|
|
4992
|
-
|
|
5028
|
+
resolve12(mainPages.length > 0 ? mainPages : fallbackPages);
|
|
4993
5029
|
} catch {
|
|
4994
|
-
|
|
5030
|
+
resolve12([]);
|
|
4995
5031
|
}
|
|
4996
5032
|
});
|
|
4997
5033
|
});
|
|
4998
|
-
req.on("error", () =>
|
|
5034
|
+
req.on("error", () => resolve12([]));
|
|
4999
5035
|
req.setTimeout(2e3, () => {
|
|
5000
5036
|
req.destroy();
|
|
5001
|
-
|
|
5037
|
+
resolve12([]);
|
|
5002
5038
|
});
|
|
5003
5039
|
});
|
|
5004
5040
|
}
|
|
@@ -5038,7 +5074,7 @@ var DaemonCdpManager = class {
|
|
|
5038
5074
|
}
|
|
5039
5075
|
}
|
|
5040
5076
|
findTargetOnPort(port) {
|
|
5041
|
-
return new Promise((
|
|
5077
|
+
return new Promise((resolve12) => {
|
|
5042
5078
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
5043
5079
|
let data = "";
|
|
5044
5080
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -5049,7 +5085,7 @@ var DaemonCdpManager = class {
|
|
|
5049
5085
|
(t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
|
|
5050
5086
|
);
|
|
5051
5087
|
if (pages.length === 0) {
|
|
5052
|
-
|
|
5088
|
+
resolve12(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
5053
5089
|
return;
|
|
5054
5090
|
}
|
|
5055
5091
|
const titleFilteredPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
|
|
@@ -5068,25 +5104,25 @@ var DaemonCdpManager = class {
|
|
|
5068
5104
|
this._targetId = selected.target.id;
|
|
5069
5105
|
}
|
|
5070
5106
|
this._pageTitle = selected.target.title || "";
|
|
5071
|
-
|
|
5107
|
+
resolve12(selected.target);
|
|
5072
5108
|
return;
|
|
5073
5109
|
}
|
|
5074
5110
|
if (previousTargetId) {
|
|
5075
5111
|
this.log(`[CDP] Target ${previousTargetId} not found in page list`);
|
|
5076
|
-
|
|
5112
|
+
resolve12(null);
|
|
5077
5113
|
return;
|
|
5078
5114
|
}
|
|
5079
5115
|
this._pageTitle = list[0]?.title || "";
|
|
5080
|
-
|
|
5116
|
+
resolve12(list[0]);
|
|
5081
5117
|
} catch {
|
|
5082
|
-
|
|
5118
|
+
resolve12(null);
|
|
5083
5119
|
}
|
|
5084
5120
|
});
|
|
5085
5121
|
});
|
|
5086
|
-
req.on("error", () =>
|
|
5122
|
+
req.on("error", () => resolve12(null));
|
|
5087
5123
|
req.setTimeout(2e3, () => {
|
|
5088
5124
|
req.destroy();
|
|
5089
|
-
|
|
5125
|
+
resolve12(null);
|
|
5090
5126
|
});
|
|
5091
5127
|
});
|
|
5092
5128
|
}
|
|
@@ -5097,7 +5133,7 @@ var DaemonCdpManager = class {
|
|
|
5097
5133
|
this.extensionProviders = providers;
|
|
5098
5134
|
}
|
|
5099
5135
|
connectToTarget(wsUrl) {
|
|
5100
|
-
return new Promise((
|
|
5136
|
+
return new Promise((resolve12) => {
|
|
5101
5137
|
this.ws = new WebSocket(wsUrl);
|
|
5102
5138
|
this.ws.on("open", async () => {
|
|
5103
5139
|
this._connected = true;
|
|
@@ -5107,17 +5143,17 @@ var DaemonCdpManager = class {
|
|
|
5107
5143
|
}
|
|
5108
5144
|
this.connectBrowserWs().catch(() => {
|
|
5109
5145
|
});
|
|
5110
|
-
|
|
5146
|
+
resolve12(true);
|
|
5111
5147
|
});
|
|
5112
5148
|
this.ws.on("message", (data) => {
|
|
5113
5149
|
try {
|
|
5114
5150
|
const msg = JSON.parse(data.toString());
|
|
5115
5151
|
if (msg.id && this.pending.has(msg.id)) {
|
|
5116
|
-
const { resolve:
|
|
5152
|
+
const { resolve: resolve13, reject } = this.pending.get(msg.id);
|
|
5117
5153
|
this.pending.delete(msg.id);
|
|
5118
5154
|
this.failureCount = 0;
|
|
5119
5155
|
if (msg.error) reject(new Error(msg.error.message));
|
|
5120
|
-
else
|
|
5156
|
+
else resolve13(msg.result);
|
|
5121
5157
|
} else if (msg.method === "Runtime.executionContextCreated") {
|
|
5122
5158
|
this.contexts.add(msg.params.context.id);
|
|
5123
5159
|
} else if (msg.method === "Runtime.executionContextDestroyed") {
|
|
@@ -5140,7 +5176,7 @@ var DaemonCdpManager = class {
|
|
|
5140
5176
|
this.ws.on("error", (err) => {
|
|
5141
5177
|
this.log(`[CDP] WebSocket error: ${err.message}`);
|
|
5142
5178
|
this._connected = false;
|
|
5143
|
-
|
|
5179
|
+
resolve12(false);
|
|
5144
5180
|
});
|
|
5145
5181
|
});
|
|
5146
5182
|
}
|
|
@@ -5154,7 +5190,7 @@ var DaemonCdpManager = class {
|
|
|
5154
5190
|
return;
|
|
5155
5191
|
}
|
|
5156
5192
|
this.log(`[CDP] Connecting browser WS for target discovery...`);
|
|
5157
|
-
await new Promise((
|
|
5193
|
+
await new Promise((resolve12, reject) => {
|
|
5158
5194
|
this.browserWs = new WebSocket(browserWsUrl);
|
|
5159
5195
|
this.browserWs.on("open", async () => {
|
|
5160
5196
|
this._browserConnected = true;
|
|
@@ -5164,16 +5200,16 @@ var DaemonCdpManager = class {
|
|
|
5164
5200
|
} catch (e) {
|
|
5165
5201
|
this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
|
|
5166
5202
|
}
|
|
5167
|
-
|
|
5203
|
+
resolve12();
|
|
5168
5204
|
});
|
|
5169
5205
|
this.browserWs.on("message", (data) => {
|
|
5170
5206
|
try {
|
|
5171
5207
|
const msg = JSON.parse(data.toString());
|
|
5172
5208
|
if (msg.id && this.browserPending.has(msg.id)) {
|
|
5173
|
-
const { resolve:
|
|
5209
|
+
const { resolve: resolve13, reject: reject2 } = this.browserPending.get(msg.id);
|
|
5174
5210
|
this.browserPending.delete(msg.id);
|
|
5175
5211
|
if (msg.error) reject2(new Error(msg.error.message));
|
|
5176
|
-
else
|
|
5212
|
+
else resolve13(msg.result);
|
|
5177
5213
|
}
|
|
5178
5214
|
} catch {
|
|
5179
5215
|
}
|
|
@@ -5193,31 +5229,31 @@ var DaemonCdpManager = class {
|
|
|
5193
5229
|
}
|
|
5194
5230
|
}
|
|
5195
5231
|
getBrowserWsUrl() {
|
|
5196
|
-
return new Promise((
|
|
5232
|
+
return new Promise((resolve12) => {
|
|
5197
5233
|
const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
|
|
5198
5234
|
let data = "";
|
|
5199
5235
|
res.on("data", (chunk) => data += chunk.toString());
|
|
5200
5236
|
res.on("end", () => {
|
|
5201
5237
|
try {
|
|
5202
5238
|
const info = JSON.parse(data);
|
|
5203
|
-
|
|
5239
|
+
resolve12(info.webSocketDebuggerUrl || null);
|
|
5204
5240
|
} catch {
|
|
5205
|
-
|
|
5241
|
+
resolve12(null);
|
|
5206
5242
|
}
|
|
5207
5243
|
});
|
|
5208
5244
|
});
|
|
5209
|
-
req.on("error", () =>
|
|
5245
|
+
req.on("error", () => resolve12(null));
|
|
5210
5246
|
req.setTimeout(3e3, () => {
|
|
5211
5247
|
req.destroy();
|
|
5212
|
-
|
|
5248
|
+
resolve12(null);
|
|
5213
5249
|
});
|
|
5214
5250
|
});
|
|
5215
5251
|
}
|
|
5216
5252
|
sendBrowser(method, params = {}, timeoutMs = 15e3) {
|
|
5217
|
-
return new Promise((
|
|
5253
|
+
return new Promise((resolve12, reject) => {
|
|
5218
5254
|
if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
|
|
5219
5255
|
const id = this.browserMsgId++;
|
|
5220
|
-
this.browserPending.set(id, { resolve:
|
|
5256
|
+
this.browserPending.set(id, { resolve: resolve12, reject });
|
|
5221
5257
|
this.browserWs.send(JSON.stringify({ id, method, params }));
|
|
5222
5258
|
setTimeout(() => {
|
|
5223
5259
|
if (this.browserPending.has(id)) {
|
|
@@ -5257,11 +5293,11 @@ var DaemonCdpManager = class {
|
|
|
5257
5293
|
}
|
|
5258
5294
|
// ─── CDP Protocol ────────────────────────────────────────
|
|
5259
5295
|
sendInternal(method, params = {}, timeoutMs = 15e3) {
|
|
5260
|
-
return new Promise((
|
|
5296
|
+
return new Promise((resolve12, reject) => {
|
|
5261
5297
|
if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
|
|
5262
5298
|
if (this.ws.readyState !== WebSocket.OPEN) return reject(new Error("WebSocket not open"));
|
|
5263
5299
|
const id = this.msgId++;
|
|
5264
|
-
this.pending.set(id, { resolve:
|
|
5300
|
+
this.pending.set(id, { resolve: resolve12, reject });
|
|
5265
5301
|
this.ws.send(JSON.stringify({ id, method, params }));
|
|
5266
5302
|
setTimeout(() => {
|
|
5267
5303
|
if (this.pending.has(id)) {
|
|
@@ -5510,7 +5546,7 @@ var DaemonCdpManager = class {
|
|
|
5510
5546
|
const browserWs = this.browserWs;
|
|
5511
5547
|
let msgId = this.browserMsgId;
|
|
5512
5548
|
const sendWs = (method, params = {}, sessionId) => {
|
|
5513
|
-
return new Promise((
|
|
5549
|
+
return new Promise((resolve12, reject) => {
|
|
5514
5550
|
const mid = msgId++;
|
|
5515
5551
|
this.browserMsgId = msgId;
|
|
5516
5552
|
const handler = (raw) => {
|
|
@@ -5519,7 +5555,7 @@ var DaemonCdpManager = class {
|
|
|
5519
5555
|
if (msg.id === mid) {
|
|
5520
5556
|
browserWs.removeListener("message", handler);
|
|
5521
5557
|
if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
|
|
5522
|
-
else
|
|
5558
|
+
else resolve12(msg.result);
|
|
5523
5559
|
}
|
|
5524
5560
|
} catch {
|
|
5525
5561
|
}
|
|
@@ -5720,14 +5756,14 @@ var DaemonCdpManager = class {
|
|
|
5720
5756
|
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
5721
5757
|
throw new Error("CDP not connected");
|
|
5722
5758
|
}
|
|
5723
|
-
return new Promise((
|
|
5759
|
+
return new Promise((resolve12, reject) => {
|
|
5724
5760
|
const id = getNextId();
|
|
5725
5761
|
pendingMap.set(id, {
|
|
5726
5762
|
resolve: (result) => {
|
|
5727
5763
|
if (result?.result?.subtype === "error") {
|
|
5728
5764
|
reject(new Error(result.result.description));
|
|
5729
5765
|
} else {
|
|
5730
|
-
|
|
5766
|
+
resolve12(result?.result?.value);
|
|
5731
5767
|
}
|
|
5732
5768
|
},
|
|
5733
5769
|
reject
|
|
@@ -5759,10 +5795,10 @@ var DaemonCdpManager = class {
|
|
|
5759
5795
|
throw new Error("CDP not connected");
|
|
5760
5796
|
}
|
|
5761
5797
|
const sendViaSession = (method, params = {}) => {
|
|
5762
|
-
return new Promise((
|
|
5798
|
+
return new Promise((resolve12, reject) => {
|
|
5763
5799
|
const pendingMap = this._browserConnected ? this.browserPending : this.pending;
|
|
5764
5800
|
const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
|
|
5765
|
-
pendingMap.set(id, { resolve:
|
|
5801
|
+
pendingMap.set(id, { resolve: resolve12, reject });
|
|
5766
5802
|
ws.send(JSON.stringify({ id, sessionId, method, params }));
|
|
5767
5803
|
setTimeout(() => {
|
|
5768
5804
|
if (pendingMap.has(id)) {
|
|
@@ -7486,6 +7522,125 @@ function listSavedHistorySessions(agentType, options = {}) {
|
|
|
7486
7522
|
return { sessions: [], hasMore: false };
|
|
7487
7523
|
}
|
|
7488
7524
|
}
|
|
7525
|
+
function normalizeCanonicalHermesMessageContent(content) {
|
|
7526
|
+
if (typeof content === "string") return content.trim();
|
|
7527
|
+
if (content == null) return "";
|
|
7528
|
+
try {
|
|
7529
|
+
return JSON.stringify(content).trim();
|
|
7530
|
+
} catch {
|
|
7531
|
+
return String(content).trim();
|
|
7532
|
+
}
|
|
7533
|
+
}
|
|
7534
|
+
function extractCanonicalHermesMessageTimestamp(message, fallbackTs) {
|
|
7535
|
+
const numericTimestamp = Number(message.receivedAt || message.timestamp || message.ts || 0);
|
|
7536
|
+
if (Number.isFinite(numericTimestamp) && numericTimestamp > 0) return numericTimestamp;
|
|
7537
|
+
const stringTimestamp = typeof message.ts === "string" ? Date.parse(message.ts) : typeof message.timestamp === "string" ? Date.parse(message.timestamp) : NaN;
|
|
7538
|
+
if (Number.isFinite(stringTimestamp) && stringTimestamp > 0) return stringTimestamp;
|
|
7539
|
+
return fallbackTs;
|
|
7540
|
+
}
|
|
7541
|
+
function readExistingHermesSessionStartRecord(historySessionId) {
|
|
7542
|
+
try {
|
|
7543
|
+
const dir = path7.join(HISTORY_DIR, "hermes-cli");
|
|
7544
|
+
if (!fs3.existsSync(dir)) return null;
|
|
7545
|
+
const files = listHistoryFiles(dir, historySessionId).sort();
|
|
7546
|
+
for (const file of files) {
|
|
7547
|
+
const lines = fs3.readFileSync(path7.join(dir, file), "utf-8").split("\n").filter(Boolean);
|
|
7548
|
+
for (const line of lines) {
|
|
7549
|
+
try {
|
|
7550
|
+
const parsed = JSON.parse(line);
|
|
7551
|
+
if (parsed.historySessionId !== historySessionId) continue;
|
|
7552
|
+
if (parsed.kind === "session_start" && parsed.role === "system") {
|
|
7553
|
+
return parsed;
|
|
7554
|
+
}
|
|
7555
|
+
} catch {
|
|
7556
|
+
}
|
|
7557
|
+
}
|
|
7558
|
+
}
|
|
7559
|
+
return null;
|
|
7560
|
+
} catch {
|
|
7561
|
+
return null;
|
|
7562
|
+
}
|
|
7563
|
+
}
|
|
7564
|
+
function rebuildHermesSavedHistoryFromCanonicalSession(historySessionId) {
|
|
7565
|
+
const normalizedSessionId = normalizeSavedHistorySessionId("hermes-cli", historySessionId);
|
|
7566
|
+
if (!normalizedSessionId) return false;
|
|
7567
|
+
try {
|
|
7568
|
+
const sessionFilePath = path7.join(os5.homedir(), ".hermes", "sessions", `session_${normalizedSessionId}.json`);
|
|
7569
|
+
if (!fs3.existsSync(sessionFilePath)) return false;
|
|
7570
|
+
const raw = JSON.parse(fs3.readFileSync(sessionFilePath, "utf-8"));
|
|
7571
|
+
const canonicalMessages = Array.isArray(raw.messages) ? raw.messages : [];
|
|
7572
|
+
const dir = path7.join(HISTORY_DIR, "hermes-cli");
|
|
7573
|
+
fs3.mkdirSync(dir, { recursive: true });
|
|
7574
|
+
const existingSessionStart = readExistingHermesSessionStartRecord(normalizedSessionId);
|
|
7575
|
+
const records = [];
|
|
7576
|
+
if (existingSessionStart) {
|
|
7577
|
+
records.push({
|
|
7578
|
+
...existingSessionStart,
|
|
7579
|
+
historySessionId: normalizedSessionId
|
|
7580
|
+
});
|
|
7581
|
+
}
|
|
7582
|
+
let fallbackTs = Date.parse(raw.session_start || raw.last_updated || "") || Date.now();
|
|
7583
|
+
for (const message of canonicalMessages) {
|
|
7584
|
+
const role = String(message.role || "").trim();
|
|
7585
|
+
const content = normalizeCanonicalHermesMessageContent(message.content);
|
|
7586
|
+
if (!content) continue;
|
|
7587
|
+
const receivedAt = extractCanonicalHermesMessageTimestamp(message, fallbackTs);
|
|
7588
|
+
fallbackTs = receivedAt + 1;
|
|
7589
|
+
if (role === "user") {
|
|
7590
|
+
records.push({
|
|
7591
|
+
ts: new Date(receivedAt).toISOString(),
|
|
7592
|
+
receivedAt,
|
|
7593
|
+
role: "user",
|
|
7594
|
+
content,
|
|
7595
|
+
kind: "standard",
|
|
7596
|
+
agent: "hermes-cli",
|
|
7597
|
+
historySessionId: normalizedSessionId
|
|
7598
|
+
});
|
|
7599
|
+
continue;
|
|
7600
|
+
}
|
|
7601
|
+
if (role === "assistant") {
|
|
7602
|
+
records.push({
|
|
7603
|
+
ts: new Date(receivedAt).toISOString(),
|
|
7604
|
+
receivedAt,
|
|
7605
|
+
role: "assistant",
|
|
7606
|
+
content,
|
|
7607
|
+
kind: "standard",
|
|
7608
|
+
agent: "hermes-cli",
|
|
7609
|
+
historySessionId: normalizedSessionId
|
|
7610
|
+
});
|
|
7611
|
+
continue;
|
|
7612
|
+
}
|
|
7613
|
+
if (role === "tool") {
|
|
7614
|
+
records.push({
|
|
7615
|
+
ts: new Date(receivedAt).toISOString(),
|
|
7616
|
+
receivedAt,
|
|
7617
|
+
role: "assistant",
|
|
7618
|
+
content,
|
|
7619
|
+
kind: "tool",
|
|
7620
|
+
senderName: "Tool",
|
|
7621
|
+
agent: "hermes-cli",
|
|
7622
|
+
historySessionId: normalizedSessionId
|
|
7623
|
+
});
|
|
7624
|
+
}
|
|
7625
|
+
}
|
|
7626
|
+
if (records.length === 0) return false;
|
|
7627
|
+
const prefix = `${normalizedSessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
|
|
7628
|
+
for (const file of fs3.readdirSync(dir)) {
|
|
7629
|
+
if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
|
|
7630
|
+
fs3.unlinkSync(path7.join(dir, file));
|
|
7631
|
+
}
|
|
7632
|
+
}
|
|
7633
|
+
const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
|
|
7634
|
+
const filePath = path7.join(dir, `${prefix}${targetDate}.jsonl`);
|
|
7635
|
+
fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
|
|
7636
|
+
`, "utf-8");
|
|
7637
|
+
invalidatePersistedSavedHistoryIndex("hermes-cli", dir);
|
|
7638
|
+
savedHistorySessionCache.delete("hermes-cli");
|
|
7639
|
+
return true;
|
|
7640
|
+
} catch {
|
|
7641
|
+
return false;
|
|
7642
|
+
}
|
|
7643
|
+
}
|
|
7489
7644
|
|
|
7490
7645
|
// src/providers/provider-patch-state.ts
|
|
7491
7646
|
function isControlValue(value) {
|
|
@@ -9659,7 +9814,9 @@ function getTargetInstance(h, args) {
|
|
|
9659
9814
|
const targetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
|
|
9660
9815
|
const sessionId = targetSessionId || h.currentSession?.sessionId || "";
|
|
9661
9816
|
if (!sessionId) return null;
|
|
9662
|
-
|
|
9817
|
+
const session = h.ctx.sessionRegistry?.get(sessionId);
|
|
9818
|
+
const instanceKey = session?.adapterKey || session?.instanceKey || sessionId;
|
|
9819
|
+
return h.ctx.instanceManager?.getInstance(instanceKey) || null;
|
|
9663
9820
|
}
|
|
9664
9821
|
function getTargetTransport(h, provider) {
|
|
9665
9822
|
if (h.currentSession?.transport) return h.currentSession.transport;
|
|
@@ -9956,7 +10113,7 @@ function getStateLastSignature(state) {
|
|
|
9956
10113
|
async function getStableExtensionBaseline(h) {
|
|
9957
10114
|
const first = await readExtensionChatState(h);
|
|
9958
10115
|
if (getStateMessageCount(first) > 0 || getStateLastSignature(first)) return first;
|
|
9959
|
-
await new Promise((
|
|
10116
|
+
await new Promise((resolve12) => setTimeout(resolve12, 150));
|
|
9960
10117
|
const second = await readExtensionChatState(h);
|
|
9961
10118
|
return getStateMessageCount(second) >= getStateMessageCount(first) ? second : first;
|
|
9962
10119
|
}
|
|
@@ -9964,7 +10121,7 @@ async function verifyExtensionSendObserved(h, before) {
|
|
|
9964
10121
|
const beforeCount = getStateMessageCount(before);
|
|
9965
10122
|
const beforeSignature = getStateLastSignature(before);
|
|
9966
10123
|
for (let attempt = 0; attempt < 12; attempt += 1) {
|
|
9967
|
-
await new Promise((
|
|
10124
|
+
await new Promise((resolve12) => setTimeout(resolve12, 250));
|
|
9968
10125
|
const state = await readExtensionChatState(h);
|
|
9969
10126
|
if (state?.status === "waiting_approval") return true;
|
|
9970
10127
|
const afterCount = getStateMessageCount(state);
|
|
@@ -10728,10 +10885,17 @@ async function handleResolveAction(h, args) {
|
|
|
10728
10885
|
}
|
|
10729
10886
|
}
|
|
10730
10887
|
const status = adapter.getStatus();
|
|
10731
|
-
|
|
10888
|
+
const targetInstance = getTargetInstance(h, args);
|
|
10889
|
+
const targetState = targetInstance?.getState?.();
|
|
10890
|
+
const surfacedModal = targetState?.activeChat?.activeModal && Array.isArray(targetState.activeChat.activeModal.buttons) && targetState.activeChat.activeModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim()) ? targetState.activeChat.activeModal : null;
|
|
10891
|
+
const statusModal = status?.activeModal && Array.isArray(status.activeModal.buttons) && status.activeModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim()) ? status.activeModal : null;
|
|
10892
|
+
const effectiveModal = statusModal || surfacedModal;
|
|
10893
|
+
const effectiveStatus = status?.status === "waiting_approval" || targetState?.activeChat?.status === "waiting_approval" ? "waiting_approval" : status?.status;
|
|
10894
|
+
LOG.info("Command", `[resolveAction] CLI PTY gate target=${String(args?.targetSessionId || "")} rawStatus=${String(status?.status || "")} effectiveStatus=${String(effectiveStatus || "")} statusModal=${statusModal ? "yes" : "no"} surfacedModal=${surfacedModal ? "yes" : "no"} instance=${targetInstance ? "yes" : "no"}`);
|
|
10895
|
+
if (effectiveStatus !== "waiting_approval" && !effectiveModal) {
|
|
10732
10896
|
return { success: false, error: "Not in approval state" };
|
|
10733
10897
|
}
|
|
10734
|
-
const buttons =
|
|
10898
|
+
const buttons = effectiveModal?.buttons || ["Allow once", "Always allow", "Deny"];
|
|
10735
10899
|
let buttonIndex = typeof args?.buttonIndex === "number" ? args.buttonIndex : -1;
|
|
10736
10900
|
if (buttonIndex < 0) {
|
|
10737
10901
|
const btnLower = button.toLowerCase();
|
|
@@ -12184,7 +12348,7 @@ var DaemonCommandHandler = class {
|
|
|
12184
12348
|
try {
|
|
12185
12349
|
const http3 = await import("http");
|
|
12186
12350
|
const postData = JSON.stringify(body);
|
|
12187
|
-
const result = await new Promise((
|
|
12351
|
+
const result = await new Promise((resolve12, reject) => {
|
|
12188
12352
|
const req = http3.request({
|
|
12189
12353
|
hostname: "127.0.0.1",
|
|
12190
12354
|
port: 19280,
|
|
@@ -12196,9 +12360,9 @@ var DaemonCommandHandler = class {
|
|
|
12196
12360
|
res.on("data", (chunk) => data += chunk);
|
|
12197
12361
|
res.on("end", () => {
|
|
12198
12362
|
try {
|
|
12199
|
-
|
|
12363
|
+
resolve12(JSON.parse(data));
|
|
12200
12364
|
} catch {
|
|
12201
|
-
|
|
12365
|
+
resolve12({ raw: data });
|
|
12202
12366
|
}
|
|
12203
12367
|
});
|
|
12204
12368
|
});
|
|
@@ -12216,15 +12380,15 @@ var DaemonCommandHandler = class {
|
|
|
12216
12380
|
if (!providerType) return { success: false, error: "providerType required" };
|
|
12217
12381
|
try {
|
|
12218
12382
|
const http3 = await import("http");
|
|
12219
|
-
const result = await new Promise((
|
|
12383
|
+
const result = await new Promise((resolve12, reject) => {
|
|
12220
12384
|
http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
|
|
12221
12385
|
let data = "";
|
|
12222
12386
|
res.on("data", (chunk) => data += chunk);
|
|
12223
12387
|
res.on("end", () => {
|
|
12224
12388
|
try {
|
|
12225
|
-
|
|
12389
|
+
resolve12(JSON.parse(data));
|
|
12226
12390
|
} catch {
|
|
12227
|
-
|
|
12391
|
+
resolve12({ raw: data });
|
|
12228
12392
|
}
|
|
12229
12393
|
});
|
|
12230
12394
|
}).on("error", reject);
|
|
@@ -12238,7 +12402,7 @@ var DaemonCommandHandler = class {
|
|
|
12238
12402
|
try {
|
|
12239
12403
|
const http3 = await import("http");
|
|
12240
12404
|
const postData = JSON.stringify(args || {});
|
|
12241
|
-
const result = await new Promise((
|
|
12405
|
+
const result = await new Promise((resolve12, reject) => {
|
|
12242
12406
|
const req = http3.request({
|
|
12243
12407
|
hostname: "127.0.0.1",
|
|
12244
12408
|
port: 19280,
|
|
@@ -12250,9 +12414,9 @@ var DaemonCommandHandler = class {
|
|
|
12250
12414
|
res.on("data", (chunk) => data += chunk);
|
|
12251
12415
|
res.on("end", () => {
|
|
12252
12416
|
try {
|
|
12253
|
-
|
|
12417
|
+
resolve12(JSON.parse(data));
|
|
12254
12418
|
} catch {
|
|
12255
|
-
|
|
12419
|
+
resolve12({ raw: data });
|
|
12256
12420
|
}
|
|
12257
12421
|
});
|
|
12258
12422
|
});
|
|
@@ -12350,7 +12514,7 @@ async function waitForCliAdapterReady(adapter, options) {
|
|
|
12350
12514
|
if (status === "stopped") {
|
|
12351
12515
|
throw new Error("CLI runtime stopped before it became ready");
|
|
12352
12516
|
}
|
|
12353
|
-
await new Promise((
|
|
12517
|
+
await new Promise((resolve12) => setTimeout(resolve12, pollMs));
|
|
12354
12518
|
}
|
|
12355
12519
|
throw new Error(`CLI runtime did not become ready within ${timeoutMs}ms`);
|
|
12356
12520
|
}
|
|
@@ -12387,6 +12551,7 @@ var CliProviderInstance = class {
|
|
|
12387
12551
|
historyWriter;
|
|
12388
12552
|
runtimeMessages = [];
|
|
12389
12553
|
lastPersistedHistoryMessages = [];
|
|
12554
|
+
lastCanonicalHermesSyncMtimeMs = 0;
|
|
12390
12555
|
instanceId;
|
|
12391
12556
|
suppressIdleHistoryReplay = false;
|
|
12392
12557
|
errorMessage = void 0;
|
|
@@ -12419,34 +12584,7 @@ var CliProviderInstance = class {
|
|
|
12419
12584
|
await this.enforceFreshSessionLaunchIfNeeded();
|
|
12420
12585
|
this.maybeAppendRuntimeRecoveryMessage(this.adapter.getRuntimeMetadata());
|
|
12421
12586
|
if (this.providerSessionId) {
|
|
12422
|
-
this.
|
|
12423
|
-
const restoredHistory = readChatHistory(this.type, 0, 200, this.providerSessionId);
|
|
12424
|
-
this.historyWriter.seedSessionHistory(
|
|
12425
|
-
this.type,
|
|
12426
|
-
restoredHistory.messages,
|
|
12427
|
-
this.providerSessionId,
|
|
12428
|
-
this.instanceId
|
|
12429
|
-
);
|
|
12430
|
-
this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
|
|
12431
|
-
role: message.role,
|
|
12432
|
-
content: message.content,
|
|
12433
|
-
kind: message.kind,
|
|
12434
|
-
senderName: message.senderName,
|
|
12435
|
-
receivedAt: message.receivedAt
|
|
12436
|
-
}));
|
|
12437
|
-
this.suppressIdleHistoryReplay = restoredHistory.messages.length > 0;
|
|
12438
|
-
if (restoredHistory.messages.length > 0) {
|
|
12439
|
-
this.adapter.seedCommittedMessages(
|
|
12440
|
-
restoredHistory.messages.map((message) => ({
|
|
12441
|
-
role: message.role,
|
|
12442
|
-
content: message.content,
|
|
12443
|
-
timestamp: message.receivedAt,
|
|
12444
|
-
receivedAt: message.receivedAt,
|
|
12445
|
-
kind: message.kind,
|
|
12446
|
-
senderName: message.senderName
|
|
12447
|
-
}))
|
|
12448
|
-
);
|
|
12449
|
-
}
|
|
12587
|
+
this.restorePersistedHistoryFromCurrentSession();
|
|
12450
12588
|
}
|
|
12451
12589
|
if (this.providerSessionId && this.launchMode === "resume") {
|
|
12452
12590
|
const resumedAt = Date.now();
|
|
@@ -12555,6 +12693,7 @@ var CliProviderInstance = class {
|
|
|
12555
12693
|
parsedMessages = historyMessageCount > 0 ? parsedMessages.slice(-historyMessageCount) : [];
|
|
12556
12694
|
}
|
|
12557
12695
|
const mergedMessages = this.mergeConversationMessages(parsedMessages);
|
|
12696
|
+
const canonicalHermesBackedHistory = this.syncCanonicalHermesSavedHistoryIfNeeded();
|
|
12558
12697
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
12559
12698
|
if (parsedMessages.length > 0) {
|
|
12560
12699
|
const shouldSkipReplayPersist = this.suppressIdleHistoryReplay && adapterStatus.status === "idle" && parsedStatus?.status === "idle";
|
|
@@ -12572,7 +12711,7 @@ var CliProviderInstance = class {
|
|
|
12572
12711
|
senderName: typeof message.senderName === "string" ? message.senderName : void 0,
|
|
12573
12712
|
receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
|
|
12574
12713
|
}));
|
|
12575
|
-
if (!shouldSkipReplayPersist && normalizedMessagesToSave.length > 0) {
|
|
12714
|
+
if (!canonicalHermesBackedHistory && !shouldSkipReplayPersist && normalizedMessagesToSave.length > 0) {
|
|
12576
12715
|
const incrementalMessages = buildIncrementalHistoryAppendMessages(this.lastPersistedHistoryMessages, normalizedMessagesToSave);
|
|
12577
12716
|
this.historyWriter.appendNewMessages(
|
|
12578
12717
|
this.type,
|
|
@@ -12582,7 +12721,9 @@ var CliProviderInstance = class {
|
|
|
12582
12721
|
this.providerSessionId
|
|
12583
12722
|
);
|
|
12584
12723
|
}
|
|
12585
|
-
|
|
12724
|
+
if (!canonicalHermesBackedHistory) {
|
|
12725
|
+
this.lastPersistedHistoryMessages = normalizedMessagesToSave;
|
|
12726
|
+
}
|
|
12586
12727
|
}
|
|
12587
12728
|
this.applyProviderResponse(parsedStatus, { phase: "immediate" });
|
|
12588
12729
|
const surface = resolveProviderStateSurface({
|
|
@@ -13039,6 +13180,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
13039
13180
|
this.providerSessionId = nextSessionId;
|
|
13040
13181
|
this.historyWriter.promoteHistorySession(this.type, previousHistorySessionId, nextSessionId);
|
|
13041
13182
|
this.historyWriter.writeSessionStart(this.type, nextSessionId, this.workingDir, this.instanceId);
|
|
13183
|
+
this.restorePersistedHistoryFromCurrentSession();
|
|
13042
13184
|
this.adapter.updateRuntimeMeta({ providerSessionId: nextSessionId });
|
|
13043
13185
|
this.onProviderSessionResolved?.({
|
|
13044
13186
|
instanceId: this.instanceId,
|
|
@@ -13050,6 +13192,61 @@ ${effect.notification.body || ""}`.trim();
|
|
|
13050
13192
|
});
|
|
13051
13193
|
LOG.info("CLI", `[${this.type}] discovered provider session id: ${nextSessionId}`);
|
|
13052
13194
|
}
|
|
13195
|
+
syncCanonicalHermesSavedHistoryIfNeeded() {
|
|
13196
|
+
if (this.type !== "hermes-cli" || !this.providerSessionId) return false;
|
|
13197
|
+
try {
|
|
13198
|
+
const canonicalPath = path11.join(os11.homedir(), ".hermes", "sessions", `session_${this.providerSessionId}.json`);
|
|
13199
|
+
if (!fs5.existsSync(canonicalPath)) return false;
|
|
13200
|
+
const stat = fs5.statSync(canonicalPath);
|
|
13201
|
+
if (stat.mtimeMs <= this.lastCanonicalHermesSyncMtimeMs) return true;
|
|
13202
|
+
const rebuilt = rebuildHermesSavedHistoryFromCanonicalSession(this.providerSessionId);
|
|
13203
|
+
if (!rebuilt) return false;
|
|
13204
|
+
this.lastCanonicalHermesSyncMtimeMs = stat.mtimeMs;
|
|
13205
|
+
const restoredHistory = readChatHistory(this.type, 0, 200, this.providerSessionId);
|
|
13206
|
+
this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
|
|
13207
|
+
role: message.role,
|
|
13208
|
+
content: message.content,
|
|
13209
|
+
kind: message.kind,
|
|
13210
|
+
senderName: message.senderName,
|
|
13211
|
+
receivedAt: message.receivedAt
|
|
13212
|
+
}));
|
|
13213
|
+
return true;
|
|
13214
|
+
} catch {
|
|
13215
|
+
return false;
|
|
13216
|
+
}
|
|
13217
|
+
}
|
|
13218
|
+
restorePersistedHistoryFromCurrentSession() {
|
|
13219
|
+
if (!this.providerSessionId) return;
|
|
13220
|
+
this.syncCanonicalHermesSavedHistoryIfNeeded();
|
|
13221
|
+
this.historyWriter.compactHistorySession(this.type, this.providerSessionId);
|
|
13222
|
+
const restoredHistory = readChatHistory(this.type, 0, 200, this.providerSessionId);
|
|
13223
|
+
this.historyWriter.seedSessionHistory(
|
|
13224
|
+
this.type,
|
|
13225
|
+
restoredHistory.messages,
|
|
13226
|
+
this.providerSessionId,
|
|
13227
|
+
this.instanceId
|
|
13228
|
+
);
|
|
13229
|
+
this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
|
|
13230
|
+
role: message.role,
|
|
13231
|
+
content: message.content,
|
|
13232
|
+
kind: message.kind,
|
|
13233
|
+
senderName: message.senderName,
|
|
13234
|
+
receivedAt: message.receivedAt
|
|
13235
|
+
}));
|
|
13236
|
+
this.suppressIdleHistoryReplay = restoredHistory.messages.length > 0;
|
|
13237
|
+
if (restoredHistory.messages.length > 0) {
|
|
13238
|
+
this.adapter.seedCommittedMessages(
|
|
13239
|
+
restoredHistory.messages.map((message) => ({
|
|
13240
|
+
role: message.role,
|
|
13241
|
+
content: message.content,
|
|
13242
|
+
timestamp: message.receivedAt,
|
|
13243
|
+
receivedAt: message.receivedAt,
|
|
13244
|
+
kind: message.kind,
|
|
13245
|
+
senderName: message.senderName
|
|
13246
|
+
}))
|
|
13247
|
+
);
|
|
13248
|
+
}
|
|
13249
|
+
}
|
|
13053
13250
|
getProbeDirectories() {
|
|
13054
13251
|
const dirs = /* @__PURE__ */ new Set();
|
|
13055
13252
|
const addDir = (value) => {
|
|
@@ -13659,13 +13856,13 @@ var AcpProviderInstance = class {
|
|
|
13659
13856
|
}
|
|
13660
13857
|
this.currentStatus = "waiting_approval";
|
|
13661
13858
|
this.detectStatusTransition();
|
|
13662
|
-
const approved = await new Promise((
|
|
13663
|
-
this.permissionResolvers.push(
|
|
13859
|
+
const approved = await new Promise((resolve12) => {
|
|
13860
|
+
this.permissionResolvers.push(resolve12);
|
|
13664
13861
|
setTimeout(() => {
|
|
13665
|
-
const idx = this.permissionResolvers.indexOf(
|
|
13862
|
+
const idx = this.permissionResolvers.indexOf(resolve12);
|
|
13666
13863
|
if (idx >= 0) {
|
|
13667
13864
|
this.permissionResolvers.splice(idx, 1);
|
|
13668
|
-
|
|
13865
|
+
resolve12(false);
|
|
13669
13866
|
}
|
|
13670
13867
|
}, 3e5);
|
|
13671
13868
|
});
|
|
@@ -15207,10 +15404,75 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
15207
15404
|
}
|
|
15208
15405
|
static GITHUB_TARBALL_URL = "https://github.com/vilmire/adhdev-providers/archive/refs/heads/main.tar.gz";
|
|
15209
15406
|
static META_FILE = ".meta.json";
|
|
15407
|
+
static REPO_PROVIDER_DIRNAME = "adhdev-providers";
|
|
15408
|
+
static SIBLING_MARKER_FILE = ".adhdev-provider-root";
|
|
15409
|
+
static SIBLING_ENV_VAR = "ADHDEV_USE_SIBLING_PROVIDERS";
|
|
15410
|
+
probeStarts = [];
|
|
15411
|
+
siblingLogged = false;
|
|
15412
|
+
userDirSource = "home-default";
|
|
15413
|
+
/** Process-level dedup for stderr sibling-adoption notices (shared across all ProviderLoader instances). */
|
|
15414
|
+
static siblingStderrLogged = /* @__PURE__ */ new Set();
|
|
15415
|
+
static looksLikeProviderRoot(candidate) {
|
|
15416
|
+
try {
|
|
15417
|
+
if (!fs6.existsSync(candidate) || !fs6.statSync(candidate).isDirectory()) return false;
|
|
15418
|
+
return ["ide", "extension", "cli", "acp"].some(
|
|
15419
|
+
(category) => fs6.existsSync(path13.join(candidate, category))
|
|
15420
|
+
);
|
|
15421
|
+
} catch {
|
|
15422
|
+
return false;
|
|
15423
|
+
}
|
|
15424
|
+
}
|
|
15425
|
+
static hasProviderRootMarker(candidate) {
|
|
15426
|
+
try {
|
|
15427
|
+
return fs6.existsSync(path13.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
|
|
15428
|
+
} catch {
|
|
15429
|
+
return false;
|
|
15430
|
+
}
|
|
15431
|
+
}
|
|
15432
|
+
detectDefaultUserDir() {
|
|
15433
|
+
const fallback = path13.join(os13.homedir(), ".adhdev", "providers");
|
|
15434
|
+
const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
|
|
15435
|
+
const visited = /* @__PURE__ */ new Set();
|
|
15436
|
+
for (const start of this.probeStarts) {
|
|
15437
|
+
let current = path13.resolve(start);
|
|
15438
|
+
while (!visited.has(current)) {
|
|
15439
|
+
visited.add(current);
|
|
15440
|
+
const siblingCandidate = path13.join(path13.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
|
|
15441
|
+
if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
|
|
15442
|
+
const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
|
|
15443
|
+
if (envOptIn || hasMarker) {
|
|
15444
|
+
const source = hasMarker ? "sibling-marker" : "sibling-env";
|
|
15445
|
+
if (!this.siblingLogged) {
|
|
15446
|
+
this.log(`Using sibling provider checkout (${source}): ${siblingCandidate}`);
|
|
15447
|
+
this.siblingLogged = true;
|
|
15448
|
+
}
|
|
15449
|
+
if (!_ProviderLoader.siblingStderrLogged.has(siblingCandidate)) {
|
|
15450
|
+
_ProviderLoader.siblingStderrLogged.add(siblingCandidate);
|
|
15451
|
+
try {
|
|
15452
|
+
process.stderr.write(
|
|
15453
|
+
`[adhdev] Using sibling adhdev-providers checkout (${source}): ${siblingCandidate}
|
|
15454
|
+
`
|
|
15455
|
+
);
|
|
15456
|
+
} catch {
|
|
15457
|
+
}
|
|
15458
|
+
}
|
|
15459
|
+
return { path: siblingCandidate, source };
|
|
15460
|
+
}
|
|
15461
|
+
}
|
|
15462
|
+
const parent = path13.dirname(current);
|
|
15463
|
+
if (parent === current) break;
|
|
15464
|
+
current = parent;
|
|
15465
|
+
}
|
|
15466
|
+
}
|
|
15467
|
+
return { path: fallback, source: "home-default" };
|
|
15468
|
+
}
|
|
15210
15469
|
constructor(options) {
|
|
15211
15470
|
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
15471
|
+
this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
|
|
15212
15472
|
this.defaultProvidersDir = path13.join(os13.homedir(), ".adhdev", "providers");
|
|
15213
|
-
|
|
15473
|
+
const detected = this.detectDefaultUserDir();
|
|
15474
|
+
this.userDir = detected.path;
|
|
15475
|
+
this.userDirSource = detected.source;
|
|
15214
15476
|
this.upstreamDir = path13.join(this.defaultProvidersDir, ".upstream");
|
|
15215
15477
|
this.disableUpstream = false;
|
|
15216
15478
|
this.applySourceConfig({
|
|
@@ -15248,6 +15510,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
15248
15510
|
disableUpstream: this.disableUpstream,
|
|
15249
15511
|
explicitProviderDir: this.explicitProviderDir,
|
|
15250
15512
|
userDir: this.userDir,
|
|
15513
|
+
userDirSource: this.userDirSource,
|
|
15251
15514
|
upstreamDir: this.upstreamDir,
|
|
15252
15515
|
providerRoots: this.getProviderRoots()
|
|
15253
15516
|
};
|
|
@@ -15258,7 +15521,14 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
15258
15521
|
this.explicitProviderDir = options.userDir?.trim() ? options.userDir : null;
|
|
15259
15522
|
}
|
|
15260
15523
|
this.sourceMode = nextSourceMode;
|
|
15261
|
-
|
|
15524
|
+
if (this.explicitProviderDir) {
|
|
15525
|
+
this.userDir = this.explicitProviderDir;
|
|
15526
|
+
this.userDirSource = "explicit";
|
|
15527
|
+
} else {
|
|
15528
|
+
const detected = this.detectDefaultUserDir();
|
|
15529
|
+
this.userDir = detected.path;
|
|
15530
|
+
this.userDirSource = detected.source;
|
|
15531
|
+
}
|
|
15262
15532
|
this.upstreamDir = path13.join(this.defaultProvidersDir, ".upstream");
|
|
15263
15533
|
this.disableUpstream = this.sourceMode === "no-upstream";
|
|
15264
15534
|
if (this.explicitProviderDir) {
|
|
@@ -15852,7 +16122,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
15852
16122
|
return { updated: false };
|
|
15853
16123
|
}
|
|
15854
16124
|
try {
|
|
15855
|
-
const etag = await new Promise((
|
|
16125
|
+
const etag = await new Promise((resolve12, reject) => {
|
|
15856
16126
|
const options = {
|
|
15857
16127
|
method: "HEAD",
|
|
15858
16128
|
hostname: "github.com",
|
|
@@ -15870,7 +16140,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
15870
16140
|
headers: { "User-Agent": "adhdev-launcher" },
|
|
15871
16141
|
timeout: 1e4
|
|
15872
16142
|
}, (res2) => {
|
|
15873
|
-
|
|
16143
|
+
resolve12(res2.headers.etag || res2.headers["last-modified"] || "");
|
|
15874
16144
|
});
|
|
15875
16145
|
req2.on("error", reject);
|
|
15876
16146
|
req2.on("timeout", () => {
|
|
@@ -15879,7 +16149,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
15879
16149
|
});
|
|
15880
16150
|
req2.end();
|
|
15881
16151
|
} else {
|
|
15882
|
-
|
|
16152
|
+
resolve12(res.headers.etag || res.headers["last-modified"] || "");
|
|
15883
16153
|
}
|
|
15884
16154
|
});
|
|
15885
16155
|
req.on("error", reject);
|
|
@@ -15943,7 +16213,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
15943
16213
|
downloadFile(url, destPath) {
|
|
15944
16214
|
const https = __require("https");
|
|
15945
16215
|
const http3 = __require("http");
|
|
15946
|
-
return new Promise((
|
|
16216
|
+
return new Promise((resolve12, reject) => {
|
|
15947
16217
|
const doRequest = (reqUrl, redirectCount = 0) => {
|
|
15948
16218
|
if (redirectCount > 5) {
|
|
15949
16219
|
reject(new Error("Too many redirects"));
|
|
@@ -15963,7 +16233,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
15963
16233
|
res.pipe(ws);
|
|
15964
16234
|
ws.on("finish", () => {
|
|
15965
16235
|
ws.close();
|
|
15966
|
-
|
|
16236
|
+
resolve12();
|
|
15967
16237
|
});
|
|
15968
16238
|
ws.on("error", reject);
|
|
15969
16239
|
});
|
|
@@ -16438,17 +16708,17 @@ async function findFreePort(ports) {
|
|
|
16438
16708
|
throw new Error("No free port found");
|
|
16439
16709
|
}
|
|
16440
16710
|
function checkPortFree(port) {
|
|
16441
|
-
return new Promise((
|
|
16711
|
+
return new Promise((resolve12) => {
|
|
16442
16712
|
const server = net.createServer();
|
|
16443
16713
|
server.unref();
|
|
16444
|
-
server.on("error", () =>
|
|
16714
|
+
server.on("error", () => resolve12(false));
|
|
16445
16715
|
server.listen(port, "127.0.0.1", () => {
|
|
16446
|
-
server.close(() =>
|
|
16716
|
+
server.close(() => resolve12(true));
|
|
16447
16717
|
});
|
|
16448
16718
|
});
|
|
16449
16719
|
}
|
|
16450
16720
|
async function isCdpActive(port) {
|
|
16451
|
-
return new Promise((
|
|
16721
|
+
return new Promise((resolve12) => {
|
|
16452
16722
|
const req = __require("http").get(`http://127.0.0.1:${port}/json/version`, {
|
|
16453
16723
|
timeout: 2e3
|
|
16454
16724
|
}, (res) => {
|
|
@@ -16457,16 +16727,16 @@ async function isCdpActive(port) {
|
|
|
16457
16727
|
res.on("end", () => {
|
|
16458
16728
|
try {
|
|
16459
16729
|
const info = JSON.parse(data);
|
|
16460
|
-
|
|
16730
|
+
resolve12(!!info["WebKit-Version"] || !!info["Browser"]);
|
|
16461
16731
|
} catch {
|
|
16462
|
-
|
|
16732
|
+
resolve12(false);
|
|
16463
16733
|
}
|
|
16464
16734
|
});
|
|
16465
16735
|
});
|
|
16466
|
-
req.on("error", () =>
|
|
16736
|
+
req.on("error", () => resolve12(false));
|
|
16467
16737
|
req.on("timeout", () => {
|
|
16468
16738
|
req.destroy();
|
|
16469
|
-
|
|
16739
|
+
resolve12(false);
|
|
16470
16740
|
});
|
|
16471
16741
|
});
|
|
16472
16742
|
}
|
|
@@ -17258,7 +17528,7 @@ async function waitForPidExit(pid, timeoutMs) {
|
|
|
17258
17528
|
while (Date.now() - start < timeoutMs) {
|
|
17259
17529
|
try {
|
|
17260
17530
|
process.kill(pid, 0);
|
|
17261
|
-
await new Promise((
|
|
17531
|
+
await new Promise((resolve12) => setTimeout(resolve12, 250));
|
|
17262
17532
|
} catch {
|
|
17263
17533
|
return;
|
|
17264
17534
|
}
|
|
@@ -17373,7 +17643,7 @@ async function runDaemonUpgradeHelper(payload) {
|
|
|
17373
17643
|
appendUpgradeLog(installOutput.trim());
|
|
17374
17644
|
}
|
|
17375
17645
|
if (process.platform === "win32") {
|
|
17376
|
-
await new Promise((
|
|
17646
|
+
await new Promise((resolve12) => setTimeout(resolve12, 500));
|
|
17377
17647
|
cleanupStaleGlobalInstallDirs(payload.packageName);
|
|
17378
17648
|
appendUpgradeLog("Post-install staging cleanup complete");
|
|
17379
17649
|
}
|
|
@@ -18715,7 +18985,7 @@ var ProviderStreamAdapter = class {
|
|
|
18715
18985
|
const beforeCount = this.messageCount(before);
|
|
18716
18986
|
const beforeSignature = this.lastMessageSignature(before);
|
|
18717
18987
|
for (let attempt = 0; attempt < 12; attempt += 1) {
|
|
18718
|
-
await new Promise((
|
|
18988
|
+
await new Promise((resolve12) => setTimeout(resolve12, 250));
|
|
18719
18989
|
let state;
|
|
18720
18990
|
try {
|
|
18721
18991
|
state = await this.readChat(evaluate);
|
|
@@ -18737,7 +19007,7 @@ var ProviderStreamAdapter = class {
|
|
|
18737
19007
|
if (this.messageCount(first) > 0 || this.lastMessageSignature(first)) {
|
|
18738
19008
|
return first;
|
|
18739
19009
|
}
|
|
18740
|
-
await new Promise((
|
|
19010
|
+
await new Promise((resolve12) => setTimeout(resolve12, 150));
|
|
18741
19011
|
const second = await this.readChat(evaluate);
|
|
18742
19012
|
return this.messageCount(second) >= this.messageCount(first) ? second : first;
|
|
18743
19013
|
}
|
|
@@ -18888,7 +19158,7 @@ var ProviderStreamAdapter = class {
|
|
|
18888
19158
|
if (typeof data.error === "string" && data.error.trim()) return false;
|
|
18889
19159
|
}
|
|
18890
19160
|
for (let attempt = 0; attempt < 6; attempt += 1) {
|
|
18891
|
-
await new Promise((
|
|
19161
|
+
await new Promise((resolve12) => setTimeout(resolve12, 250));
|
|
18892
19162
|
const state = await this.readChat(evaluate);
|
|
18893
19163
|
const title = this.getStateTitle(state);
|
|
18894
19164
|
if (this.titlesMatch(title, sessionId)) return true;
|
|
@@ -21414,7 +21684,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
|
|
|
21414
21684
|
return { target, instance, adapter };
|
|
21415
21685
|
}
|
|
21416
21686
|
function sleep(ms) {
|
|
21417
|
-
return new Promise((
|
|
21687
|
+
return new Promise((resolve12) => setTimeout(resolve12, ms));
|
|
21418
21688
|
}
|
|
21419
21689
|
async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
|
|
21420
21690
|
const startedAt = Date.now();
|
|
@@ -23672,15 +23942,15 @@ var DevServer = class _DevServer {
|
|
|
23672
23942
|
this.json(res, 500, { error: e.message });
|
|
23673
23943
|
}
|
|
23674
23944
|
});
|
|
23675
|
-
return new Promise((
|
|
23945
|
+
return new Promise((resolve12, reject) => {
|
|
23676
23946
|
this.server.listen(port, "127.0.0.1", () => {
|
|
23677
23947
|
this.log(`Dev server listening on http://127.0.0.1:${port}`);
|
|
23678
|
-
|
|
23948
|
+
resolve12();
|
|
23679
23949
|
});
|
|
23680
23950
|
this.server.on("error", (e) => {
|
|
23681
23951
|
if (e.code === "EADDRINUSE") {
|
|
23682
23952
|
this.log(`Port ${port} in use, skipping dev server`);
|
|
23683
|
-
|
|
23953
|
+
resolve12();
|
|
23684
23954
|
} else {
|
|
23685
23955
|
reject(e);
|
|
23686
23956
|
}
|
|
@@ -23762,20 +24032,20 @@ var DevServer = class _DevServer {
|
|
|
23762
24032
|
child.stderr?.on("data", (d) => {
|
|
23763
24033
|
stderr += d.toString().slice(0, 2e3);
|
|
23764
24034
|
});
|
|
23765
|
-
await new Promise((
|
|
24035
|
+
await new Promise((resolve12) => {
|
|
23766
24036
|
const timer = setTimeout(() => {
|
|
23767
24037
|
child.kill();
|
|
23768
|
-
|
|
24038
|
+
resolve12();
|
|
23769
24039
|
}, 3e3);
|
|
23770
24040
|
child.on("exit", () => {
|
|
23771
24041
|
clearTimeout(timer);
|
|
23772
|
-
|
|
24042
|
+
resolve12();
|
|
23773
24043
|
});
|
|
23774
24044
|
child.stdout?.once("data", () => {
|
|
23775
24045
|
setTimeout(() => {
|
|
23776
24046
|
child.kill();
|
|
23777
24047
|
clearTimeout(timer);
|
|
23778
|
-
|
|
24048
|
+
resolve12();
|
|
23779
24049
|
}, 500);
|
|
23780
24050
|
});
|
|
23781
24051
|
});
|
|
@@ -24291,14 +24561,14 @@ var DevServer = class _DevServer {
|
|
|
24291
24561
|
child.stderr?.on("data", (d) => {
|
|
24292
24562
|
stderr += d.toString();
|
|
24293
24563
|
});
|
|
24294
|
-
await new Promise((
|
|
24564
|
+
await new Promise((resolve12) => {
|
|
24295
24565
|
const timer = setTimeout(() => {
|
|
24296
24566
|
child.kill();
|
|
24297
|
-
|
|
24567
|
+
resolve12();
|
|
24298
24568
|
}, timeout);
|
|
24299
24569
|
child.on("exit", () => {
|
|
24300
24570
|
clearTimeout(timer);
|
|
24301
|
-
|
|
24571
|
+
resolve12();
|
|
24302
24572
|
});
|
|
24303
24573
|
});
|
|
24304
24574
|
const elapsed = Date.now() - start;
|
|
@@ -24968,14 +25238,14 @@ data: ${JSON.stringify(msg.data)}
|
|
|
24968
25238
|
res.end(JSON.stringify(data, null, 2));
|
|
24969
25239
|
}
|
|
24970
25240
|
async readBody(req) {
|
|
24971
|
-
return new Promise((
|
|
25241
|
+
return new Promise((resolve12) => {
|
|
24972
25242
|
let body = "";
|
|
24973
25243
|
req.on("data", (chunk) => body += chunk);
|
|
24974
25244
|
req.on("end", () => {
|
|
24975
25245
|
try {
|
|
24976
|
-
|
|
25246
|
+
resolve12(JSON.parse(body));
|
|
24977
25247
|
} catch {
|
|
24978
|
-
|
|
25248
|
+
resolve12({});
|
|
24979
25249
|
}
|
|
24980
25250
|
});
|
|
24981
25251
|
});
|
|
@@ -25488,7 +25758,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
|
|
|
25488
25758
|
const deadline = Date.now() + timeoutMs;
|
|
25489
25759
|
while (Date.now() < deadline) {
|
|
25490
25760
|
if (await canConnect(endpoint)) return;
|
|
25491
|
-
await new Promise((
|
|
25761
|
+
await new Promise((resolve12) => setTimeout(resolve12, STARTUP_POLL_MS));
|
|
25492
25762
|
}
|
|
25493
25763
|
throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
|
|
25494
25764
|
}
|
|
@@ -25666,10 +25936,10 @@ async function installExtension(ide, extension) {
|
|
|
25666
25936
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
25667
25937
|
const fs15 = await import("fs");
|
|
25668
25938
|
fs15.writeFileSync(vsixPath, buffer);
|
|
25669
|
-
return new Promise((
|
|
25939
|
+
return new Promise((resolve12) => {
|
|
25670
25940
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
25671
25941
|
exec2(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
|
|
25672
|
-
|
|
25942
|
+
resolve12({
|
|
25673
25943
|
extensionId: extension.id,
|
|
25674
25944
|
marketplaceId: extension.marketplaceId,
|
|
25675
25945
|
success: !error,
|
|
@@ -25682,11 +25952,11 @@ async function installExtension(ide, extension) {
|
|
|
25682
25952
|
} catch (e) {
|
|
25683
25953
|
}
|
|
25684
25954
|
}
|
|
25685
|
-
return new Promise((
|
|
25955
|
+
return new Promise((resolve12) => {
|
|
25686
25956
|
const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
|
|
25687
25957
|
exec2(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
|
|
25688
25958
|
if (error) {
|
|
25689
|
-
|
|
25959
|
+
resolve12({
|
|
25690
25960
|
extensionId: extension.id,
|
|
25691
25961
|
marketplaceId: extension.marketplaceId,
|
|
25692
25962
|
success: false,
|
|
@@ -25694,7 +25964,7 @@ async function installExtension(ide, extension) {
|
|
|
25694
25964
|
error: stderr || error.message
|
|
25695
25965
|
});
|
|
25696
25966
|
} else {
|
|
25697
|
-
|
|
25967
|
+
resolve12({
|
|
25698
25968
|
extensionId: extension.id,
|
|
25699
25969
|
marketplaceId: extension.marketplaceId,
|
|
25700
25970
|
success: true,
|