@oh-my-pi/pi-coding-agent 17.0.4 → 17.0.6
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/CHANGELOG.md +209 -0
- package/dist/cli.js +3616 -3676
- package/dist/types/advisor/advise-tool.d.ts +3 -0
- package/dist/types/advisor/runtime.d.ts +7 -1
- package/dist/types/async/job-manager.d.ts +2 -0
- package/dist/types/config/model-registry.d.ts +7 -0
- package/dist/types/config/model-resolver.d.ts +8 -0
- package/dist/types/config/models-config-schema.d.ts +10 -0
- package/dist/types/config/models-config.d.ts +6 -0
- package/dist/types/dap/client.d.ts +10 -0
- package/dist/types/dap/types.d.ts +6 -5
- package/dist/types/exec/bash-executor.d.ts +1 -0
- package/dist/types/extensibility/extensions/load-errors.d.ts +3 -0
- package/dist/types/extensibility/extensions/runner.d.ts +4 -2
- package/dist/types/extensibility/legacy-pi-coding-agent-shim.d.ts +16 -0
- package/dist/types/extensibility/plugins/legacy-pi-compat.d.ts +8 -0
- package/dist/types/launch/spawn-options.d.ts +10 -0
- package/dist/types/launch/spawn-options.test.d.ts +1 -0
- package/dist/types/modes/components/status-line/component.d.ts +10 -3
- package/dist/types/modes/components/status-line/types.d.ts +3 -1
- package/dist/types/modes/components/tool-execution.d.ts +2 -0
- package/dist/types/modes/components/transcript-container.d.ts +4 -3
- package/dist/types/modes/components/tree-selector.d.ts +6 -2
- package/dist/types/modes/components/usage-row.d.ts +1 -1
- package/dist/types/modes/interactive-mode.d.ts +2 -0
- package/dist/types/modes/print-mode.d.ts +4 -0
- package/dist/types/modes/rpc/rpc-client.d.ts +1 -1
- package/dist/types/modes/rpc/rpc-frame.d.ts +9 -0
- package/dist/types/modes/rpc/rpc-input.d.ts +5 -0
- package/dist/types/modes/rpc/rpc-mode.d.ts +1 -1
- package/dist/types/modes/setup-wizard/index.d.ts +1 -1
- package/dist/types/modes/setup-wizard/scenes/model.d.ts +3 -0
- package/dist/types/modes/types.d.ts +2 -0
- package/dist/types/sdk.d.ts +2 -0
- package/dist/types/session/agent-session.d.ts +42 -6
- package/dist/types/session/messages.d.ts +6 -0
- package/dist/types/session/session-paths.d.ts +21 -4
- package/dist/types/tools/browser/aria/aria-snapshot.d.ts +17 -7
- package/dist/types/tools/browser/cmux/socket-client.d.ts +2 -0
- package/dist/types/tools/browser/tab-protocol.d.ts +2 -0
- package/dist/types/tools/browser/tab-worker.d.ts +2 -0
- package/dist/types/tools/gh.d.ts +5 -3
- package/dist/types/tools/hub/index.d.ts +1 -1
- package/dist/types/tools/hub/jobs.d.ts +1 -0
- package/dist/types/tools/hub/types.d.ts +2 -0
- package/dist/types/tools/tool-timeouts.d.ts +1 -1
- package/dist/types/tools/xdev.d.ts +5 -3
- package/dist/types/utils/git.d.ts +33 -0
- package/dist/types/vibe/__tests__/token-rate.test.d.ts +1 -0
- package/dist/types/vibe/runtime.d.ts +23 -0
- package/dist/types/web/search/providers/codex.d.ts +1 -1
- package/package.json +12 -12
- package/src/advisor/__tests__/advisor.test.ts +150 -0
- package/src/advisor/advise-tool.ts +4 -0
- package/src/advisor/runtime.ts +38 -14
- package/src/async/job-manager.ts +3 -0
- package/src/cli/bench-cli.ts +8 -2
- package/src/cli/dry-balance-cli.ts +1 -0
- package/src/config/model-registry.ts +89 -8
- package/src/config/model-resolver.ts +78 -14
- package/src/config/models-config-schema.ts +1 -0
- package/src/config/settings.ts +3 -1
- package/src/dap/client.ts +168 -1
- package/src/dap/config.ts +51 -1
- package/src/dap/session.ts +575 -234
- package/src/dap/types.ts +6 -5
- package/src/discovery/agents.ts +2 -2
- package/src/exec/bash-executor.ts +68 -8
- package/src/extensibility/extensions/load-errors.ts +13 -0
- package/src/extensibility/extensions/runner.ts +6 -4
- package/src/extensibility/legacy-pi-coding-agent-shim.ts +26 -0
- package/src/extensibility/plugins/legacy-pi-compat.ts +41 -6
- package/src/launch/broker.ts +34 -31
- package/src/launch/client.ts +7 -1
- package/src/launch/spawn-options.test.ts +31 -0
- package/src/launch/spawn-options.ts +17 -0
- package/src/lsp/types.ts +5 -1
- package/src/main.ts +25 -4
- package/src/mcp/transports/stdio.test.ts +9 -1
- package/src/modes/components/ask-dialog.ts +137 -73
- package/src/modes/components/chat-transcript-builder.ts +10 -1
- package/src/modes/components/status-line/component.ts +57 -3
- package/src/modes/components/status-line/segments.ts +20 -3
- package/src/modes/components/status-line/types.ts +3 -1
- package/src/modes/components/tool-execution.ts +5 -0
- package/src/modes/components/transcript-container.ts +23 -122
- package/src/modes/components/tree-selector.ts +10 -4
- package/src/modes/components/usage-row.ts +17 -1
- package/src/modes/controllers/command-controller.ts +41 -1
- package/src/modes/controllers/event-controller.ts +7 -3
- package/src/modes/controllers/input-controller.ts +1 -1
- package/src/modes/controllers/selector-controller.ts +29 -8
- package/src/modes/interactive-mode.ts +102 -60
- package/src/modes/noninteractive-dispose.test.ts +14 -1
- package/src/modes/print-mode.ts +81 -9
- package/src/modes/rpc/rpc-client.ts +76 -35
- package/src/modes/rpc/rpc-frame.ts +156 -0
- package/src/modes/rpc/rpc-input.ts +38 -0
- package/src/modes/rpc/rpc-mode.ts +11 -4
- package/src/modes/setup-wizard/index.ts +2 -0
- package/src/modes/setup-wizard/scenes/model.ts +134 -0
- package/src/modes/setup-wizard/scenes/sign-in.ts +3 -1
- package/src/modes/types.ts +2 -0
- package/src/modes/utils/ui-helpers.ts +9 -3
- package/src/prompts/system/workflow-notice.md +89 -74
- package/src/prompts/tools/browser.md +3 -2
- package/src/prompts/tools/debug.md +2 -7
- package/src/prompts/tools/github.md +6 -1
- package/src/prompts/tools/hub.md +4 -2
- package/src/prompts/tools/task-async-contract.md +1 -0
- package/src/prompts/tools/task.md +9 -2
- package/src/sdk.ts +38 -6
- package/src/session/agent-session.ts +484 -188
- package/src/session/messages.test.ts +91 -0
- package/src/session/messages.ts +248 -110
- package/src/session/session-manager.ts +34 -3
- package/src/session/session-paths.ts +38 -9
- package/src/slash-commands/builtin-registry.ts +1 -0
- package/src/task/executor.ts +104 -33
- package/src/task/index.ts +46 -9
- package/src/task/worktree.ts +10 -0
- package/src/tools/browser/aria/aria-snapshot.ts +36 -8
- package/src/tools/browser/cmux/cmux-tab.ts +2 -1
- package/src/tools/browser/cmux/socket-client.ts +139 -3
- package/src/tools/browser/run-cancellation.ts +4 -0
- package/src/tools/browser/tab-protocol.ts +2 -0
- package/src/tools/browser/tab-supervisor.ts +21 -11
- package/src/tools/browser/tab-worker.ts +199 -33
- package/src/tools/debug.ts +3 -0
- package/src/tools/gh.ts +40 -2
- package/src/tools/hub/index.ts +4 -1
- package/src/tools/hub/jobs.ts +42 -1
- package/src/tools/hub/types.ts +2 -0
- package/src/tools/tool-timeouts.ts +1 -1
- package/src/tools/xdev.ts +11 -4
- package/src/tools/yield.ts +4 -1
- package/src/utils/git.ts +237 -0
- package/src/{modes/components/status-line → utils}/token-rate.ts +6 -0
- package/src/vibe/__tests__/token-rate.test.ts +96 -0
- package/src/vibe/runtime.ts +50 -0
- package/src/web/search/index.ts +9 -5
- package/src/web/search/providers/codex.ts +195 -99
- /package/dist/types/{modes/components/status-line → utils}/token-rate.d.ts +0 -0
package/src/dap/client.ts
CHANGED
|
@@ -55,6 +55,8 @@ export class DapClient {
|
|
|
55
55
|
readonly adapter: DapResolvedAdapter;
|
|
56
56
|
readonly cwd: string;
|
|
57
57
|
readonly proc: DapClientState["proc"];
|
|
58
|
+
/** TCP server port reused by child DAP sessions. */
|
|
59
|
+
readonly port?: number;
|
|
58
60
|
/** ReadableStream of DAP bytes — from proc.stdout (stdio) or a socket (socket mode). */
|
|
59
61
|
readonly #readable: ReadableStream<Uint8Array>;
|
|
60
62
|
/** Write sink — proc.stdin (stdio) or a socket (socket mode). */
|
|
@@ -78,7 +80,12 @@ export class DapClient {
|
|
|
78
80
|
adapter: DapResolvedAdapter,
|
|
79
81
|
cwd: string,
|
|
80
82
|
proc: DapClientState["proc"],
|
|
81
|
-
options?: {
|
|
83
|
+
options?: {
|
|
84
|
+
readable?: ReadableStream<Uint8Array>;
|
|
85
|
+
writeSink?: DapWriteSink;
|
|
86
|
+
socket?: { end(): void };
|
|
87
|
+
port?: number;
|
|
88
|
+
},
|
|
82
89
|
) {
|
|
83
90
|
this.adapter = adapter;
|
|
84
91
|
this.cwd = cwd;
|
|
@@ -86,6 +93,7 @@ export class DapClient {
|
|
|
86
93
|
this.#readable = options?.readable ?? (proc.stdout as ReadableStream<Uint8Array>);
|
|
87
94
|
this.#writeSink = options?.writeSink ?? proc.stdin;
|
|
88
95
|
this.#socket = options?.socket;
|
|
96
|
+
this.port = options?.port;
|
|
89
97
|
this.proc.exited.then(
|
|
90
98
|
() => this.#rejectPendingWritesForExit(),
|
|
91
99
|
() => this.#rejectPendingWritesForExit(),
|
|
@@ -96,6 +104,9 @@ export class DapClient {
|
|
|
96
104
|
if (adapter.connectMode === "socket") {
|
|
97
105
|
return DapClient.#spawnSocket({ adapter, cwd, socketReadyTimeoutMs });
|
|
98
106
|
}
|
|
107
|
+
if (adapter.connectMode === "tcp") {
|
|
108
|
+
return DapClient.#spawnTcp({ adapter, cwd, socketReadyTimeoutMs });
|
|
109
|
+
}
|
|
99
110
|
// Merge non-interactive env and start in a new session (detached → setsid)
|
|
100
111
|
// so the adapter process tree has no controlling terminal. Without this,
|
|
101
112
|
// debuggee children can reach /dev/tty and trigger SIGTTIN, suspending
|
|
@@ -118,6 +129,85 @@ export class DapClient {
|
|
|
118
129
|
return client;
|
|
119
130
|
}
|
|
120
131
|
|
|
132
|
+
/** Connect to another session on an existing TCP DAP server. */
|
|
133
|
+
static async connect({
|
|
134
|
+
adapter,
|
|
135
|
+
cwd,
|
|
136
|
+
host,
|
|
137
|
+
port,
|
|
138
|
+
}: {
|
|
139
|
+
adapter: DapResolvedAdapter;
|
|
140
|
+
cwd: string;
|
|
141
|
+
host: string;
|
|
142
|
+
port: number;
|
|
143
|
+
}): Promise<DapClient> {
|
|
144
|
+
const exited = Promise.withResolvers<void>();
|
|
145
|
+
const { readable, writeSink, socket } = await connectTcpSocket(host, port, () => exited.resolve());
|
|
146
|
+
const proc = {
|
|
147
|
+
exited: exited.promise,
|
|
148
|
+
exitCode: null,
|
|
149
|
+
stdin: { write: () => 0, flush: () => undefined },
|
|
150
|
+
stdout: new ReadableStream<Uint8Array>(),
|
|
151
|
+
stderr: new ReadableStream<Uint8Array>(),
|
|
152
|
+
peekStderr: () => "",
|
|
153
|
+
kill: () => {
|
|
154
|
+
exited.resolve();
|
|
155
|
+
return true;
|
|
156
|
+
},
|
|
157
|
+
} as unknown as DapClientState["proc"];
|
|
158
|
+
const client = new DapClient(adapter, cwd, proc, { readable, writeSink, socket, port });
|
|
159
|
+
exited.promise.then(() => client.#handleProcessExit());
|
|
160
|
+
void client.#startMessageReader();
|
|
161
|
+
return client;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** Spawn an adapter that listens on a caller-selected TCP port. */
|
|
165
|
+
static async #spawnTcp({ adapter, cwd, socketReadyTimeoutMs }: DapSpawnOptions): Promise<DapClient> {
|
|
166
|
+
const host = "127.0.0.1";
|
|
167
|
+
const reservation = Bun.listen({
|
|
168
|
+
hostname: host,
|
|
169
|
+
port: 0,
|
|
170
|
+
socket: {
|
|
171
|
+
open() {},
|
|
172
|
+
data() {},
|
|
173
|
+
close() {},
|
|
174
|
+
error() {},
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
const port = reservation.port;
|
|
178
|
+
reservation.stop(true);
|
|
179
|
+
const args = adapter.args.map(arg => arg.replaceAll("$" + "{port}", String(port)));
|
|
180
|
+
const proc = ptree.spawn([adapter.resolvedCommand, ...args], {
|
|
181
|
+
cwd,
|
|
182
|
+
stdin: "pipe",
|
|
183
|
+
env: {
|
|
184
|
+
...Bun.env,
|
|
185
|
+
...NON_INTERACTIVE_ENV,
|
|
186
|
+
},
|
|
187
|
+
detached: true,
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
const { readable, writeSink, socket } = await waitForTcpTransport(
|
|
192
|
+
host,
|
|
193
|
+
port,
|
|
194
|
+
socketReadyTimeoutMs ?? SOCKET_READY_TIMEOUT_MS,
|
|
195
|
+
proc,
|
|
196
|
+
);
|
|
197
|
+
const client = new DapClient(adapter, cwd, proc, { readable, writeSink, socket, port });
|
|
198
|
+
proc.exited.then(() => client.#handleProcessExit());
|
|
199
|
+
void client.#startMessageReader();
|
|
200
|
+
return client;
|
|
201
|
+
} catch (error) {
|
|
202
|
+
try {
|
|
203
|
+
proc.kill();
|
|
204
|
+
} catch {
|
|
205
|
+
/* proc may already be dead */
|
|
206
|
+
}
|
|
207
|
+
throw error;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
121
211
|
/**
|
|
122
212
|
* Spawn a socket-mode adapter (e.g. dlv).
|
|
123
213
|
* Linux: connect to a unix domain socket via --listen=unix:<path>
|
|
@@ -659,6 +749,83 @@ async function waitForCondition(
|
|
|
659
749
|
throw new Error(`Socket not ready after ${timeoutMs}ms`);
|
|
660
750
|
}
|
|
661
751
|
|
|
752
|
+
/** Connect once to a TCP DAP server. */
|
|
753
|
+
async function connectTcpSocket(host: string, port: number, onClose?: () => void): Promise<SocketTransport> {
|
|
754
|
+
const { promise, resolve, reject } = Promise.withResolvers<SocketTransport>();
|
|
755
|
+
let streamController: ReadableStreamDefaultController<Uint8Array>;
|
|
756
|
+
let opened = false;
|
|
757
|
+
const readable = new ReadableStream<Uint8Array>({
|
|
758
|
+
start(controller) {
|
|
759
|
+
streamController = controller;
|
|
760
|
+
},
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
void Bun.connect({
|
|
764
|
+
hostname: host,
|
|
765
|
+
port,
|
|
766
|
+
socket: {
|
|
767
|
+
open(socket) {
|
|
768
|
+
opened = true;
|
|
769
|
+
resolve({
|
|
770
|
+
readable,
|
|
771
|
+
writeSink: socketToSink(socket),
|
|
772
|
+
socket,
|
|
773
|
+
});
|
|
774
|
+
},
|
|
775
|
+
data(_socket, data) {
|
|
776
|
+
streamController.enqueue(new Uint8Array(data));
|
|
777
|
+
},
|
|
778
|
+
close() {
|
|
779
|
+
onClose?.();
|
|
780
|
+
if (!opened) {
|
|
781
|
+
reject(new Error(`Connection to TCP port ${host}:${port} closed before opening`));
|
|
782
|
+
}
|
|
783
|
+
try {
|
|
784
|
+
streamController.close();
|
|
785
|
+
} catch {
|
|
786
|
+
/* already closed */
|
|
787
|
+
}
|
|
788
|
+
},
|
|
789
|
+
error(_socket, error) {
|
|
790
|
+
onClose?.();
|
|
791
|
+
if (!opened) {
|
|
792
|
+
reject(error);
|
|
793
|
+
}
|
|
794
|
+
try {
|
|
795
|
+
streamController.error(error);
|
|
796
|
+
} catch {
|
|
797
|
+
/* already closed */
|
|
798
|
+
}
|
|
799
|
+
},
|
|
800
|
+
},
|
|
801
|
+
}).catch(error => {
|
|
802
|
+
onClose?.();
|
|
803
|
+
reject(error);
|
|
804
|
+
});
|
|
805
|
+
return promise;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
/** Wait for a TCP DAP server and retain the first successful connection. */
|
|
809
|
+
async function waitForTcpTransport(
|
|
810
|
+
host: string,
|
|
811
|
+
port: number,
|
|
812
|
+
timeoutMs: number,
|
|
813
|
+
proc: { exitCode: number | null },
|
|
814
|
+
): Promise<SocketTransport> {
|
|
815
|
+
const deadline = Date.now() + timeoutMs;
|
|
816
|
+
while (Date.now() < deadline) {
|
|
817
|
+
if (proc.exitCode !== null) {
|
|
818
|
+
throw new Error(`Adapter process exited before TCP port ${host}:${port} was ready`);
|
|
819
|
+
}
|
|
820
|
+
try {
|
|
821
|
+
return await connectTcpSocket(host, port);
|
|
822
|
+
} catch {
|
|
823
|
+
await Bun.sleep(50);
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
throw new Error(`TCP port ${host}:${port} was not ready after ${timeoutMs}ms`);
|
|
827
|
+
}
|
|
828
|
+
|
|
662
829
|
interface SocketTransport {
|
|
663
830
|
readable: ReadableStream<Uint8Array>;
|
|
664
831
|
writeSink: DapWriteSink;
|
package/src/dap/config.ts
CHANGED
|
@@ -10,6 +10,8 @@ import DEFAULTS from "./defaults.json" with { type: "json" };
|
|
|
10
10
|
import type { DapAdapterConfig, DapResolvedAdapter } from "./types";
|
|
11
11
|
|
|
12
12
|
const EXTENSIONLESS_DEBUGGER_ORDER: readonly string[] = ["gdb", "lldb-dap"];
|
|
13
|
+
const JS_DEBUG_SERVER_ENV = "JS_DEBUG_DAP_SERVER";
|
|
14
|
+
const DAP_PORT_ARGUMENT = "$" + "{port}";
|
|
13
15
|
|
|
14
16
|
interface NormalizedConfig {
|
|
15
17
|
adapters: Record<string, unknown>;
|
|
@@ -45,7 +47,7 @@ function normalizeObject(value: unknown): Record<string, unknown> {
|
|
|
45
47
|
function normalizeAdapterConfig(config: unknown): DapAdapterConfig | null {
|
|
46
48
|
if (!isRecord(config)) return null;
|
|
47
49
|
if (typeof config.command !== "string" || config.command.length === 0) return null;
|
|
48
|
-
const connectMode = config.connectMode === "socket"
|
|
50
|
+
const connectMode = config.connectMode === "socket" || config.connectMode === "tcp" ? config.connectMode : undefined;
|
|
49
51
|
return {
|
|
50
52
|
command: config.command,
|
|
51
53
|
args: normalizeStringArray(config.args),
|
|
@@ -184,6 +186,52 @@ function normalizeCommandForCwd(command: string, cwd: string): string {
|
|
|
184
186
|
return command;
|
|
185
187
|
}
|
|
186
188
|
|
|
189
|
+
function resolveJsDebugServerPath(cwd: string): string | null {
|
|
190
|
+
const configured = process.env[JS_DEBUG_SERVER_ENV];
|
|
191
|
+
const dataHome = process.env.XDG_DATA_HOME ?? path.join(os.homedir(), ".local", "share");
|
|
192
|
+
const candidates = [
|
|
193
|
+
...(configured ? [path.resolve(cwd, configured)] : []),
|
|
194
|
+
path.join(dataHome, "nvim", "mason", "packages", "js-debug-adapter", "js-debug", "src", "dapDebugServer.js"),
|
|
195
|
+
path.join(os.homedir(), ".local", "opt", "js-debug", "src", "dapDebugServer.js"),
|
|
196
|
+
];
|
|
197
|
+
for (const candidate of candidates) {
|
|
198
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
199
|
+
}
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function resolveDefaultJsDebugAdapter(
|
|
204
|
+
adapterName: string,
|
|
205
|
+
config: DapAdapterConfig,
|
|
206
|
+
cwd: string,
|
|
207
|
+
localRoots?: readonly string[],
|
|
208
|
+
): DapResolvedAdapter | null | undefined {
|
|
209
|
+
if (adapterName !== "js-debug-adapter" || config.command !== "js-debug-adapter") {
|
|
210
|
+
return undefined;
|
|
211
|
+
}
|
|
212
|
+
const serverPath = resolveJsDebugServerPath(cwd);
|
|
213
|
+
if (!serverPath) return null;
|
|
214
|
+
const nodeCommand = resolveCommand("node", cwd, {
|
|
215
|
+
cache: WhichCachePolicy.Fresh,
|
|
216
|
+
PATH: process.env.PATH,
|
|
217
|
+
localRoots,
|
|
218
|
+
});
|
|
219
|
+
const resolvedCommand = nodeCommand ?? process.execPath;
|
|
220
|
+
return {
|
|
221
|
+
name: adapterName,
|
|
222
|
+
command: nodeCommand ? "node" : "bun",
|
|
223
|
+
args: [serverPath, DAP_PORT_ARGUMENT, "127.0.0.1"],
|
|
224
|
+
resolvedCommand,
|
|
225
|
+
languages: config.languages ?? [],
|
|
226
|
+
fileTypes: config.fileTypes ?? [],
|
|
227
|
+
rootMarkers: config.rootMarkers ?? [],
|
|
228
|
+
launchDefaults: config.launchDefaults ?? {},
|
|
229
|
+
attachDefaults: config.attachDefaults ?? {},
|
|
230
|
+
connectMode: "tcp",
|
|
231
|
+
acceptsDirectoryProgram: config.acceptsDirectoryProgram === true,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
187
235
|
function resolveAdapterFromConfig(
|
|
188
236
|
adapterName: string,
|
|
189
237
|
configs: Record<string, DapAdapterConfig>,
|
|
@@ -192,6 +240,8 @@ function resolveAdapterFromConfig(
|
|
|
192
240
|
): DapResolvedAdapter | null {
|
|
193
241
|
const config = configs[adapterName];
|
|
194
242
|
if (!config) return null;
|
|
243
|
+
const jsDebugAdapter = resolveDefaultJsDebugAdapter(adapterName, config, cwd, localRoots);
|
|
244
|
+
if (jsDebugAdapter !== undefined) return jsDebugAdapter;
|
|
195
245
|
const normalizedCommand = normalizeCommandForCwd(config.command, cwd);
|
|
196
246
|
const commandIsBare =
|
|
197
247
|
!path.isAbsolute(config.command) && !config.command.includes("/") && !config.command.includes("\\");
|