@prestyj/cli 4.10.3 → 4.12.0
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/README.md +4 -4
- package/dist/app-sidecar.d.ts +2 -0
- package/dist/app-sidecar.d.ts.map +1 -0
- package/dist/app-sidecar.js +1720 -0
- package/dist/app-sidecar.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +10 -25
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +5 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -0
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +162 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +544 -23
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/api-benchmark.d.ts +64 -0
- package/dist/core/api-benchmark.d.ts.map +1 -0
- package/dist/core/api-benchmark.js +381 -0
- package/dist/core/api-benchmark.js.map +1 -0
- package/dist/core/auth-providers.d.ts +18 -0
- package/dist/core/auth-providers.d.ts.map +1 -0
- package/dist/core/auth-providers.js +71 -0
- package/dist/core/auth-providers.js.map +1 -0
- package/dist/core/event-bus.d.ts +6 -0
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js +1 -0
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/mcp/client.d.ts +21 -0
- package/dist/core/mcp/client.d.ts.map +1 -1
- package/dist/core/mcp/client.js +167 -5
- package/dist/core/mcp/client.js.map +1 -1
- package/dist/core/mcp/index.d.ts +3 -1
- package/dist/core/mcp/index.d.ts.map +1 -1
- package/dist/core/mcp/index.js +2 -0
- package/dist/core/mcp/index.js.map +1 -1
- package/dist/core/mcp/oauth-provider.d.ts +51 -0
- package/dist/core/mcp/oauth-provider.d.ts.map +1 -0
- package/dist/core/mcp/oauth-provider.js +95 -0
- package/dist/core/mcp/oauth-provider.js.map +1 -0
- package/dist/core/mcp/oauth-store.d.ts +39 -0
- package/dist/core/mcp/oauth-store.d.ts.map +1 -0
- package/dist/core/mcp/oauth-store.js +63 -0
- package/dist/core/mcp/oauth-store.js.map +1 -0
- package/dist/core/mcp/oauth-store.test.d.ts +2 -0
- package/dist/core/mcp/oauth-store.test.d.ts.map +1 -0
- package/dist/core/mcp/oauth-store.test.js +94 -0
- package/dist/core/mcp/oauth-store.test.js.map +1 -0
- package/dist/core/process-manager.d.ts.map +1 -1
- package/dist/core/process-manager.js +5 -1
- package/dist/core/process-manager.js.map +1 -1
- package/dist/core/project-discovery.d.ts +41 -0
- package/dist/core/project-discovery.d.ts.map +1 -0
- package/dist/core/project-discovery.js +441 -0
- package/dist/core/project-discovery.js.map +1 -0
- package/dist/core/prompt-commands.d.ts.map +1 -1
- package/dist/core/prompt-commands.js +203 -0
- package/dist/core/prompt-commands.js.map +1 -1
- package/dist/core/prompt-commands.test.js +39 -0
- package/dist/core/prompt-commands.test.js.map +1 -1
- package/dist/core/radio.d.ts +44 -0
- package/dist/core/radio.d.ts.map +1 -0
- package/dist/core/radio.js +250 -0
- package/dist/core/radio.js.map +1 -0
- package/dist/core/resolve-start.d.ts +29 -0
- package/dist/core/resolve-start.d.ts.map +1 -0
- package/dist/core/resolve-start.js +35 -0
- package/dist/core/resolve-start.js.map +1 -0
- package/dist/core/resolve-start.test.d.ts +2 -0
- package/dist/core/resolve-start.test.d.ts.map +1 -0
- package/dist/core/resolve-start.test.js +66 -0
- package/dist/core/resolve-start.test.js.map +1 -0
- package/dist/core/settings-manager.d.ts +5 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +5 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/shell-path.d.ts +12 -0
- package/dist/core/shell-path.d.ts.map +1 -0
- package/dist/core/shell-path.js +166 -0
- package/dist/core/shell-path.js.map +1 -0
- package/dist/core/shell.d.ts +51 -0
- package/dist/core/shell.d.ts.map +1 -0
- package/dist/core/shell.js +82 -0
- package/dist/core/shell.js.map +1 -0
- package/dist/core/shell.test.d.ts +2 -0
- package/dist/core/shell.test.d.ts.map +1 -0
- package/dist/core/shell.test.js +87 -0
- package/dist/core/shell.test.js.map +1 -0
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +10 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/speed-benchmark.d.ts +133 -0
- package/dist/core/speed-benchmark.d.ts.map +1 -0
- package/dist/core/speed-benchmark.js +410 -0
- package/dist/core/speed-benchmark.js.map +1 -0
- package/dist/core/speed-benchmark.test.d.ts +2 -0
- package/dist/core/speed-benchmark.test.d.ts.map +1 -0
- package/dist/core/speed-benchmark.test.js +97 -0
- package/dist/core/speed-benchmark.test.js.map +1 -0
- package/dist/core/telegram-config.d.ts +21 -0
- package/dist/core/telegram-config.d.ts.map +1 -0
- package/dist/core/telegram-config.js +52 -0
- package/dist/core/telegram-config.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/interactive.d.ts.map +1 -1
- package/dist/interactive.js +4 -3
- package/dist/interactive.js.map +1 -1
- package/dist/modes/serve-mode.d.ts +24 -0
- package/dist/modes/serve-mode.d.ts.map +1 -1
- package/dist/modes/serve-mode.js +54 -19
- package/dist/modes/serve-mode.js.map +1 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +17 -1
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/generate-image.d.ts +39 -0
- package/dist/tools/generate-image.d.ts.map +1 -0
- package/dist/tools/generate-image.js +301 -0
- package/dist/tools/generate-image.js.map +1 -0
- package/dist/tools/generate-image.test.d.ts +2 -0
- package/dist/tools/generate-image.test.d.ts.map +1 -0
- package/dist/tools/generate-image.test.js +223 -0
- package/dist/tools/generate-image.test.js.map +1 -0
- package/dist/tools/goal-mode.test.js +1 -1
- package/dist/tools/goal-mode.test.js.map +1 -1
- package/dist/tools/goals.d.ts +7 -7
- package/dist/tools/index.d.ts +15 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +17 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/plan-mode.test.js +5 -5
- package/dist/tools/plan-mode.test.js.map +1 -1
- package/dist/tools/prompt-hints.d.ts.map +1 -1
- package/dist/tools/prompt-hints.js +2 -0
- package/dist/tools/prompt-hints.js.map +1 -1
- package/dist/tools/safe-env.d.ts.map +1 -1
- package/dist/tools/safe-env.js +27 -0
- package/dist/tools/safe-env.js.map +1 -1
- package/dist/tools/subagent.d.ts +2 -4
- package/dist/tools/subagent.d.ts.map +1 -1
- package/dist/tools/subagent.js +24 -23
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/tasks.d.ts +1 -7
- package/dist/tools/tasks.d.ts.map +1 -1
- package/dist/tools/tasks.js +4 -31
- package/dist/tools/tasks.js.map +1 -1
- package/dist/ui/App.d.ts +1 -1
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/hooks/usePixelFixFlow.d.ts +1 -1
- package/dist/ui/hooks/usePixelFixFlow.d.ts.map +1 -1
- package/dist/ui/hooks/usePixelFixFlow.js +1 -1
- package/dist/ui/hooks/usePixelFixFlow.js.map +1 -1
- package/dist/ui/hooks/useTranscriptHistory.d.ts +2 -0
- package/dist/ui/hooks/useTranscriptHistory.d.ts.map +1 -1
- package/dist/ui/hooks/useTranscriptHistory.js +3 -2
- package/dist/ui/hooks/useTranscriptHistory.js.map +1 -1
- package/dist/ui/long-prompt-regression-harness.test.js +8 -8
- package/dist/ui/render.d.ts +1 -1
- package/dist/ui/render.d.ts.map +1 -1
- package/dist/ui/render.js +60 -8
- package/dist/ui/render.js.map +1 -1
- package/dist/ui/startup-banner-order.test.js +1 -1
- package/dist/ui/startup-banner-order.test.js.map +1 -1
- package/dist/ui/terminal-history-repaint.test.d.ts +2 -0
- package/dist/ui/terminal-history-repaint.test.d.ts.map +1 -0
- package/dist/ui/terminal-history-repaint.test.js +73 -0
- package/dist/ui/terminal-history-repaint.test.js.map +1 -0
- package/dist/ui/terminal-history.d.ts +1 -0
- package/dist/ui/terminal-history.d.ts.map +1 -1
- package/dist/ui/terminal-history.js +31 -2
- package/dist/ui/terminal-history.js.map +1 -1
- package/dist/utils/git.d.ts +6 -0
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +12 -0
- package/dist/utils/git.js.map +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Provider } from "@prestyj/ai";
|
|
2
|
+
/** A resolved startup provider + model for an AgentSession. */
|
|
3
|
+
export interface ResolvedStart {
|
|
4
|
+
provider: Provider;
|
|
5
|
+
model: string;
|
|
6
|
+
}
|
|
7
|
+
/** The boot-time provider resolution, plus whether the user is logged in. */
|
|
8
|
+
export interface ResolvedStartResult extends ResolvedStart {
|
|
9
|
+
/** False when no provider has usable credentials — the sidecar boots anyway
|
|
10
|
+
* (logged-out, login endpoints reachable) instead of crashing. */
|
|
11
|
+
loggedIn: boolean;
|
|
12
|
+
}
|
|
13
|
+
/** Minimal auth surface needed to decide the startup provider (testable). */
|
|
14
|
+
export interface ProviderAuthLookup {
|
|
15
|
+
hasProviderAuth(provider: string): Promise<boolean>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Pick a provider/model the user is logged into, preferring the saved defaults.
|
|
19
|
+
* Mirrors the CLI's resolveActiveProvider, but NEVER throws when logged out:
|
|
20
|
+
* instead it falls back to `preferred` + its default model and reports
|
|
21
|
+
* `loggedIn: false`. This is what lets the ezcoder-app sidecar boot (and serve the
|
|
22
|
+
* login endpoints) for a fresh user with no credentials — throwing here used to
|
|
23
|
+
* kill the sidecar before it listened, making login impossible.
|
|
24
|
+
*
|
|
25
|
+
* Credentials resolve lazily at prompt time, so a logged-out boot is safe: a
|
|
26
|
+
* prompt sent before login fails cleanly through the run's error handling.
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolveStartOrFallback(auth: ProviderAuthLookup, allProviders: readonly Provider[], preferred: Provider, savedModel: string | undefined): Promise<ResolvedStartResult>;
|
|
29
|
+
//# sourceMappingURL=resolve-start.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-start.d.ts","sourceRoot":"","sources":["../../src/core/resolve-start.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG5C,+DAA+D;AAC/D,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,6EAA6E;AAC7E,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD;uEACmE;IACnE,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,6EAA6E;AAC7E,MAAM,WAAW,kBAAkB;IACjC,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACrD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,kBAAkB,EACxB,YAAY,EAAE,SAAS,QAAQ,EAAE,EACjC,SAAS,EAAE,QAAQ,EACnB,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,OAAO,CAAC,mBAAmB,CAAC,CAuB9B"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { getDefaultModel, getModel } from "./model-registry.js";
|
|
2
|
+
/**
|
|
3
|
+
* Pick a provider/model the user is logged into, preferring the saved defaults.
|
|
4
|
+
* Mirrors the CLI's resolveActiveProvider, but NEVER throws when logged out:
|
|
5
|
+
* instead it falls back to `preferred` + its default model and reports
|
|
6
|
+
* `loggedIn: false`. This is what lets the ezcoder-app sidecar boot (and serve the
|
|
7
|
+
* login endpoints) for a fresh user with no credentials — throwing here used to
|
|
8
|
+
* kill the sidecar before it listened, making login impossible.
|
|
9
|
+
*
|
|
10
|
+
* Credentials resolve lazily at prompt time, so a logged-out boot is safe: a
|
|
11
|
+
* prompt sent before login fails cleanly through the run's error handling.
|
|
12
|
+
*/
|
|
13
|
+
export async function resolveStartOrFallback(auth, allProviders, preferred, savedModel) {
|
|
14
|
+
const loggedIn = [];
|
|
15
|
+
for (const p of allProviders) {
|
|
16
|
+
if (await auth.hasProviderAuth(p))
|
|
17
|
+
loggedIn.push(p);
|
|
18
|
+
}
|
|
19
|
+
if (loggedIn.length === 0) {
|
|
20
|
+
// Logged-out fallback: boot with the preferred provider's default model so
|
|
21
|
+
// the sidecar still starts and the login flow is reachable.
|
|
22
|
+
return { provider: preferred, model: getDefaultModel(preferred).id, loggedIn: false };
|
|
23
|
+
}
|
|
24
|
+
if (loggedIn.includes(preferred)) {
|
|
25
|
+
const saved = savedModel ? getModel(savedModel) : undefined;
|
|
26
|
+
return {
|
|
27
|
+
provider: preferred,
|
|
28
|
+
model: saved?.provider === preferred ? saved.id : getDefaultModel(preferred).id,
|
|
29
|
+
loggedIn: true,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
const provider = loggedIn[0];
|
|
33
|
+
return { provider, model: getDefaultModel(provider).id, loggedIn: true };
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=resolve-start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-start.js","sourceRoot":"","sources":["../../src/core/resolve-start.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAoBhE;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,IAAwB,EACxB,YAAiC,EACjC,SAAmB,EACnB,UAA8B;IAE9B,MAAM,QAAQ,GAAe,EAAE,CAAC;IAChC,KAAK,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;QAC7B,IAAI,MAAM,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,2EAA2E;QAC3E,4DAA4D;QAC5D,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IACxF,CAAC;IAED,IAAI,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC5D,OAAO;YACL,QAAQ,EAAE,SAAS;YACnB,KAAK,EAAE,KAAK,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,EAAE;YAC/E,QAAQ,EAAE,IAAI;SACf,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAE,CAAC;IAC9B,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAC3E,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-start.test.d.ts","sourceRoot":"","sources":["../../src/core/resolve-start.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { getDefaultModel } from "./model-registry.js";
|
|
3
|
+
import { resolveStartOrFallback } from "./resolve-start.js";
|
|
4
|
+
const ALL = [
|
|
5
|
+
"anthropic",
|
|
6
|
+
"xiaomi",
|
|
7
|
+
"openai",
|
|
8
|
+
"gemini",
|
|
9
|
+
"glm",
|
|
10
|
+
"moonshot",
|
|
11
|
+
"minimax",
|
|
12
|
+
"deepseek",
|
|
13
|
+
"openrouter",
|
|
14
|
+
];
|
|
15
|
+
/** Fake auth lookup: only the providers in `set` are "logged in". */
|
|
16
|
+
function auth(...connected) {
|
|
17
|
+
const set = new Set(connected);
|
|
18
|
+
return { hasProviderAuth: async (p) => set.has(p) };
|
|
19
|
+
}
|
|
20
|
+
describe("resolveStartOrFallback", () => {
|
|
21
|
+
it("falls back to preferred + default model when no provider is logged in", async () => {
|
|
22
|
+
const res = await resolveStartOrFallback(auth(), ALL, "anthropic", undefined);
|
|
23
|
+
expect(res.loggedIn).toBe(false);
|
|
24
|
+
expect(res.provider).toBe("anthropic");
|
|
25
|
+
expect(res.model).toBe(getDefaultModel("anthropic").id);
|
|
26
|
+
});
|
|
27
|
+
it("honors a non-anthropic preferred provider in the logged-out fallback", async () => {
|
|
28
|
+
const res = await resolveStartOrFallback(auth(), ALL, "openai", undefined);
|
|
29
|
+
expect(res.loggedIn).toBe(false);
|
|
30
|
+
expect(res.provider).toBe("openai");
|
|
31
|
+
expect(res.model).toBe(getDefaultModel("openai").id);
|
|
32
|
+
});
|
|
33
|
+
it("uses the preferred provider's default model when logged in with no saved model", async () => {
|
|
34
|
+
const res = await resolveStartOrFallback(auth("anthropic"), ALL, "anthropic", undefined);
|
|
35
|
+
expect(res.loggedIn).toBe(true);
|
|
36
|
+
expect(res.provider).toBe("anthropic");
|
|
37
|
+
expect(res.model).toBe(getDefaultModel("anthropic").id);
|
|
38
|
+
});
|
|
39
|
+
it("keeps a saved model that belongs to the preferred provider", async () => {
|
|
40
|
+
const saved = getDefaultModel("anthropic").id;
|
|
41
|
+
const res = await resolveStartOrFallback(auth("anthropic"), ALL, "anthropic", saved);
|
|
42
|
+
expect(res.loggedIn).toBe(true);
|
|
43
|
+
expect(res.provider).toBe("anthropic");
|
|
44
|
+
expect(res.model).toBe(saved);
|
|
45
|
+
});
|
|
46
|
+
it("ignores a saved model that belongs to a different provider", async () => {
|
|
47
|
+
// Saved model is an OpenAI model but preferred is anthropic → default anthropic.
|
|
48
|
+
const otherProviderModel = getDefaultModel("openai").id;
|
|
49
|
+
const res = await resolveStartOrFallback(auth("anthropic"), ALL, "anthropic", otherProviderModel);
|
|
50
|
+
expect(res.provider).toBe("anthropic");
|
|
51
|
+
expect(res.model).toBe(getDefaultModel("anthropic").id);
|
|
52
|
+
});
|
|
53
|
+
it("falls back to the first logged-in provider when preferred is not connected", async () => {
|
|
54
|
+
// Preferred anthropic is logged out; only openai is connected.
|
|
55
|
+
const res = await resolveStartOrFallback(auth("openai"), ALL, "anthropic", undefined);
|
|
56
|
+
expect(res.loggedIn).toBe(true);
|
|
57
|
+
expect(res.provider).toBe("openai");
|
|
58
|
+
expect(res.model).toBe(getDefaultModel("openai").id);
|
|
59
|
+
});
|
|
60
|
+
it("picks the first connected provider in registry order", async () => {
|
|
61
|
+
// Both gemini and glm connected; ALL lists gemini before glm.
|
|
62
|
+
const res = await resolveStartOrFallback(auth("glm", "gemini"), ALL, "anthropic", undefined);
|
|
63
|
+
expect(res.provider).toBe("gemini");
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
//# sourceMappingURL=resolve-start.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-start.test.js","sourceRoot":"","sources":["../../src/core/resolve-start.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,8 +24,8 @@ declare const SettingsSchema: z.ZodObject<{
|
|
|
24
24
|
max: "max";
|
|
25
25
|
}>>;
|
|
26
26
|
theme: z.ZodDefault<z.ZodEnum<{
|
|
27
|
-
light: "light";
|
|
28
27
|
dark: "dark";
|
|
28
|
+
light: "light";
|
|
29
29
|
"dark-ansi": "dark-ansi";
|
|
30
30
|
"light-ansi": "light-ansi";
|
|
31
31
|
"dark-daltonized": "dark-daltonized";
|
|
@@ -38,6 +38,10 @@ declare const SettingsSchema: z.ZodObject<{
|
|
|
38
38
|
lspDiagnostics: z.ZodDefault<z.ZodBoolean>;
|
|
39
39
|
enabledTools: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
40
40
|
sessionRetentionDays: z.ZodDefault<z.ZodNumber>;
|
|
41
|
+
speedProfile: z.ZodDefault<z.ZodEnum<{
|
|
42
|
+
baseline: "baseline";
|
|
43
|
+
optimized: "optimized";
|
|
44
|
+
}>>;
|
|
41
45
|
}, z.core.$strip>;
|
|
42
46
|
export type Settings = z.infer<typeof SettingsSchema>;
|
|
43
47
|
export declare const DEFAULT_SETTINGS: Settings;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-manager.d.ts","sourceRoot":"","sources":["../../src/core/settings-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,QAAA,MAAM,cAAc
|
|
1
|
+
{"version":3,"file":"settings-manager.d.ts","sourceRoot":"","sources":["../../src/core/settings-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,QAAA,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA2ClB,CAAC;AAEH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD,eAAO,MAAM,gBAAgB,EAAE,QAa9B,CAAC;AAIF,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAS;gBAEX,QAAQ,CAAC,EAAE,MAAM;IAIvB,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC;IAazB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B,GAAG,CAAC,CAAC,SAAS,MAAM,QAAQ,EAAE,GAAG,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;IAI5C,GAAG,CAAC,CAAC,SAAS,MAAM,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAK9E,MAAM,IAAI,QAAQ;CAGnB"}
|
|
@@ -41,6 +41,10 @@ const SettingsSchema = z.object({
|
|
|
41
41
|
enabledTools: z.array(z.string()).optional(),
|
|
42
42
|
/** Delete session transcripts older than this many days at startup. 0 disables pruning. */
|
|
43
43
|
sessionRetentionDays: z.number().int().min(0).default(30),
|
|
44
|
+
/** Speed optimization profile.
|
|
45
|
+
* - "baseline": 5-min cache TTL, no pre-warm
|
|
46
|
+
* - "optimized": 1-h cache TTL, cache pre-warming on first prompt (default) */
|
|
47
|
+
speedProfile: z.enum(["baseline", "optimized"]).default("optimized"),
|
|
44
48
|
});
|
|
45
49
|
export const DEFAULT_SETTINGS = {
|
|
46
50
|
autoCompact: true,
|
|
@@ -54,6 +58,7 @@ export const DEFAULT_SETTINGS = {
|
|
|
54
58
|
autoApprovePlans: true,
|
|
55
59
|
lspDiagnostics: true,
|
|
56
60
|
sessionRetentionDays: 30,
|
|
61
|
+
speedProfile: "optimized",
|
|
57
62
|
};
|
|
58
63
|
// ── Settings Manager ───────────────────────────────────────
|
|
59
64
|
export class SettingsManager {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-manager.js","sourceRoot":"","sources":["../../src/core/settings-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,8DAA8D;AAE9D,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACtC,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;IAC3D,eAAe,EAAE,CAAC;SACf,IAAI,CAAC;QACJ,WAAW;QACX,QAAQ;QACR,QAAQ;QACR,KAAK;QACL,UAAU;QACV,SAAS;QACT,QAAQ;QACR,UAAU;QACV,YAAY;KACb,CAAC;SACD,OAAO,CAAC,WAAW,CAAC;IACvB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;IACnD,eAAe,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IAC3C,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC3E,KAAK,EAAE,CAAC;SACL,IAAI,CAAC;QACJ,MAAM;QACN,MAAM;QACN,OAAO;QACP,WAAW;QACX,YAAY;QACZ,iBAAiB;QACjB,kBAAkB;KACnB,CAAC;SACD,OAAO,CAAC,MAAM,CAAC;IAClB,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACzC,kBAAkB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAC7C,gBAAgB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3C,yDAAyD;IACzD,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACzC,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC5C,2FAA2F;IAC3F,oBAAoB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"settings-manager.js","sourceRoot":"","sources":["../../src/core/settings-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute the enriched PATH (login shell ∪ current ∪ existing well-known dirs).
|
|
3
|
+
* Cached after first call. Order is preserved and duplicates removed.
|
|
4
|
+
*/
|
|
5
|
+
export declare function resolveEnrichedPath(currentPath?: string): Promise<string>;
|
|
6
|
+
/**
|
|
7
|
+
* Enrich `process.env.PATH` in place so every later spawn/execFile (the bash
|
|
8
|
+
* tool, background tasks, LSP servers, git helpers) inherits a working PATH.
|
|
9
|
+
* Idempotent and safe to call once at startup. No-op on Windows.
|
|
10
|
+
*/
|
|
11
|
+
export declare function enrichProcessPath(): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=shell-path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell-path.d.ts","sourceRoot":"","sources":["../../src/core/shell-path.ts"],"names":[],"mappings":"AA4HA;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,GAAE,MAA+B,GAC3C,OAAO,CAAC,MAAM,CAAC,CAqBjB;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAUvD"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { log } from "./logger.js";
|
|
6
|
+
/**
|
|
7
|
+
* Resolve a usable PATH for shelling out to developer tools.
|
|
8
|
+
*
|
|
9
|
+
* GUI apps launched from Finder/Dock (the packaged desktop app) inherit a
|
|
10
|
+
* minimal PATH — on macOS just `/usr/bin:/bin:/usr/sbin:/sbin` — which omits
|
|
11
|
+
* Homebrew (`/opt/homebrew/bin`, `/usr/local/bin`), Cargo (`~/.cargo/bin`),
|
|
12
|
+
* version managers (nvm/asdf/pyenv), and most toolchains. A coding agent that
|
|
13
|
+
* can't find `node`, `npm`, `git`, `python3`, `rg`, `cargo`, … is useless, so
|
|
14
|
+
* we enrich the process PATH once at sidecar startup.
|
|
15
|
+
*
|
|
16
|
+
* Strategy (union, de-duped, order-preserving):
|
|
17
|
+
* 1. The user's real login-shell PATH (captures nvm/asdf/pyenv/custom dirs).
|
|
18
|
+
* 2. The current process PATH (whatever we were launched with).
|
|
19
|
+
* 3. Well-known install dirs that exist on disk (fallback when 1 fails).
|
|
20
|
+
*
|
|
21
|
+
* No-op on Windows, where GUI apps inherit a usable PATH and there's no
|
|
22
|
+
* equivalent login-shell concept.
|
|
23
|
+
*/
|
|
24
|
+
/** Well-known bin dirs a GUI PATH commonly omits, by platform. */
|
|
25
|
+
function wellKnownBinDirs() {
|
|
26
|
+
const home = os.homedir();
|
|
27
|
+
if (process.platform === "darwin") {
|
|
28
|
+
return [
|
|
29
|
+
"/opt/homebrew/bin",
|
|
30
|
+
"/opt/homebrew/sbin",
|
|
31
|
+
"/usr/local/bin",
|
|
32
|
+
"/usr/local/sbin",
|
|
33
|
+
"/opt/local/bin", // MacPorts
|
|
34
|
+
"/opt/local/sbin",
|
|
35
|
+
path.join(home, ".local", "bin"),
|
|
36
|
+
path.join(home, ".cargo", "bin"),
|
|
37
|
+
path.join(home, "go", "bin"),
|
|
38
|
+
path.join(home, ".deno", "bin"),
|
|
39
|
+
path.join(home, ".bun", "bin"),
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
if (process.platform === "linux") {
|
|
43
|
+
return [
|
|
44
|
+
"/usr/local/bin",
|
|
45
|
+
"/usr/local/sbin",
|
|
46
|
+
"/usr/bin",
|
|
47
|
+
"/bin",
|
|
48
|
+
"/usr/sbin",
|
|
49
|
+
"/sbin",
|
|
50
|
+
"/snap/bin",
|
|
51
|
+
path.join(home, ".local", "bin"),
|
|
52
|
+
path.join(home, ".cargo", "bin"),
|
|
53
|
+
path.join(home, "go", "bin"),
|
|
54
|
+
path.join(home, ".deno", "bin"),
|
|
55
|
+
path.join(home, ".bun", "bin"),
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
const DELIMITER = "_GG_SHELL_ENV_DELIMITER_";
|
|
61
|
+
/**
|
|
62
|
+
* Ask the user's login shell for its PATH. Best-effort: resolves to null on any
|
|
63
|
+
* error/timeout so the caller falls back to the well-known dirs. Mirrors the
|
|
64
|
+
* approach used by `shell-env`/`fix-path` (delimited echo, detached to dodge a
|
|
65
|
+
* zsh hang, oh-my-zsh auto-update disabled).
|
|
66
|
+
*/
|
|
67
|
+
function loginShellPath() {
|
|
68
|
+
if (process.platform === "win32")
|
|
69
|
+
return Promise.resolve(null);
|
|
70
|
+
const shell = process.env.SHELL || "/bin/zsh";
|
|
71
|
+
return new Promise((resolve) => {
|
|
72
|
+
let settled = false;
|
|
73
|
+
const finish = (value) => {
|
|
74
|
+
if (settled)
|
|
75
|
+
return;
|
|
76
|
+
settled = true;
|
|
77
|
+
resolve(value);
|
|
78
|
+
};
|
|
79
|
+
try {
|
|
80
|
+
const child = spawn(shell, ["-ilc", `echo -n "${DELIMITER}"; printf "%s" "$PATH"; echo -n "${DELIMITER}"; exit`], {
|
|
81
|
+
// zsh can hang on stdin without detaching; matches shell-env's fix.
|
|
82
|
+
detached: true,
|
|
83
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
84
|
+
env: { ...process.env, DISABLE_AUTO_UPDATE: "true" },
|
|
85
|
+
});
|
|
86
|
+
let out = "";
|
|
87
|
+
child.stdout?.on("data", (d) => {
|
|
88
|
+
out += d.toString("utf-8");
|
|
89
|
+
});
|
|
90
|
+
child.once("error", () => finish(null));
|
|
91
|
+
child.once("close", () => {
|
|
92
|
+
const start = out.indexOf(DELIMITER);
|
|
93
|
+
const end = out.lastIndexOf(DELIMITER);
|
|
94
|
+
if (start === -1 || end === -1 || end <= start) {
|
|
95
|
+
finish(null);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const value = out.slice(start + DELIMITER.length, end).trim();
|
|
99
|
+
finish(value || null);
|
|
100
|
+
});
|
|
101
|
+
// Hard cap: some shells (slow rc files) can stall; don't block startup.
|
|
102
|
+
const timer = setTimeout(() => {
|
|
103
|
+
try {
|
|
104
|
+
if (child.pid)
|
|
105
|
+
process.kill(-child.pid, "SIGKILL");
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
child.kill("SIGKILL");
|
|
109
|
+
}
|
|
110
|
+
finish(null);
|
|
111
|
+
}, 5000);
|
|
112
|
+
timer.unref();
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
finish(null);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
let cached;
|
|
120
|
+
/**
|
|
121
|
+
* Compute the enriched PATH (login shell ∪ current ∪ existing well-known dirs).
|
|
122
|
+
* Cached after first call. Order is preserved and duplicates removed.
|
|
123
|
+
*/
|
|
124
|
+
export async function resolveEnrichedPath(currentPath = process.env.PATH ?? "") {
|
|
125
|
+
if (cached !== undefined)
|
|
126
|
+
return cached;
|
|
127
|
+
const parts = [];
|
|
128
|
+
const seen = new Set();
|
|
129
|
+
const add = (dir) => {
|
|
130
|
+
const d = dir.trim();
|
|
131
|
+
if (d && !seen.has(d)) {
|
|
132
|
+
seen.add(d);
|
|
133
|
+
parts.push(d);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
const login = await loginShellPath();
|
|
137
|
+
if (login)
|
|
138
|
+
for (const d of login.split(path.delimiter))
|
|
139
|
+
add(d);
|
|
140
|
+
for (const d of currentPath.split(path.delimiter))
|
|
141
|
+
add(d);
|
|
142
|
+
// Only append fallback dirs that actually exist, so PATH stays clean.
|
|
143
|
+
for (const d of wellKnownBinDirs())
|
|
144
|
+
if (existsSync(d))
|
|
145
|
+
add(d);
|
|
146
|
+
cached = parts.join(path.delimiter);
|
|
147
|
+
return cached;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Enrich `process.env.PATH` in place so every later spawn/execFile (the bash
|
|
151
|
+
* tool, background tasks, LSP servers, git helpers) inherits a working PATH.
|
|
152
|
+
* Idempotent and safe to call once at startup. No-op on Windows.
|
|
153
|
+
*/
|
|
154
|
+
export async function enrichProcessPath() {
|
|
155
|
+
if (process.platform === "win32")
|
|
156
|
+
return;
|
|
157
|
+
const before = process.env.PATH ?? "";
|
|
158
|
+
const enriched = await resolveEnrichedPath(before);
|
|
159
|
+
if (enriched && enriched !== before) {
|
|
160
|
+
process.env.PATH = enriched;
|
|
161
|
+
log("INFO", "shell-path", "enriched PATH for tools", {
|
|
162
|
+
added: enriched.length - before.length,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=shell-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell-path.js","sourceRoot":"","sources":["../../src/core/shell-path.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-platform shell resolution for the bash tool + background process
|
|
3
|
+
* manager.
|
|
4
|
+
*
|
|
5
|
+
* The agent writes shell commands assuming POSIX `bash` semantics (`&&`, pipes,
|
|
6
|
+
* `ls`, `grep`, `$(...)`, single-quoting, …). On macOS/Linux that's just
|
|
7
|
+
* `bash`. On Windows there are three cases, and getting this wrong is the root
|
|
8
|
+
* of the "files not mounted / different environment" class of bugs:
|
|
9
|
+
*
|
|
10
|
+
* 1. Git Bash (Git for Windows) — a REAL POSIX bash that operates on the
|
|
11
|
+
* native Windows filesystem. `D:\proj` is reachable as `/d/proj` AND the
|
|
12
|
+
* spawned process honors the Windows `cwd`. This is what we want, so we
|
|
13
|
+
* detect and prefer it.
|
|
14
|
+
*
|
|
15
|
+
* 2. WSL bash (`C:\Windows\System32\bash.exe`) — the Windows Subsystem for
|
|
16
|
+
* Linux launcher. It runs commands inside a SEPARATE Linux distro whose
|
|
17
|
+
* filesystem is not the project tree (`D:\proj` ≈ `/mnt/d/proj`, and a
|
|
18
|
+
* raw `D:\proj` cwd lands you somewhere else entirely). Commands appear to
|
|
19
|
+
* run "in a different project / sandbox". We deliberately SKIP it.
|
|
20
|
+
*
|
|
21
|
+
* 3. No bash at all — bare `spawn("bash", …)` fails with `spawn bash ENOENT`,
|
|
22
|
+
* so every shell command the agent runs errors out. We fall back to
|
|
23
|
+
* `cmd.exe` so commands can at least run (with different semantics, which
|
|
24
|
+
* the agent is told about).
|
|
25
|
+
*
|
|
26
|
+
* The resolver is pure: filesystem + env + platform are injected so it can be
|
|
27
|
+
* unit-tested for every OS from any host.
|
|
28
|
+
*/
|
|
29
|
+
export interface ShellResolution {
|
|
30
|
+
/** Executable to spawn (never goes through a shell wrapper itself). */
|
|
31
|
+
file: string;
|
|
32
|
+
/** Args that run the given command string as one shell command. */
|
|
33
|
+
args: string[];
|
|
34
|
+
/** True when `file` is a cmd.exe fallback (non-POSIX semantics). */
|
|
35
|
+
isCmdFallback: boolean;
|
|
36
|
+
}
|
|
37
|
+
export interface ResolveShellOpts {
|
|
38
|
+
platform?: NodeJS.Platform;
|
|
39
|
+
env?: NodeJS.ProcessEnv;
|
|
40
|
+
/** Injected for testability; defaults to fs.existsSync. */
|
|
41
|
+
exists?: (p: string) => boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Resolve the shell executable + args to run a single command string.
|
|
45
|
+
*
|
|
46
|
+
* `GG_BASH` env override always wins (point it at any POSIX bash, e.g. a custom
|
|
47
|
+
* Git Bash or msys2 install). Otherwise: non-Windows → `bash`; Windows → Git
|
|
48
|
+
* Bash if found, else `cmd.exe`.
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolveShell(command: string, opts?: ResolveShellOpts): ShellResolution;
|
|
51
|
+
//# sourceMappingURL=shell.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../src/core/shell.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,oEAAoE;IACpE,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;CACjC;AAmDD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,gBAAqB,GAAG,eAAe,CAwB1F"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Fixed Git-Bash install locations to probe on Windows, in priority order.
|
|
5
|
+
* These cover the official Git for Windows installer (system + per-user) plus
|
|
6
|
+
* the common 32-bit path. We NEVER include `System32\bash.exe` (WSL).
|
|
7
|
+
*/
|
|
8
|
+
function gitBashFixedCandidates(env) {
|
|
9
|
+
const programFiles = env.ProgramFiles ?? "C:\\Program Files";
|
|
10
|
+
const programFilesX86 = env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
|
|
11
|
+
const localAppData = env.LOCALAPPDATA;
|
|
12
|
+
const candidates = [
|
|
13
|
+
path.win32.join(programFiles, "Git", "bin", "bash.exe"),
|
|
14
|
+
path.win32.join(programFilesX86, "Git", "bin", "bash.exe"),
|
|
15
|
+
];
|
|
16
|
+
if (localAppData) {
|
|
17
|
+
candidates.push(path.win32.join(localAppData, "Programs", "Git", "bin", "bash.exe"));
|
|
18
|
+
}
|
|
19
|
+
return candidates;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Derive Git Bash from `git.exe` on PATH: Git for Windows ships `git.exe` under
|
|
23
|
+
* `<root>\cmd` (and `<root>\bin`), with `bash.exe` at `<root>\bin\bash.exe`.
|
|
24
|
+
*/
|
|
25
|
+
function gitBashFromPath(env, exists) {
|
|
26
|
+
const rawPath = env.PATH ?? env.Path ?? "";
|
|
27
|
+
if (!rawPath)
|
|
28
|
+
return null;
|
|
29
|
+
// Windows PATH is always ';'-separated. (Don't use path.delimiter — it
|
|
30
|
+
// reflects the HOST OS, which breaks when this win32-only branch is exercised
|
|
31
|
+
// in cross-platform tests on a POSIX host.)
|
|
32
|
+
for (const dir of rawPath.split(";")) {
|
|
33
|
+
if (!dir)
|
|
34
|
+
continue;
|
|
35
|
+
const gitExe = path.win32.join(dir, "git.exe");
|
|
36
|
+
if (!exists(gitExe))
|
|
37
|
+
continue;
|
|
38
|
+
// <root>\cmd\git.exe or <root>\bin\git.exe → <root>\bin\bash.exe
|
|
39
|
+
const gitRoot = path.win32.dirname(path.win32.dirname(gitExe));
|
|
40
|
+
const bash = path.win32.join(gitRoot, "bin", "bash.exe");
|
|
41
|
+
if (exists(bash))
|
|
42
|
+
return bash;
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
/** Locate a usable Git Bash on Windows, or null if none is installed. */
|
|
47
|
+
function findGitBash(env, exists) {
|
|
48
|
+
for (const candidate of gitBashFixedCandidates(env)) {
|
|
49
|
+
if (exists(candidate))
|
|
50
|
+
return candidate;
|
|
51
|
+
}
|
|
52
|
+
return gitBashFromPath(env, exists);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Resolve the shell executable + args to run a single command string.
|
|
56
|
+
*
|
|
57
|
+
* `GG_BASH` env override always wins (point it at any POSIX bash, e.g. a custom
|
|
58
|
+
* Git Bash or msys2 install). Otherwise: non-Windows → `bash`; Windows → Git
|
|
59
|
+
* Bash if found, else `cmd.exe`.
|
|
60
|
+
*/
|
|
61
|
+
export function resolveShell(command, opts = {}) {
|
|
62
|
+
const platform = opts.platform ?? process.platform;
|
|
63
|
+
const env = opts.env ?? process.env;
|
|
64
|
+
const exists = opts.exists ?? existsSync;
|
|
65
|
+
// Explicit override (power users / tests): treat as a POSIX bash.
|
|
66
|
+
const override = env.GG_BASH?.trim();
|
|
67
|
+
if (override) {
|
|
68
|
+
return { file: override, args: ["-c", command], isCmdFallback: false };
|
|
69
|
+
}
|
|
70
|
+
if (platform !== "win32") {
|
|
71
|
+
return { file: "bash", args: ["-c", command], isCmdFallback: false };
|
|
72
|
+
}
|
|
73
|
+
const gitBash = findGitBash(env, exists);
|
|
74
|
+
if (gitBash) {
|
|
75
|
+
return { file: gitBash, args: ["-c", command], isCmdFallback: false };
|
|
76
|
+
}
|
|
77
|
+
// Last resort: cmd.exe. `/d` skips AutoRun, `/s` + `/c` runs the rest as a
|
|
78
|
+
// single command verbatim (correct quoting for an arbitrary command string).
|
|
79
|
+
const comspec = env.ComSpec ?? env.COMSPEC ?? "C:\\Windows\\System32\\cmd.exe";
|
|
80
|
+
return { file: comspec, args: ["/d", "/s", "/c", command], isCmdFallback: true };
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=shell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/core/shell.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell.test.d.ts","sourceRoot":"","sources":["../../src/core/shell.test.ts"],"names":[],"mappings":""}
|