@adhdev/daemon-core 0.6.74 → 0.6.76
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/index.d.ts +7 -1
- package/dist/index.js +111 -58
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/cli-adapters/provider-cli-adapter.ts +72 -19
- package/src/commands/handler.ts +17 -1
- package/src/daemon/dev-server.ts +28 -15
- package/src/detection/cli-detector.ts +18 -5
- package/src/providers/cli-provider-instance.ts +8 -23
- package/src/providers/provider-loader.ts +9 -2
- package/src/shared-types.ts +1 -1
- package/src/status/builders.ts +1 -1
package/package.json
CHANGED
|
@@ -146,6 +146,25 @@ function stripAnsi(str: string): string {
|
|
|
146
146
|
.replace(/ +/g, ' ');
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
+
function stripTerminalNoise(str: string): string {
|
|
150
|
+
return String(str || '')
|
|
151
|
+
// Remove remaining C0/C1 control chars except newlines/tabs.
|
|
152
|
+
// eslint-disable-next-line no-control-regex
|
|
153
|
+
.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]/g, '')
|
|
154
|
+
// Drop common terminal negotiation/report fragments that can remain after ANSI stripping.
|
|
155
|
+
.replace(/(^|[\s([])(?:\??\d{1,4}(?:;\d{1,4})*[A-Za-z])(?=$|[\s)\]])/g, '$1')
|
|
156
|
+
.replace(/(^|[\s([])(?:\[\??\d{1,4}(?:;\d{1,4})*[A-Za-z])(?=$|[\s)\]])/g, '$1')
|
|
157
|
+
.replace(/(^|[\s([])(?:\d{1,4};\?)(?=$|[\s)\]])/g, '$1')
|
|
158
|
+
.replace(/\r+/g, '\n')
|
|
159
|
+
.replace(/[ \t]+\n/g, '\n')
|
|
160
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
161
|
+
.replace(/ {2,}/g, ' ');
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function sanitizeTerminalText(str: string): string {
|
|
165
|
+
return stripTerminalNoise(stripAnsi(str));
|
|
166
|
+
}
|
|
167
|
+
|
|
149
168
|
function findBinary(name: string): string {
|
|
150
169
|
const isWin = os.platform() === 'win32';
|
|
151
170
|
try {
|
|
@@ -370,6 +389,9 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
370
389
|
// Approval state machine
|
|
371
390
|
private approvalTransitionBuffer: string = '';
|
|
372
391
|
private approvalExitTimeout: NodeJS.Timeout | null = null;
|
|
392
|
+
private pendingScriptStatus: 'generating' | 'waiting_approval' | null = null;
|
|
393
|
+
private pendingScriptStatusSince = 0;
|
|
394
|
+
private pendingScriptStatusTimer: NodeJS.Timeout | null = null;
|
|
373
395
|
|
|
374
396
|
// Output settle debounce — fires after PTY output goes quiet
|
|
375
397
|
private settleTimer: NodeJS.Timeout | null = null;
|
|
@@ -454,6 +476,7 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
454
476
|
private readonly sendDelayMs: number;
|
|
455
477
|
private readonly sendKey: string;
|
|
456
478
|
private readonly submitStrategy: 'wait_for_echo' | 'immediate';
|
|
479
|
+
private static readonly SCRIPT_STATUS_DEBOUNCE_MS = 1000;
|
|
457
480
|
|
|
458
481
|
constructor(provider: CliProviderModule, workingDir: string, private extraArgs: string[] = []) {
|
|
459
482
|
this.provider = provider;
|
|
@@ -645,7 +668,7 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
645
668
|
private handleOutput(rawData: string): void {
|
|
646
669
|
this.terminalScreen.write(rawData);
|
|
647
670
|
this.terminalHistory = mergeTerminalHistory(this.terminalHistory, this.terminalScreen.getText());
|
|
648
|
-
const cleanData =
|
|
671
|
+
const cleanData = sanitizeTerminalText(rawData);
|
|
649
672
|
|
|
650
673
|
if (this.isWaitingForResponse && cleanData) {
|
|
651
674
|
this.responseBuffer = (this.responseBuffer + cleanData).slice(-8000);
|
|
@@ -764,26 +787,45 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
764
787
|
|
|
765
788
|
const prevStatus = this.currentStatus;
|
|
766
789
|
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
790
|
+
const clearPendingScriptStatus = () => {
|
|
791
|
+
this.pendingScriptStatus = null;
|
|
792
|
+
this.pendingScriptStatusSince = 0;
|
|
793
|
+
if (this.pendingScriptStatusTimer) {
|
|
794
|
+
clearTimeout(this.pendingScriptStatusTimer);
|
|
795
|
+
this.pendingScriptStatusTimer = null;
|
|
796
|
+
}
|
|
797
|
+
};
|
|
798
|
+
const armPendingScriptStatus = (delayMs: number) => {
|
|
799
|
+
if (this.pendingScriptStatusTimer) clearTimeout(this.pendingScriptStatusTimer);
|
|
800
|
+
this.pendingScriptStatusTimer = setTimeout(() => {
|
|
801
|
+
this.pendingScriptStatusTimer = null;
|
|
802
|
+
this.settledBuffer = this.recentOutputBuffer;
|
|
803
|
+
this.evaluateSettled();
|
|
804
|
+
}, delayMs);
|
|
805
|
+
};
|
|
806
|
+
const shouldDebouncePromotion = (status: string) =>
|
|
807
|
+
prevStatus === 'idle'
|
|
808
|
+
&& !this.isWaitingForResponse
|
|
809
|
+
&& !this.currentTurnScope
|
|
810
|
+
&& (status === 'generating' || status === 'waiting_approval');
|
|
811
|
+
|
|
812
|
+
if (shouldDebouncePromotion(scriptStatus)) {
|
|
813
|
+
if (this.pendingScriptStatus !== scriptStatus) {
|
|
814
|
+
this.pendingScriptStatus = scriptStatus as 'generating' | 'waiting_approval';
|
|
815
|
+
this.pendingScriptStatusSince = now;
|
|
816
|
+
armPendingScriptStatus(ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS);
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
const elapsed = now - this.pendingScriptStatusSince;
|
|
820
|
+
if (elapsed < ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS) {
|
|
821
|
+
armPendingScriptStatus(ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS - elapsed);
|
|
784
822
|
return;
|
|
785
823
|
}
|
|
824
|
+
} else {
|
|
825
|
+
clearPendingScriptStatus();
|
|
826
|
+
}
|
|
786
827
|
|
|
828
|
+
if (scriptStatus === 'waiting_approval') {
|
|
787
829
|
const inCooldown = this.lastApprovalResolvedAt && (Date.now() - this.lastApprovalResolvedAt) < this.timeouts.approvalCooldown;
|
|
788
830
|
if (!inCooldown) {
|
|
789
831
|
this.isWaitingForResponse = true;
|
|
@@ -800,6 +842,16 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
800
842
|
}
|
|
801
843
|
|
|
802
844
|
if (scriptStatus === 'generating') {
|
|
845
|
+
const screenText = this.terminalScreen.getText() || this.accumulatedBuffer;
|
|
846
|
+
const noActiveTurn = !this.currentTurnScope;
|
|
847
|
+
const looksIdleChrome = /(^|\n)\s*[❯›>]\s*(?:\n|$)/m.test(screenText)
|
|
848
|
+
|| (/accept edits on/i.test(screenText)
|
|
849
|
+
&& (/Update available!/i.test(screenText)
|
|
850
|
+
|| /\/effort/i.test(screenText)
|
|
851
|
+
|| /^.*➜\s+\S+/m.test(screenText)));
|
|
852
|
+
if (prevStatus === 'idle' && !this.isWaitingForResponse && noActiveTurn && !modal && looksIdleChrome) {
|
|
853
|
+
return;
|
|
854
|
+
}
|
|
803
855
|
if (prevStatus === 'waiting_approval') {
|
|
804
856
|
// Transitioned out of approval → generating
|
|
805
857
|
if (this.approvalExitTimeout) { clearTimeout(this.approvalExitTimeout); this.approvalExitTimeout = null; }
|
|
@@ -1242,7 +1294,7 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1242
1294
|
committedMessages: this.committedMessages.slice(-20),
|
|
1243
1295
|
structuredMessages: this.structuredMessages.slice(-20),
|
|
1244
1296
|
messageCount: this.committedMessages.length,
|
|
1245
|
-
screenText: this.terminalScreen.getText().slice(-4000),
|
|
1297
|
+
screenText: sanitizeTerminalText(this.terminalScreen.getText()).slice(-4000),
|
|
1246
1298
|
terminalHistory: this.terminalHistory.slice(-8000),
|
|
1247
1299
|
currentTurnScope: this.currentTurnScope,
|
|
1248
1300
|
startupBuffer: this.startupBuffer.slice(-4000),
|
|
@@ -1251,6 +1303,7 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1251
1303
|
accumulatedBufferLength: this.accumulatedBuffer.length,
|
|
1252
1304
|
accumulatedRawBufferLength: this.accumulatedRawBuffer.length,
|
|
1253
1305
|
rawBufferPreview: this.accumulatedRawBuffer.slice(-1000),
|
|
1306
|
+
sanitizedRawPreview: sanitizeTerminalText(this.accumulatedRawBuffer).slice(-1000),
|
|
1254
1307
|
responseBuffer: this.responseBuffer.slice(-1000),
|
|
1255
1308
|
isWaitingForResponse: this.isWaitingForResponse,
|
|
1256
1309
|
activeModal: this.activeModal,
|
package/src/commands/handler.ts
CHANGED
|
@@ -168,8 +168,24 @@ export class DaemonCommandHandler implements CommandHelpers {
|
|
|
168
168
|
getCliAdapter(type?: string): any | null {
|
|
169
169
|
const target = type || this._currentIdeType;
|
|
170
170
|
if (!target || !this._ctx.adapters) return null;
|
|
171
|
+
// Normalize composite transport IDs:
|
|
172
|
+
// standalone_xxx:cli:<uuid> -> <uuid>
|
|
173
|
+
// daemon:acp:<uuid> -> <uuid>
|
|
174
|
+
let normalizedTarget = target;
|
|
175
|
+
const colonIdx = normalizedTarget.lastIndexOf(':');
|
|
176
|
+
if (colonIdx >= 0) normalizedTarget = normalizedTarget.substring(colonIdx + 1);
|
|
177
|
+
|
|
178
|
+
const direct = this._ctx.adapters.get(normalizedTarget);
|
|
179
|
+
if (direct) return direct;
|
|
180
|
+
|
|
171
181
|
for (const [key, adapter] of this._ctx.adapters.entries()) {
|
|
172
|
-
if (
|
|
182
|
+
if (
|
|
183
|
+
(adapter as any).cliType === target
|
|
184
|
+
|| (adapter as any).cliType === normalizedTarget
|
|
185
|
+
|| key === normalizedTarget
|
|
186
|
+
|| key.startsWith(target)
|
|
187
|
+
|| key.startsWith(normalizedTarget)
|
|
188
|
+
) {
|
|
173
189
|
return adapter;
|
|
174
190
|
}
|
|
175
191
|
}
|
package/src/daemon/dev-server.ts
CHANGED
|
@@ -1895,22 +1895,25 @@ export class DevServer {
|
|
|
1895
1895
|
return path.join(scriptsDir, versions[0]);
|
|
1896
1896
|
}
|
|
1897
1897
|
|
|
1898
|
-
private resolveAutoImplWritableProviderDir(
|
|
1898
|
+
private resolveAutoImplWritableProviderDir(
|
|
1899
|
+
category: ProviderCategory,
|
|
1900
|
+
type: string,
|
|
1901
|
+
requestedDir?: string,
|
|
1902
|
+
): { dir: string | null; reason?: string } {
|
|
1899
1903
|
const canonicalUserDir = path.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
1900
1904
|
const desiredDir = requestedDir ? path.resolve(requestedDir) : canonicalUserDir;
|
|
1901
|
-
|
|
1902
|
-
if (desiredDir
|
|
1903
|
-
return null;
|
|
1905
|
+
const upstreamRoot = path.resolve(this.providerLoader.getUpstreamDir());
|
|
1906
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path.sep}`)) {
|
|
1907
|
+
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
1904
1908
|
}
|
|
1905
1909
|
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
return null;
|
|
1910
|
+
if (path.basename(desiredDir) !== type) {
|
|
1911
|
+
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
1909
1912
|
}
|
|
1910
1913
|
|
|
1911
1914
|
const sourceDir = this.findProviderDir(type);
|
|
1912
1915
|
if (!sourceDir) {
|
|
1913
|
-
return null;
|
|
1916
|
+
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
1914
1917
|
}
|
|
1915
1918
|
|
|
1916
1919
|
if (!fs.existsSync(desiredDir)) {
|
|
@@ -1921,7 +1924,7 @@ export class DevServer {
|
|
|
1921
1924
|
|
|
1922
1925
|
const providerJson = path.join(desiredDir, 'provider.json');
|
|
1923
1926
|
if (!fs.existsSync(providerJson)) {
|
|
1924
|
-
return null;
|
|
1927
|
+
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
1925
1928
|
}
|
|
1926
1929
|
|
|
1927
1930
|
try {
|
|
@@ -1930,11 +1933,14 @@ export class DevServer {
|
|
|
1930
1933
|
providerData.disableUpstream = true;
|
|
1931
1934
|
fs.writeFileSync(providerJson, JSON.stringify(providerData, null, 2));
|
|
1932
1935
|
}
|
|
1933
|
-
} catch {
|
|
1934
|
-
return
|
|
1936
|
+
} catch (error) {
|
|
1937
|
+
return {
|
|
1938
|
+
dir: null,
|
|
1939
|
+
reason: `Failed to update provider.json in writable provider directory: ${(error as Error).message}`,
|
|
1940
|
+
};
|
|
1935
1941
|
}
|
|
1936
1942
|
|
|
1937
|
-
return desiredDir;
|
|
1943
|
+
return { dir: desiredDir };
|
|
1938
1944
|
}
|
|
1939
1945
|
|
|
1940
1946
|
private loadAutoImplReferenceScripts(referenceType: string | null): Record<string, string> {
|
|
@@ -1975,13 +1981,14 @@ export class DevServer {
|
|
|
1975
1981
|
const provider = this.providerLoader.resolve(type);
|
|
1976
1982
|
if (!provider) { this.json(res, 404, { error: `Provider not found: ${type}` }); return; }
|
|
1977
1983
|
|
|
1978
|
-
const
|
|
1979
|
-
if (!
|
|
1984
|
+
const writableProvider = this.resolveAutoImplWritableProviderDir(provider.category, type, requestedProviderDir);
|
|
1985
|
+
if (!writableProvider.dir) {
|
|
1980
1986
|
this.json(res, 409, {
|
|
1981
|
-
error: `Auto-implement only writes to the canonical user provider directory for '${type}'.`,
|
|
1987
|
+
error: writableProvider.reason || `Auto-implement only writes to the canonical user provider directory for '${type}'.`,
|
|
1982
1988
|
});
|
|
1983
1989
|
return;
|
|
1984
1990
|
}
|
|
1991
|
+
const providerDir = writableProvider.dir;
|
|
1985
1992
|
|
|
1986
1993
|
try {
|
|
1987
1994
|
// 1. Collect DOM context
|
|
@@ -2749,6 +2756,9 @@ export class DevServer {
|
|
|
2749
2756
|
lines.push('8. Keep exports compatible with the existing `scripts.js` router (`module.exports = function ...`).');
|
|
2750
2757
|
lines.push('9. Do not rewrite unrelated provider config. Only touch the scripts needed for this task unless a tiny supporting change is required.');
|
|
2751
2758
|
lines.push('10. When the verification API returns `instanceId`, keep using that exact instance for follow-up `send`, `resolve`, `raw`, and `stop` calls. Do not assume type-only routing is safe if multiple sessions exist.');
|
|
2759
|
+
lines.push('11. Do NOT repeatedly dump the same target files. Read the target scripts once, reproduce the bug, then move directly to patching.');
|
|
2760
|
+
lines.push('12. If the user instructions include concrete screen text, raw PTY snippets, or a specific repro, treat that as the primary acceptance criteria.');
|
|
2761
|
+
lines.push('13. After the first successful live repro, stop broad diagnosis. Edit the scripts, reload, and verify. Do not burn tokens on repeated re-inspection without code changes.');
|
|
2752
2762
|
lines.push('');
|
|
2753
2763
|
|
|
2754
2764
|
lines.push('## Task');
|
|
@@ -2792,6 +2802,9 @@ export class DevServer {
|
|
|
2792
2802
|
lines.push('');
|
|
2793
2803
|
lines.push('Use `resolve` when the parsed modal buttons are correct. Use `raw` when the CLI expects a literal keystroke like `1`, `y`, or Enter. Repeat until idle.');
|
|
2794
2804
|
lines.push('');
|
|
2805
|
+
lines.push('### Patch Discipline');
|
|
2806
|
+
lines.push('Once the repro is confirmed, immediately edit the target files. Avoid loops where you keep re-reading long files or re-running the same debug commands without changing code.');
|
|
2807
|
+
lines.push('');
|
|
2795
2808
|
lines.push('### 5. Verify the side effects outside the CLI');
|
|
2796
2809
|
lines.push('```bash');
|
|
2797
2810
|
lines.push('test -f tmp/adhdev_provider_fix_test.py');
|
|
@@ -16,12 +16,18 @@ export interface CLIInfo {
|
|
|
16
16
|
displayName: string;
|
|
17
17
|
icon: string;
|
|
18
18
|
command: string;
|
|
19
|
+
versionCommand?: string;
|
|
19
20
|
installed: boolean;
|
|
20
21
|
version?: string;
|
|
21
22
|
path?: string;
|
|
22
23
|
category?: string;
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
function parseVersion(raw: string): string {
|
|
27
|
+
const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
|
|
28
|
+
return match ? match[1] : raw.split('\n')[0].slice(0, 100);
|
|
29
|
+
}
|
|
30
|
+
|
|
25
31
|
/** Run a shell command with timeout, returning stdout or null on failure */
|
|
26
32
|
function execAsync(cmd: string, timeoutMs = 5000): Promise<string | null> {
|
|
27
33
|
return new Promise((resolve) => {
|
|
@@ -62,11 +68,18 @@ export async function detectCLIs(providerLoader?: ProviderLoader): Promise<CLIIn
|
|
|
62
68
|
// Get version (parallel with other checks)
|
|
63
69
|
let version: string | undefined;
|
|
64
70
|
try {
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
71
|
+
const versionCommands = [
|
|
72
|
+
cli.versionCommand,
|
|
73
|
+
`${cli.command} --version 2>/dev/null`,
|
|
74
|
+
`${cli.command} -V 2>/dev/null`,
|
|
75
|
+
`${cli.command} -v 2>/dev/null`,
|
|
76
|
+
].filter((v): v is string => !!v);
|
|
77
|
+
for (const versionCommand of versionCommands) {
|
|
78
|
+
const versionResult = await execAsync(versionCommand, 3000);
|
|
79
|
+
if (versionResult) {
|
|
80
|
+
version = parseVersion(versionResult);
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
70
83
|
}
|
|
71
84
|
} catch { }
|
|
72
85
|
|
|
@@ -85,25 +85,6 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
85
85
|
|
|
86
86
|
const dirName = this.workingDir.split('/').filter(Boolean).pop() || 'session';
|
|
87
87
|
|
|
88
|
-
// Preserve rich message objects, just truncate extremely long text strings
|
|
89
|
-
const recentMessages = adapterStatus.messages.slice(-50).map((m: any) => {
|
|
90
|
-
const content = typeof m.content === 'string' && m.content.length > 8000
|
|
91
|
-
? m.content.slice(0, 8000) + '\n... (truncated)'
|
|
92
|
-
: m.content;
|
|
93
|
-
return { ...m, content };
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
// generating during partial response add
|
|
97
|
-
// Save history
|
|
98
|
-
if (recentMessages.length > 0) {
|
|
99
|
-
const dirName = this.workingDir.split('/').filter(Boolean).pop() || 'session';
|
|
100
|
-
this.historyWriter.appendNewMessages(
|
|
101
|
-
this.type,
|
|
102
|
-
recentMessages,
|
|
103
|
-
`${this.provider.name} · ${dirName}`,
|
|
104
|
-
this.instanceId,
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
88
|
if (adapterStatus.terminalHistory?.trim()) {
|
|
108
89
|
this.historyWriter.appendTerminalHistory(
|
|
109
90
|
this.type,
|
|
@@ -118,12 +99,12 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
118
99
|
name: this.provider.name,
|
|
119
100
|
category: 'cli',
|
|
120
101
|
status: adapterStatus.status,
|
|
121
|
-
mode:
|
|
102
|
+
mode: 'terminal',
|
|
122
103
|
activeChat: {
|
|
123
104
|
id: `${this.type}_${this.workingDir}`,
|
|
124
105
|
title: `${this.provider.name} · ${dirName}`,
|
|
125
106
|
status: adapterStatus.status,
|
|
126
|
-
messages:
|
|
107
|
+
messages: [],
|
|
127
108
|
activeModal: adapterStatus.activeModal,
|
|
128
109
|
terminalHistory: adapterStatus.terminalHistory,
|
|
129
110
|
inputContent: '',
|
|
@@ -138,11 +119,15 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
138
119
|
|
|
139
120
|
onEvent(event: string, data?: any): void {
|
|
140
121
|
if (event === 'send_message' && data?.text) {
|
|
141
|
-
this.adapter.sendMessage(data.text)
|
|
122
|
+
void this.adapter.sendMessage(data.text).catch((e: any) => {
|
|
123
|
+
LOG.warn('CLI', `[${this.type}] send_message failed: ${e?.message || e}`);
|
|
124
|
+
});
|
|
142
125
|
} else if (event === 'server_connected' && data?.serverConn) {
|
|
143
126
|
this.adapter.setServerConn(data.serverConn);
|
|
144
127
|
} else if (event === 'resolve_action' && data) {
|
|
145
|
-
this.adapter.resolveAction(data)
|
|
128
|
+
void this.adapter.resolveAction(data).catch((e: any) => {
|
|
129
|
+
LOG.warn('CLI', `[${this.type}] resolve_action failed: ${e?.message || e}`);
|
|
130
|
+
});
|
|
146
131
|
}
|
|
147
132
|
}
|
|
148
133
|
|
|
@@ -237,16 +237,23 @@ export class ProviderLoader {
|
|
|
237
237
|
* Build CLI/ACP detection list (replaces cli-detector)
|
|
238
238
|
* Dynamically generated from provider.js spawn.command.
|
|
239
239
|
*/
|
|
240
|
-
getCliDetectionList(): { id: string; displayName: string; icon: string; command: string; category: string }[] {
|
|
241
|
-
const result: { id: string; displayName: string; icon: string; command: string; category: string }[] = [];
|
|
240
|
+
getCliDetectionList(): { id: string; displayName: string; icon: string; command: string; category: string; versionCommand?: string }[] {
|
|
241
|
+
const result: { id: string; displayName: string; icon: string; command: string; category: string; versionCommand?: string }[] = [];
|
|
242
242
|
for (const p of this.providers.values()) {
|
|
243
243
|
if ((p.category === 'cli' || p.category === 'acp') && p.spawn?.command) {
|
|
244
|
+
const verCmdConfig = (p as any).versionCommand;
|
|
245
|
+
const versionCommand = typeof verCmdConfig === 'object' && verCmdConfig !== null
|
|
246
|
+
? verCmdConfig[process.platform]
|
|
247
|
+
: verCmdConfig;
|
|
244
248
|
result.push({
|
|
245
249
|
id: p.type,
|
|
246
250
|
displayName: p.displayName || p.name,
|
|
247
251
|
icon: p.icon || '🔧',
|
|
248
252
|
command: p.spawn.command,
|
|
249
253
|
category: p.category,
|
|
254
|
+
...(typeof versionCommand === 'string' && versionCommand.trim()
|
|
255
|
+
? { versionCommand: versionCommand.trim() }
|
|
256
|
+
: {}),
|
|
250
257
|
});
|
|
251
258
|
}
|
|
252
259
|
}
|
package/src/shared-types.ts
CHANGED
package/src/status/builders.ts
CHANGED