@aligndottech/cli 0.47.1 → 0.49.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 +6 -5
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +9 -18
- package/dist/cli.js.map +1 -1
- package/dist/commands/agents.d.ts +20 -0
- package/dist/commands/agents.d.ts.map +1 -0
- package/dist/commands/agents.js +62 -0
- package/dist/commands/agents.js.map +1 -0
- package/dist/commands/ai.d.ts +11 -0
- package/dist/commands/ai.d.ts.map +1 -0
- package/dist/commands/ai.js +121 -0
- package/dist/commands/ai.js.map +1 -0
- package/dist/commands/default-action.js +2 -2
- package/dist/commands/default-action.js.map +1 -1
- package/dist/commands/registry.d.ts.map +1 -1
- package/dist/commands/registry.js +7 -0
- package/dist/commands/registry.js.map +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +53 -191
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/use.js +1 -1
- package/dist/commands/use.js.map +1 -1
- package/dist/commands/why.d.ts.map +1 -1
- package/dist/commands/why.js +21 -0
- package/dist/commands/why.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/ask-key-offer.d.ts +38 -0
- package/dist/lib/ask-key-offer.d.ts.map +1 -0
- package/dist/lib/ask-key-offer.js +130 -0
- package/dist/lib/ask-key-offer.js.map +1 -0
- package/dist/lib/config.d.ts +25 -24
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +37 -45
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/launch/adapters/amp.d.ts +18 -0
- package/dist/lib/launch/adapters/amp.d.ts.map +1 -0
- package/dist/lib/launch/adapters/amp.js +29 -0
- package/dist/lib/launch/adapters/amp.js.map +1 -0
- package/dist/lib/launch/adapters/claude-code.d.ts +8 -0
- package/dist/lib/launch/adapters/claude-code.d.ts.map +1 -1
- package/dist/lib/launch/adapters/claude-code.js.map +1 -1
- package/dist/lib/launch/adapters/codex.d.ts +17 -0
- package/dist/lib/launch/adapters/codex.d.ts.map +1 -0
- package/dist/lib/launch/adapters/codex.js +44 -0
- package/dist/lib/launch/adapters/codex.js.map +1 -0
- package/dist/lib/launch/adapters/copilot.d.ts +17 -0
- package/dist/lib/launch/adapters/copilot.d.ts.map +1 -0
- package/dist/lib/launch/adapters/copilot.js +29 -0
- package/dist/lib/launch/adapters/copilot.js.map +1 -0
- package/dist/lib/launch/adapters/droid.d.ts +19 -0
- package/dist/lib/launch/adapters/droid.d.ts.map +1 -0
- package/dist/lib/launch/adapters/droid.js +38 -0
- package/dist/lib/launch/adapters/droid.js.map +1 -0
- package/dist/lib/launch/adapters/gemini-cli.d.ts +25 -0
- package/dist/lib/launch/adapters/gemini-cli.d.ts.map +1 -0
- package/dist/lib/launch/adapters/gemini-cli.js +73 -0
- package/dist/lib/launch/adapters/gemini-cli.js.map +1 -0
- package/dist/lib/launch/adapters/grok-build.d.ts +16 -0
- package/dist/lib/launch/adapters/grok-build.d.ts.map +1 -0
- package/dist/lib/launch/adapters/grok-build.js +25 -0
- package/dist/lib/launch/adapters/grok-build.js.map +1 -0
- package/dist/lib/launch/adapters/kiro.d.ts +17 -0
- package/dist/lib/launch/adapters/kiro.d.ts.map +1 -0
- package/dist/lib/launch/adapters/kiro.js +25 -0
- package/dist/lib/launch/adapters/kiro.js.map +1 -0
- package/dist/lib/launch/adapters/qwen.d.ts +25 -0
- package/dist/lib/launch/adapters/qwen.d.ts.map +1 -0
- package/dist/lib/launch/adapters/qwen.js +67 -0
- package/dist/lib/launch/adapters/qwen.js.map +1 -0
- package/dist/lib/launch/agents.d.ts +16 -3
- package/dist/lib/launch/agents.d.ts.map +1 -1
- package/dist/lib/launch/agents.js +26 -4
- package/dist/lib/launch/agents.js.map +1 -1
- package/dist/lib/launch/amp-state.d.ts +21 -0
- package/dist/lib/launch/amp-state.d.ts.map +1 -0
- package/dist/lib/launch/amp-state.js +61 -0
- package/dist/lib/launch/amp-state.js.map +1 -0
- package/dist/lib/launch/codex-state.d.ts +31 -0
- package/dist/lib/launch/codex-state.d.ts.map +1 -0
- package/dist/lib/launch/codex-state.js +92 -0
- package/dist/lib/launch/codex-state.js.map +1 -0
- package/dist/lib/launch/config-writes.d.ts +7 -1
- package/dist/lib/launch/config-writes.d.ts.map +1 -1
- package/dist/lib/launch/config-writes.js +60 -7
- package/dist/lib/launch/config-writes.js.map +1 -1
- package/dist/lib/launch/copilot-state.d.ts +19 -0
- package/dist/lib/launch/copilot-state.d.ts.map +1 -0
- package/dist/lib/launch/copilot-state.js +51 -0
- package/dist/lib/launch/copilot-state.js.map +1 -0
- package/dist/lib/launch/detect.d.ts.map +1 -1
- package/dist/lib/launch/detect.js +2 -1
- package/dist/lib/launch/detect.js.map +1 -1
- package/dist/lib/launch/droid-state.d.ts +24 -0
- package/dist/lib/launch/droid-state.d.ts.map +1 -0
- package/dist/lib/launch/droid-state.js +74 -0
- package/dist/lib/launch/droid-state.js.map +1 -0
- package/dist/lib/launch/gemini-state.d.ts +32 -0
- package/dist/lib/launch/gemini-state.d.ts.map +1 -0
- package/dist/lib/launch/gemini-state.js +59 -0
- package/dist/lib/launch/gemini-state.js.map +1 -0
- package/dist/lib/launch/gemini-trust.d.ts +26 -0
- package/dist/lib/launch/gemini-trust.d.ts.map +1 -0
- package/dist/lib/launch/gemini-trust.js +103 -0
- package/dist/lib/launch/gemini-trust.js.map +1 -0
- package/dist/lib/launch/grok-state.d.ts +42 -0
- package/dist/lib/launch/grok-state.d.ts.map +1 -0
- package/dist/lib/launch/grok-state.js +128 -0
- package/dist/lib/launch/grok-state.js.map +1 -0
- package/dist/lib/launch/install.d.ts +33 -0
- package/dist/lib/launch/install.d.ts.map +1 -0
- package/dist/lib/launch/install.js +48 -0
- package/dist/lib/launch/install.js.map +1 -0
- package/dist/lib/launch/kiro-state.d.ts +22 -0
- package/dist/lib/launch/kiro-state.d.ts.map +1 -0
- package/dist/lib/launch/kiro-state.js +59 -0
- package/dist/lib/launch/kiro-state.js.map +1 -0
- package/dist/lib/launch/launch-files.d.ts +15 -0
- package/dist/lib/launch/launch-files.d.ts.map +1 -1
- package/dist/lib/launch/launch-files.js +64 -4
- package/dist/lib/launch/launch-files.js.map +1 -1
- package/dist/lib/launch/launch.d.ts +61 -6
- package/dist/lib/launch/launch.d.ts.map +1 -1
- package/dist/lib/launch/launch.js +98 -31
- package/dist/lib/launch/launch.js.map +1 -1
- package/dist/lib/launch/layer-files.d.ts +12 -0
- package/dist/lib/launch/layer-files.d.ts.map +1 -0
- package/dist/lib/launch/layer-files.js +43 -0
- package/dist/lib/launch/layer-files.js.map +1 -0
- package/dist/lib/launch/pick-agent.d.ts +12 -5
- package/dist/lib/launch/pick-agent.d.ts.map +1 -1
- package/dist/lib/launch/pick-agent.js +47 -19
- package/dist/lib/launch/pick-agent.js.map +1 -1
- package/dist/lib/launch/picker-options.d.ts +30 -0
- package/dist/lib/launch/picker-options.d.ts.map +1 -0
- package/dist/lib/launch/picker-options.js +42 -0
- package/dist/lib/launch/picker-options.js.map +1 -0
- package/dist/lib/launch/prompts.d.ts +11 -0
- package/dist/lib/launch/prompts.d.ts.map +1 -0
- package/dist/lib/launch/prompts.js +27 -0
- package/dist/lib/launch/prompts.js.map +1 -0
- package/dist/lib/launch/qwen-state.d.ts +30 -0
- package/dist/lib/launch/qwen-state.d.ts.map +1 -0
- package/dist/lib/launch/qwen-state.js +57 -0
- package/dist/lib/launch/qwen-state.js.map +1 -0
- package/dist/lib/launch/qwen-trust.d.ts +24 -0
- package/dist/lib/launch/qwen-trust.d.ts.map +1 -0
- package/dist/lib/launch/qwen-trust.js +100 -0
- package/dist/lib/launch/qwen-trust.js.map +1 -0
- package/dist/lib/launch/registry/agents/amp.d.ts +3 -0
- package/dist/lib/launch/registry/agents/amp.d.ts.map +1 -0
- package/dist/lib/launch/registry/agents/amp.js +14 -0
- package/dist/lib/launch/registry/agents/amp.js.map +1 -0
- package/dist/lib/launch/registry/agents/claude-code.js +1 -1
- package/dist/lib/launch/registry/agents/claude-code.js.map +1 -1
- package/dist/lib/launch/registry/agents/codex.d.ts.map +1 -1
- package/dist/lib/launch/registry/agents/codex.js +4 -2
- package/dist/lib/launch/registry/agents/codex.js.map +1 -1
- package/dist/lib/launch/registry/agents/copilot.d.ts +3 -0
- package/dist/lib/launch/registry/agents/copilot.d.ts.map +1 -0
- package/dist/lib/launch/registry/agents/copilot.js +11 -0
- package/dist/lib/launch/registry/agents/copilot.js.map +1 -0
- package/dist/lib/launch/registry/agents/cursor.js +1 -1
- package/dist/lib/launch/registry/agents/cursor.js.map +1 -1
- package/dist/lib/launch/registry/agents/droid.d.ts +3 -0
- package/dist/lib/launch/registry/agents/droid.d.ts.map +1 -0
- package/dist/lib/launch/registry/agents/droid.js +13 -0
- package/dist/lib/launch/registry/agents/droid.js.map +1 -0
- package/dist/lib/launch/registry/agents/gemini-cli.d.ts.map +1 -1
- package/dist/lib/launch/registry/agents/gemini-cli.js +4 -2
- package/dist/lib/launch/registry/agents/gemini-cli.js.map +1 -1
- package/dist/lib/launch/registry/agents/grok-build.d.ts +3 -0
- package/dist/lib/launch/registry/agents/grok-build.d.ts.map +1 -0
- package/dist/lib/launch/registry/agents/grok-build.js +14 -0
- package/dist/lib/launch/registry/agents/grok-build.js.map +1 -0
- package/dist/lib/launch/registry/agents/kiro.d.ts +3 -0
- package/dist/lib/launch/registry/agents/kiro.d.ts.map +1 -0
- package/dist/lib/launch/registry/agents/kiro.js +11 -0
- package/dist/lib/launch/registry/agents/kiro.js.map +1 -0
- package/dist/lib/launch/registry/agents/opencode.js +1 -1
- package/dist/lib/launch/registry/agents/opencode.js.map +1 -1
- package/dist/lib/launch/registry/agents/pi.js +1 -1
- package/dist/lib/launch/registry/agents/pi.js.map +1 -1
- package/dist/lib/launch/registry/agents/qwen.d.ts +3 -0
- package/dist/lib/launch/registry/agents/qwen.d.ts.map +1 -0
- package/dist/lib/launch/registry/agents/qwen.js +11 -0
- package/dist/lib/launch/registry/agents/qwen.js.map +1 -0
- package/dist/lib/launch/registry/index.d.ts +4 -1
- package/dist/lib/launch/registry/index.d.ts.map +1 -1
- package/dist/lib/launch/registry/index.js +11 -2
- package/dist/lib/launch/registry/index.js.map +1 -1
- package/dist/lib/launch/registry/types.d.ts +18 -2
- package/dist/lib/launch/registry/types.d.ts.map +1 -1
- package/dist/lib/launch/run-agent.d.ts +15 -0
- package/dist/lib/launch/run-agent.d.ts.map +1 -1
- package/dist/lib/launch/run-agent.js +23 -2
- package/dist/lib/launch/run-agent.js.map +1 -1
- package/dist/lib/launch/strict-entry.d.ts +49 -0
- package/dist/lib/launch/strict-entry.d.ts.map +1 -0
- package/dist/lib/launch/strict-entry.js +108 -0
- package/dist/lib/launch/strict-entry.js.map +1 -0
- package/dist/lib/llm-providers.d.ts +66 -0
- package/dist/lib/llm-providers.d.ts.map +1 -0
- package/dist/lib/llm-providers.js +150 -0
- package/dist/lib/llm-providers.js.map +1 -0
- package/dist/lib/local-llm.d.ts +63 -12
- package/dist/lib/local-llm.d.ts.map +1 -1
- package/dist/lib/local-llm.js +229 -104
- package/dist/lib/local-llm.js.map +1 -1
- package/dist/lib/safe-config-write.d.ts +12 -1
- package/dist/lib/safe-config-write.d.ts.map +1 -1
- package/dist/lib/safe-config-write.js +123 -7
- package/dist/lib/safe-config-write.js.map +1 -1
- package/dist/lib/startup-env.d.ts +8 -0
- package/dist/lib/startup-env.d.ts.map +1 -0
- package/dist/lib/startup-env.js +8 -0
- package/dist/lib/startup-env.js.map +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { ALIGN_NUDGE_START } from '../agent-rules.js';
|
|
4
|
+
/** A file's text, or null when it is missing or unreadable (a directory, no permission). */
|
|
5
|
+
export function readText(file) {
|
|
6
|
+
try {
|
|
7
|
+
return readFileSync(file, 'utf8');
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/** cwd and every directory above it, to the filesystem root, nearest first. */
|
|
14
|
+
export function ancestors(cwd) {
|
|
15
|
+
const dirs = [];
|
|
16
|
+
for (let dir = path.resolve(cwd);; dir = path.dirname(dir)) {
|
|
17
|
+
dirs.push(dir);
|
|
18
|
+
if (path.dirname(dir) === dir)
|
|
19
|
+
return dirs;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** The file carries the managed align block (`align setup`'s instructions). */
|
|
23
|
+
export function fileHasBlock(file) {
|
|
24
|
+
return readText(file)?.includes(ALIGN_NUDGE_START) ?? false;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The value of a root option in the user's own args, before any `--` (`--opt v` or `--opt=v`).
|
|
28
|
+
* The last one wins, as a CLI parser reads it. undefined when absent.
|
|
29
|
+
*/
|
|
30
|
+
export function optionValue(passthrough, name) {
|
|
31
|
+
let value;
|
|
32
|
+
for (let i = 0; i < passthrough.length; i++) {
|
|
33
|
+
const a = passthrough[i];
|
|
34
|
+
if (a === '--')
|
|
35
|
+
break;
|
|
36
|
+
if (a === name)
|
|
37
|
+
value = passthrough[++i];
|
|
38
|
+
else if (a.startsWith(`${name}=`))
|
|
39
|
+
value = a.slice(name.length + 1);
|
|
40
|
+
}
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=layer-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layer-files.js","sourceRoot":"","sources":["../../../src/lib/launch/layer-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,4FAA4F;AAC5F,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5D,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACf,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;IAC7C,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC;AAC9D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,WAAqB,EAAE,IAAY;IAC7D,IAAI,KAAyB,CAAC;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5C,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAE,CAAC;QAC1B,IAAI,CAAC,KAAK,IAAI;YAAE,MAAM;QACtB,IAAI,CAAC,KAAK,IAAI;YAAE,KAAK,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;aACpC,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,CAAC;YAAE,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -1,17 +1,24 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { LaunchAgentId } from './registry/types.js';
|
|
2
2
|
import { type LaunchAgent } from './agents.js';
|
|
3
|
+
import { type InstallOfferDeps } from './install.js';
|
|
4
|
+
import { type PickerOption } from './picker-options.js';
|
|
3
5
|
/**
|
|
4
6
|
* The wizard's "which coding agent?" step (C5). It reads the same table and the same PATH scan
|
|
5
7
|
* the launcher does and stores through the same config key, so what the wizard picks is exactly
|
|
6
|
-
* what bare `align` opens afterwards.
|
|
8
|
+
* what bare `align` opens afterwards. On a terminal the picker lists every supported agent,
|
|
9
|
+
* installed ones first; picking a missing one offers its install (plan Decision 4).
|
|
7
10
|
*/
|
|
8
11
|
export interface PickAgentDeps {
|
|
9
12
|
env: Record<string, string | undefined>;
|
|
10
13
|
platform: string;
|
|
11
14
|
agents: readonly LaunchAgent[];
|
|
12
15
|
findOnPath(bin: string, env: Record<string, string | undefined>, platform: string): string | null;
|
|
13
|
-
/** Resolves null when the user cancels. Only called on a terminal
|
|
14
|
-
select(
|
|
16
|
+
/** Resolves null when the user cancels. Only called on a terminal. `initial` is preselected. */
|
|
17
|
+
select(options: PickerOption[], initial?: LaunchAgentId): Promise<LaunchAgentId | null>;
|
|
18
|
+
/** Default-No question: true on yes, false on no, null on Ctrl-C (install-on-pick). */
|
|
19
|
+
confirm(message: string): Promise<boolean | null>;
|
|
20
|
+
/** Runs an install argv the user approved. */
|
|
21
|
+
spawn: InstallOfferDeps['spawn'];
|
|
15
22
|
say(line: string): void;
|
|
16
23
|
}
|
|
17
24
|
/** The user cancelled the picker: the wizard stops, like any other cancelled prompt. */
|
|
@@ -24,5 +31,5 @@ export interface AgentConfig {
|
|
|
24
31
|
export declare function pickAgent(config: AgentConfig, opts: {
|
|
25
32
|
interactive: boolean;
|
|
26
33
|
approve?: boolean;
|
|
27
|
-
}, overrides?: Partial<PickAgentDeps>): Promise<
|
|
34
|
+
}, overrides?: Partial<PickAgentDeps>): Promise<LaunchAgentId | null | typeof PICK_CANCELLED>;
|
|
28
35
|
//# sourceMappingURL=pick-agent.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pick-agent.d.ts","sourceRoot":"","sources":["../../../src/lib/launch/pick-agent.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pick-agent.d.ts","sourceRoot":"","sources":["../../../src/lib/launch/pick-agent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAA2B,KAAK,WAAW,EAA4D,MAAM,aAAa,CAAC;AAElI,OAAO,EAAE,KAAK,gBAAgB,EAAgB,MAAM,cAAc,CAAC;AACnE,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAIrE;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IAC/B,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAClG,gGAAgG;IAChG,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IACxF,uFAAuF;IACvF,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAClD,8CAA8C;IAC9C,KAAK,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACjC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,wFAAwF;AACxF,eAAO,MAAM,cAAc,EAAG,WAAoB,CAAC;AAEnD,MAAM,WAAW,WAAW;IAC1B,QAAQ,IAAI,MAAM,GAAG,SAAS,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,CAAC,IAAI,OAAO,CAAC;CACzB;AAeD,wBAAsB,SAAS,CAC7B,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE;IAAE,WAAW,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,EACjD,SAAS,GAAE,OAAO,CAAC,aAAa,CAAM,GACrC,OAAO,CAAC,aAAa,GAAG,IAAI,GAAG,OAAO,cAAc,CAAC,CAkEvD"}
|
|
@@ -1,49 +1,77 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { spawn as nodeSpawn } from 'node:child_process';
|
|
2
|
+
import { agentByName, byPriority, PRE_WAVE_A, PRE_WAVE_B, resolveAgentBin, supportedAgents } from './agents.js';
|
|
2
3
|
import { findOnPath } from './detect.js';
|
|
4
|
+
import { offerInstall } from './install.js';
|
|
5
|
+
import { chooseAgent } from './picker-options.js';
|
|
6
|
+
import { confirmDefaultNo, selectAgent } from './prompts.js';
|
|
7
|
+
import { specByName } from './registry/index.js';
|
|
3
8
|
/** The user cancelled the picker: the wizard stops, like any other cancelled prompt. */
|
|
4
9
|
export const PICK_CANCELLED = 'cancelled';
|
|
5
|
-
async function clackSelect(candidates) {
|
|
6
|
-
const clack = await import('@clack/prompts');
|
|
7
|
-
const answer = await clack.select({
|
|
8
|
-
message: 'Which coding agent should `align` open?',
|
|
9
|
-
options: candidates.map((a) => ({ value: a.name, label: a.label })),
|
|
10
|
-
});
|
|
11
|
-
return clack.isCancel(answer) ? null : answer;
|
|
12
|
-
}
|
|
13
10
|
function defaultDeps() {
|
|
14
11
|
return {
|
|
15
12
|
env: process.env,
|
|
16
13
|
platform: process.platform,
|
|
17
14
|
agents: supportedAgents(),
|
|
18
15
|
findOnPath,
|
|
19
|
-
select:
|
|
16
|
+
select: (options, initial) => selectAgent(options, initial),
|
|
17
|
+
confirm: (message) => confirmDefaultNo(message),
|
|
18
|
+
spawn: (command, args, options) => nodeSpawn(command, args, options),
|
|
20
19
|
say: (l) => console.log(l),
|
|
21
20
|
};
|
|
22
21
|
}
|
|
23
22
|
export async function pickAgent(config, opts, overrides = {}) {
|
|
24
23
|
const d = { ...defaultDeps(), ...overrides };
|
|
25
|
-
const
|
|
24
|
+
const isInstalled = (a) => resolveAgentBin(a, d.findOnPath, d.env, d.platform) !== null;
|
|
25
|
+
const installed = d.agents.filter(isInstalled);
|
|
26
26
|
// A re-run keeps the choice, provided it can still be launched; `align use` changes it. A
|
|
27
27
|
// stored agent that has left PATH is treated as no choice at all.
|
|
28
28
|
const stored = agentByName(config.getAgent());
|
|
29
29
|
if (stored && installed.some((a) => a.name === stored.name))
|
|
30
30
|
return stored.name;
|
|
31
|
-
if (installed.length === 0) {
|
|
31
|
+
if (installed.length === 0 && (!opts.interactive || opts.approve)) {
|
|
32
32
|
d.say('No coding agent that Align can open was found on your PATH. Align works with:');
|
|
33
33
|
for (const a of d.agents)
|
|
34
34
|
d.say(` ${a.label}: ${a.install}`);
|
|
35
|
-
d.say('Install one, then run `align` again.');
|
|
35
|
+
d.say('Install one, then run `align` again. `align agents` lists them all.');
|
|
36
36
|
return null;
|
|
37
37
|
}
|
|
38
|
+
// Without a terminal and without --approve, only the oldest launchable agents installed are
|
|
39
|
+
// weighed, wave by wave: a machine with Claude Code plus Codex picks Claude Code, as it did
|
|
40
|
+
// before Codex could be launched, Codex plus Qwen picks Codex, as before wave B, and two agents
|
|
41
|
+
// of the same wave still are not guessed between.
|
|
42
|
+
const tier = [PRE_WAVE_A, PRE_WAVE_B].map((set) => installed.filter((a) => set.has(a.name))).find((t) => t.length > 0);
|
|
43
|
+
const unattended = !opts.interactive && !opts.approve && tier ? tier : installed;
|
|
38
44
|
let chosen;
|
|
39
|
-
if (
|
|
40
|
-
chosen = installed[0];
|
|
45
|
+
if (opts.approve) {
|
|
46
|
+
chosen = byPriority(installed)[0];
|
|
41
47
|
}
|
|
42
48
|
else if (opts.interactive) {
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
// Always asked on a terminal: with one installed it is preselected, so Enter keeps it.
|
|
50
|
+
chosen = await chooseAgent(d.agents, {
|
|
51
|
+
isInstalled,
|
|
52
|
+
select: (options, initial) => d.select(options, initial),
|
|
53
|
+
offer: (a) => offerInstall(specByName(a.name), {
|
|
54
|
+
isTTY: true,
|
|
55
|
+
platform: d.platform,
|
|
56
|
+
confirm: (m) => d.confirm(m),
|
|
57
|
+
spawn: d.spawn,
|
|
58
|
+
onPath: (bin) => d.findOnPath(bin, d.env, d.platform),
|
|
59
|
+
say: d.say,
|
|
60
|
+
}),
|
|
61
|
+
say: d.say,
|
|
62
|
+
});
|
|
63
|
+
if (chosen === null) {
|
|
64
|
+
// With nothing installed, leaving the picker is not cancelling setup: it carries on with no
|
|
65
|
+
// agent chosen, as it did before the picker listed missing agents.
|
|
66
|
+
if (installed.length === 0) {
|
|
67
|
+
d.say('No agent chosen. Install one, then run `align` again. `align agents` lists them all.');
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
45
70
|
return PICK_CANCELLED;
|
|
46
|
-
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else if (unattended.length === 1) {
|
|
74
|
+
chosen = unattended[0];
|
|
47
75
|
}
|
|
48
76
|
else {
|
|
49
77
|
d.say(`More than one coding agent is installed (${installed.map((a) => a.label).join(', ')}) and there is no terminal to ask in.`);
|
|
@@ -56,7 +84,7 @@ export async function pickAgent(config, opts, overrides = {}) {
|
|
|
56
84
|
config.setAgent(chosen.name);
|
|
57
85
|
if (wasOff)
|
|
58
86
|
d.say('Launching is on again: `align use --undo` had turned it off.');
|
|
59
|
-
if (installed.length === 1)
|
|
87
|
+
if (installed.length === 1 || unattended.length === 1)
|
|
60
88
|
d.say(`Using ${chosen.label}. Switch any time with \`align use\`.`);
|
|
61
89
|
return chosen.name;
|
|
62
90
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pick-agent.js","sourceRoot":"","sources":["../../../src/lib/launch/pick-agent.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pick-agent.js","sourceRoot":"","sources":["../../../src/lib/launch/pick-agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { LaunchAgent } from './agents.js';
|
|
2
|
+
import type { InstallOutcome } from './install.js';
|
|
3
|
+
import type { LaunchAgentId } from './registry/types.js';
|
|
4
|
+
export interface PickerOption {
|
|
5
|
+
value: LaunchAgentId;
|
|
6
|
+
label: string;
|
|
7
|
+
hint?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Every agent Align supports, for the "which coding agent?" picker: the installed ones first,
|
|
11
|
+
* then the rest, each by label, the rest marked with how to install them. Built from whatever
|
|
12
|
+
* list it is given, so a new registry spec appears with no change here.
|
|
13
|
+
*/
|
|
14
|
+
export declare function pickerOptions(agents: readonly LaunchAgent[], isInstalled: (a: LaunchAgent) => boolean): PickerOption[];
|
|
15
|
+
export interface ChooseDeps {
|
|
16
|
+
isInstalled(a: LaunchAgent): boolean;
|
|
17
|
+
/** Resolves null when the user cancels. `initial` is the row the cursor starts on. */
|
|
18
|
+
select(options: PickerOption[], initial?: LaunchAgentId): Promise<LaunchAgentId | null>;
|
|
19
|
+
/** Decision 4: offer to install a picked agent that is missing (install.ts). */
|
|
20
|
+
offer(a: LaunchAgent): Promise<InstallOutcome>;
|
|
21
|
+
say(line: string): void;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Show the picker until the user picks an installed agent (or one that installs and is then
|
|
25
|
+
* found on PATH) or cancels, at the picker or at the install question. A plain No, a printed
|
|
26
|
+
* installer or a failed install returns to the picker. With exactly one agent installed the
|
|
27
|
+
* cursor starts on it, so Enter keeps what bare `align` used to pick without asking.
|
|
28
|
+
*/
|
|
29
|
+
export declare function chooseAgent(agents: readonly LaunchAgent[], d: ChooseDeps): Promise<LaunchAgent | null>;
|
|
30
|
+
//# sourceMappingURL=picker-options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"picker-options.d.ts","sourceRoot":"","sources":["../../../src/lib/launch/picker-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,aAAa,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAKD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,EAAE,WAAW,KAAK,OAAO,GAAG,YAAY,EAAE,CAOtH;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,CAAC,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;IACrC,sFAAsF;IACtF,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IACxF,gFAAgF;IAChF,KAAK,CAAC,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC/C,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,EAAE,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAe5G"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** Code-unit order, never locale order: the same list on every machine. */
|
|
2
|
+
const byLabel = (a, b) => (a.label < b.label ? -1 : a.label > b.label ? 1 : 0);
|
|
3
|
+
/**
|
|
4
|
+
* Every agent Align supports, for the "which coding agent?" picker: the installed ones first,
|
|
5
|
+
* then the rest, each by label, the rest marked with how to install them. Built from whatever
|
|
6
|
+
* list it is given, so a new registry spec appears with no change here.
|
|
7
|
+
*/
|
|
8
|
+
export function pickerOptions(agents, isInstalled) {
|
|
9
|
+
const installed = agents.filter(isInstalled).sort(byLabel);
|
|
10
|
+
const missing = agents.filter((a) => !isInstalled(a)).sort(byLabel);
|
|
11
|
+
return [
|
|
12
|
+
...installed.map((a) => ({ value: a.name, label: a.label })),
|
|
13
|
+
...missing.map((a) => ({ value: a.name, label: `${a.label} (not installed)`, hint: `install: ${a.install}` })),
|
|
14
|
+
];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Show the picker until the user picks an installed agent (or one that installs and is then
|
|
18
|
+
* found on PATH) or cancels, at the picker or at the install question. A plain No, a printed
|
|
19
|
+
* installer or a failed install returns to the picker. With exactly one agent installed the
|
|
20
|
+
* cursor starts on it, so Enter keeps what bare `align` used to pick without asking.
|
|
21
|
+
*/
|
|
22
|
+
export async function chooseAgent(agents, d) {
|
|
23
|
+
for (;;) {
|
|
24
|
+
const installed = agents.filter(d.isInstalled);
|
|
25
|
+
const initial = installed.length === 1 ? installed[0].name : undefined;
|
|
26
|
+
const name = await d.select(pickerOptions(agents, d.isInstalled), initial);
|
|
27
|
+
const chosen = agents.find((a) => a.name === name);
|
|
28
|
+
if (!chosen)
|
|
29
|
+
return null;
|
|
30
|
+
if (d.isInstalled(chosen))
|
|
31
|
+
return chosen;
|
|
32
|
+
const outcome = await d.offer(chosen);
|
|
33
|
+
if (outcome === 'cancelled')
|
|
34
|
+
return null;
|
|
35
|
+
if (outcome === 'installed') {
|
|
36
|
+
if (d.isInstalled(chosen))
|
|
37
|
+
return chosen;
|
|
38
|
+
d.say(`${chosen.label} installed, but ${chosen.bin} is still not on your PATH. Open a new terminal, or pick another.`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=picker-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"picker-options.js","sourceRoot":"","sources":["../../../src/lib/launch/picker-options.ts"],"names":[],"mappings":"AAUA,2EAA2E;AAC3E,MAAM,OAAO,GAAG,CAAC,CAAc,EAAE,CAAc,EAAU,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEjH;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,MAA8B,EAAE,WAAwC;IACpG,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC3D,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpE,OAAO;QACL,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QAC5D,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,kBAAkB,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;KAC/G,CAAC;AACJ,CAAC;AAWD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAA8B,EAAE,CAAa;IAC7E,SAAS,CAAC;QACR,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;QACxE,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,CAAC;QAC3E,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACzB,IAAI,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC;YAAE,OAAO,MAAM,CAAC;QACzC,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,OAAO,KAAK,WAAW;YAAE,OAAO,IAAI,CAAC;QACzC,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;YAC5B,IAAI,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC;gBAAE,OAAO,MAAM,CAAC;YACzC,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,KAAK,mBAAmB,MAAM,CAAC,GAAG,mEAAmE,CAAC,CAAC;QACzH,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Writable } from 'node:stream';
|
|
2
|
+
import type { PickerOption } from './picker-options.js';
|
|
3
|
+
import type { LaunchAgentId } from './registry/types.js';
|
|
4
|
+
/** "Which coding agent?". Resolves null on cancel. `initial` is the row the cursor starts on. */
|
|
5
|
+
export declare function selectAgent(options: PickerOption[], initial: LaunchAgentId | undefined, output?: Writable): Promise<LaunchAgentId | null>;
|
|
6
|
+
/**
|
|
7
|
+
* A yes/no question with No preselected. true only on an explicit yes, false on anything else,
|
|
8
|
+
* null on Ctrl-C (which the picker treats as leaving it, not as a No).
|
|
9
|
+
*/
|
|
10
|
+
export declare function confirmDefaultNo(message: string, output?: Writable): Promise<boolean | null>;
|
|
11
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../src/lib/launch/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAOzD,iGAAiG;AACjG,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,aAAa,GAAG,SAAS,EAAE,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAS/I;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAKlG"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The two clack prompts behind the agent picker, shared by bare `align` and the wizard. clack is
|
|
3
|
+
* imported on use, never at module load, so the launch path pays nothing for it (cost rule).
|
|
4
|
+
*/
|
|
5
|
+
/** "Which coding agent?". Resolves null on cancel. `initial` is the row the cursor starts on. */
|
|
6
|
+
export async function selectAgent(options, initial, output) {
|
|
7
|
+
const clack = await import('@clack/prompts');
|
|
8
|
+
const answer = await clack.select({
|
|
9
|
+
message: 'Which coding agent should `align` open?',
|
|
10
|
+
options,
|
|
11
|
+
...(initial !== undefined ? { initialValue: initial } : {}),
|
|
12
|
+
...(output ? { output } : {}),
|
|
13
|
+
});
|
|
14
|
+
return clack.isCancel(answer) ? null : answer;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A yes/no question with No preselected. true only on an explicit yes, false on anything else,
|
|
18
|
+
* null on Ctrl-C (which the picker treats as leaving it, not as a No).
|
|
19
|
+
*/
|
|
20
|
+
export async function confirmDefaultNo(message, output) {
|
|
21
|
+
const clack = await import('@clack/prompts');
|
|
22
|
+
const answer = await clack.confirm({ message, initialValue: false, ...(output ? { output } : {}) });
|
|
23
|
+
if (clack.isCancel(answer))
|
|
24
|
+
return null;
|
|
25
|
+
return answer === true;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/lib/launch/prompts.ts"],"names":[],"mappings":"AAIA;;;GAGG;AAEH,iGAAiG;AACjG,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAuB,EAAE,OAAkC,EAAE,MAAiB;IAC9G,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC;QAChC,OAAO,EAAE,yCAAyC;QAClD,OAAO;QACP,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9B,CAAC,CAAC;IACH,OAAO,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,MAAwB,CAAC;AACnE,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAe,EAAE,MAAiB;IACvE,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACpG,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IACxC,OAAO,MAAM,KAAK,IAAI,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type QwenTrust } from './qwen-trust.js';
|
|
2
|
+
import { type AlignLocalState } from './strict-entry.js';
|
|
3
|
+
/** The system settings file Qwen would read with no help from align, and what it holds. */
|
|
4
|
+
export interface QwenSystemSettings {
|
|
5
|
+
path: string;
|
|
6
|
+
/** Its text; null when it does not exist (or is unreadable). */
|
|
7
|
+
text: string | null;
|
|
8
|
+
/** It exists but could not be read (a directory, no permission). */
|
|
9
|
+
unreadable: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface QwenProjectState extends AlignLocalState {
|
|
12
|
+
systemSettings: QwenSystemSettings;
|
|
13
|
+
trust: QwenTrust;
|
|
14
|
+
}
|
|
15
|
+
/** One launch-cache copy per SOURCE file, as for Gemini, so concurrent launches never share one. */
|
|
16
|
+
export declare const QWEN_COPY_PREFIX = "qwen-system-settings-";
|
|
17
|
+
export declare function qwenCopyName(source: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* What Qwen Code would already load here, in its merge order (qwen-code 0.25.0 mergeSettings:
|
|
20
|
+
* system-defaults, user, workspace, system): system-defaults, $QWEN_HOME or ~/.qwen settings,
|
|
21
|
+
* the project's .qwen/settings.json only when the folder is trusted (trust is off by default,
|
|
22
|
+
* which counts as trusted), and the system file. mcpServers merges SHALLOWLY with the system
|
|
23
|
+
* tier last (mergeStrategy "shallow_merge": `{...obj1, ...obj2}`), so the injected system copy
|
|
24
|
+
* replaces any align-local whole: a non-canonical one is overridden, never a conflict
|
|
25
|
+
* (verified: `qwen mcp list` with a user and a workspace align-local shows only align's).
|
|
26
|
+
*/
|
|
27
|
+
export declare function readQwenState(cwd: string, home: string, opts: {
|
|
28
|
+
localIsDefault: boolean;
|
|
29
|
+
}, env: Record<string, string | undefined>, platform: string): QwenProjectState;
|
|
30
|
+
//# sourceMappingURL=qwen-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qwen-state.d.ts","sourceRoot":"","sources":["../../../src/lib/launch/qwen-state.ts"],"names":[],"mappings":"AAGA,OAAO,EAA4E,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC3H,OAAO,EAAE,KAAK,eAAe,EAA6D,MAAM,mBAAmB,CAAC;AAEpH,2FAA2F;AAC3F,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,oEAAoE;IACpE,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD,cAAc,EAAE,kBAAkB,CAAC;IACnC,KAAK,EAAE,SAAS,CAAC;CAClB;AAED,oGAAoG;AACpG,eAAO,MAAM,gBAAgB,0BAA0B,CAAC;AAExD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnD;AAoBD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;IAAE,cAAc,EAAE,OAAO,CAAA;CAAE,EACjC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EACvC,QAAQ,EAAE,MAAM,GACf,gBAAgB,CAmBlB"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { qwenDir, qwenFolderTrust, qwenSystemDefaultsPath, qwenSystemSettingsPath } from './qwen-trust.js';
|
|
5
|
+
import { foldLayers, isCanonicalLocalEntry, parseJsonc } from './strict-entry.js';
|
|
6
|
+
/** One launch-cache copy per SOURCE file, as for Gemini, so concurrent launches never share one. */
|
|
7
|
+
export const QWEN_COPY_PREFIX = 'qwen-system-settings-';
|
|
8
|
+
export function qwenCopyName(source) {
|
|
9
|
+
return `${QWEN_COPY_PREFIX}${createHash('sha256').update(path.resolve(source)).digest('hex').slice(0, 12)}.json`;
|
|
10
|
+
}
|
|
11
|
+
function readSystem(file) {
|
|
12
|
+
try {
|
|
13
|
+
return { path: file, text: readFileSync(file, 'utf8'), unreadable: false };
|
|
14
|
+
}
|
|
15
|
+
catch (e) {
|
|
16
|
+
return { path: file, text: null, unreadable: e.code !== 'ENOENT' };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function readText(file) {
|
|
20
|
+
try {
|
|
21
|
+
return readFileSync(file, 'utf8');
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const layer = (file, text) => ({ file, servers: parseJsonc(text)?.['mcpServers'] });
|
|
28
|
+
/**
|
|
29
|
+
* What Qwen Code would already load here, in its merge order (qwen-code 0.25.0 mergeSettings:
|
|
30
|
+
* system-defaults, user, workspace, system): system-defaults, $QWEN_HOME or ~/.qwen settings,
|
|
31
|
+
* the project's .qwen/settings.json only when the folder is trusted (trust is off by default,
|
|
32
|
+
* which counts as trusted), and the system file. mcpServers merges SHALLOWLY with the system
|
|
33
|
+
* tier last (mergeStrategy "shallow_merge": `{...obj1, ...obj2}`), so the injected system copy
|
|
34
|
+
* replaces any align-local whole: a non-canonical one is overridden, never a conflict
|
|
35
|
+
* (verified: `qwen mcp list` with a user and a workspace align-local shows only align's).
|
|
36
|
+
*/
|
|
37
|
+
export function readQwenState(cwd, home, opts, env, platform) {
|
|
38
|
+
const system = readSystem(qwenSystemSettingsPath(env, platform));
|
|
39
|
+
const trust = qwenFolderTrust(cwd, home, env, platform);
|
|
40
|
+
const defaultsPath = env['QWEN_CODE_SYSTEM_DEFAULTS_PATH'] ? env['QWEN_CODE_SYSTEM_DEFAULTS_PATH'] : qwenSystemDefaultsPath(system.path, platform);
|
|
41
|
+
const userPath = path.join(qwenDir(home, env), 'settings.json');
|
|
42
|
+
const workspacePath = path.join(cwd, '.qwen', 'settings.json');
|
|
43
|
+
const layers = [
|
|
44
|
+
layer(defaultsPath, readText(defaultsPath)),
|
|
45
|
+
layer(userPath, readText(userPath)),
|
|
46
|
+
...(trust === 'trusted' || trust === 'off' ? [layer(workspacePath, readText(workspacePath))] : []),
|
|
47
|
+
layer(system.path, system.text),
|
|
48
|
+
];
|
|
49
|
+
const o = { ...opts, platform, host: 'mcpServers' };
|
|
50
|
+
const { overridden } = foldLayers(layers, o, () => true);
|
|
51
|
+
// Only the user's own `align` stands in for us; a canonical align-local is replaced whole anyway.
|
|
52
|
+
// Not the workspace's: Qwen holds a workspace server until the user approves it (`qwen mcp list`
|
|
53
|
+
// shows "Pending approval"), so a repo's `align` may not run at all.
|
|
54
|
+
const present = layers.some((l) => l.file !== workspacePath && isCanonicalLocalEntry(l.servers?.['align'], o));
|
|
55
|
+
return { present, overridden, systemSettings: system, trust };
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=qwen-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qwen-state.js","sourceRoot":"","sources":["../../../src/lib/launch/qwen-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether Qwen Code will run MCP servers in this folder. Like Gemini (it is a fork), Qwen skips
|
|
3
|
+
* MCP discovery in a folder it does not trust, so the injected align-local is off there too.
|
|
4
|
+
* - trusted / untrusted: what Qwen will decide.
|
|
5
|
+
* - off: folder trust is off, which is Qwen's DEFAULT (unlike Gemini), so nothing is disabled.
|
|
6
|
+
* - unknown: trustedFolders.json is unreadable or invalid.
|
|
7
|
+
*/
|
|
8
|
+
export type QwenTrust = 'trusted' | 'untrusted' | 'off' | 'unknown';
|
|
9
|
+
/** Qwen's own default system settings file, used when QWEN_CODE_SYSTEM_SETTINGS_PATH is unset (qwen-code 0.25.0 getSystemSettingsPath). */
|
|
10
|
+
export declare function qwenSystemSettingsPath(env: Record<string, string | undefined>, platform: string): string;
|
|
11
|
+
/** QWEN_CODE_SYSTEM_DEFAULTS_PATH, else `system-defaults.json` beside the system settings file. */
|
|
12
|
+
export declare function qwenSystemDefaultsPath(systemSettingsPath: string, platform: string): string;
|
|
13
|
+
/** $QWEN_HOME when set (the directory itself, not $QWEN_HOME/.qwen), else ~/.qwen. */
|
|
14
|
+
export declare function qwenDir(home: string, env: Record<string, string | undefined>): string;
|
|
15
|
+
/**
|
|
16
|
+
* Qwen Code 0.25.0's folder-trust verdict for `cwd`, read from its own files and never written
|
|
17
|
+
* (isWorkspaceTrusted, buildTrustPrecedenceRules, resolveTrustRule):
|
|
18
|
+
* - folder trust off (the default) means nothing is disabled;
|
|
19
|
+
* - else the DEEPEST matching rule in trustedFolders.json decides (TRUST_PARENT matches the
|
|
20
|
+
* rule's parent directory), an untrusted rule wins a tie, and no matching rule is untrusted.
|
|
21
|
+
* Qwen also takes a verdict from a connected IDE, which align cannot see (one extra line at most).
|
|
22
|
+
*/
|
|
23
|
+
export declare function qwenFolderTrust(cwd: string, home: string, env: Record<string, string | undefined>, platform: string): QwenTrust;
|
|
24
|
+
//# sourceMappingURL=qwen-trust.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qwen-trust.d.ts","sourceRoot":"","sources":["../../../src/lib/launch/qwen-trust.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,KAAK,GAAG,SAAS,CAAC;AAepE,2IAA2I;AAC3I,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKxG;AAED,mGAAmG;AACnG,wBAAgB,sBAAsB,CAAC,kBAAkB,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG3F;AAED,sFAAsF;AACtF,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,MAAM,CAErF;AAqCD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,CAsB/H"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { existsSync, readFileSync, realpathSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { parseJsonc } from './strict-entry.js';
|
|
4
|
+
const LEVELS = new Set(['TRUST_FOLDER', 'TRUST_PARENT', 'DO_NOT_TRUST']);
|
|
5
|
+
function readJson(file) {
|
|
6
|
+
try {
|
|
7
|
+
return parseJsonc(readFileSync(file, 'utf8'));
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
const pathFor = (platform) => (platform === 'win32' ? path.win32 : path.posix);
|
|
14
|
+
/** Qwen's own default system settings file, used when QWEN_CODE_SYSTEM_SETTINGS_PATH is unset (qwen-code 0.25.0 getSystemSettingsPath). */
|
|
15
|
+
export function qwenSystemSettingsPath(env, platform) {
|
|
16
|
+
if (env['QWEN_CODE_SYSTEM_SETTINGS_PATH'])
|
|
17
|
+
return env['QWEN_CODE_SYSTEM_SETTINGS_PATH'];
|
|
18
|
+
if (platform === 'darwin')
|
|
19
|
+
return '/Library/Application Support/QwenCode/settings.json';
|
|
20
|
+
if (platform === 'win32')
|
|
21
|
+
return 'C:\\ProgramData\\qwen-code\\settings.json';
|
|
22
|
+
return '/etc/qwen-code/settings.json';
|
|
23
|
+
}
|
|
24
|
+
/** QWEN_CODE_SYSTEM_DEFAULTS_PATH, else `system-defaults.json` beside the system settings file. */
|
|
25
|
+
export function qwenSystemDefaultsPath(systemSettingsPath, platform) {
|
|
26
|
+
const p = pathFor(platform);
|
|
27
|
+
return p.join(p.dirname(systemSettingsPath), 'system-defaults.json');
|
|
28
|
+
}
|
|
29
|
+
/** $QWEN_HOME when set (the directory itself, not $QWEN_HOME/.qwen), else ~/.qwen. */
|
|
30
|
+
export function qwenDir(home, env) {
|
|
31
|
+
return env['QWEN_HOME'] ? path.resolve(env['QWEN_HOME']) : path.join(home, '.qwen');
|
|
32
|
+
}
|
|
33
|
+
const folderTrustSetting = (s) => s?.['security']?.['folderTrust']?.['enabled'];
|
|
34
|
+
/** security.folderTrust.enabled, merged system-defaults < user < system; default OFF (isFolderTrustEnabled: `?? false`). */
|
|
35
|
+
function folderTrustEnabled(home, env, platform) {
|
|
36
|
+
const system = qwenSystemSettingsPath(env, platform);
|
|
37
|
+
const defaults = env['QWEN_CODE_SYSTEM_DEFAULTS_PATH'] ? env['QWEN_CODE_SYSTEM_DEFAULTS_PATH'] : qwenSystemDefaultsPath(system, platform);
|
|
38
|
+
let enabled = false;
|
|
39
|
+
for (const file of [defaults, path.join(qwenDir(home, env), 'settings.json'), system]) {
|
|
40
|
+
const v = folderTrustSetting(readJson(file));
|
|
41
|
+
if (typeof v === 'boolean')
|
|
42
|
+
enabled = v;
|
|
43
|
+
}
|
|
44
|
+
return enabled;
|
|
45
|
+
}
|
|
46
|
+
function realPath(p) {
|
|
47
|
+
try {
|
|
48
|
+
return existsSync(p) ? realpathSync(p) : p;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return p;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function normalize(p, platform) {
|
|
55
|
+
const abs = pathFor(platform).resolve(p);
|
|
56
|
+
return platform === 'win32' || platform === 'darwin' ? abs.toLowerCase() : abs;
|
|
57
|
+
}
|
|
58
|
+
/** How deep `rule` sits when it is `location` or an ancestor of it; -1 when it is neither. */
|
|
59
|
+
function matchingDepth(rule, location, platform) {
|
|
60
|
+
const p = pathFor(platform);
|
|
61
|
+
const rel = p.relative(rule, location);
|
|
62
|
+
if (rel.startsWith(`..${p.sep}`) || rel === '..' || p.isAbsolute(rel))
|
|
63
|
+
return -1;
|
|
64
|
+
return rule.split(p.sep).filter(Boolean).length;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Qwen Code 0.25.0's folder-trust verdict for `cwd`, read from its own files and never written
|
|
68
|
+
* (isWorkspaceTrusted, buildTrustPrecedenceRules, resolveTrustRule):
|
|
69
|
+
* - folder trust off (the default) means nothing is disabled;
|
|
70
|
+
* - else the DEEPEST matching rule in trustedFolders.json decides (TRUST_PARENT matches the
|
|
71
|
+
* rule's parent directory), an untrusted rule wins a tie, and no matching rule is untrusted.
|
|
72
|
+
* Qwen also takes a verdict from a connected IDE, which align cannot see (one extra line at most).
|
|
73
|
+
*/
|
|
74
|
+
export function qwenFolderTrust(cwd, home, env, platform) {
|
|
75
|
+
if (!folderTrustEnabled(home, env, platform))
|
|
76
|
+
return 'off';
|
|
77
|
+
const file = env['QWEN_CODE_TRUSTED_FOLDERS_PATH'] ? env['QWEN_CODE_TRUSTED_FOLDERS_PATH'] : path.join(qwenDir(home, env), 'trustedFolders.json');
|
|
78
|
+
if (!existsSync(file))
|
|
79
|
+
return 'untrusted';
|
|
80
|
+
const rules = readJson(file);
|
|
81
|
+
if (!rules || !Object.values(rules).every((v) => typeof v === 'string' && LEVELS.has(v)))
|
|
82
|
+
return 'unknown';
|
|
83
|
+
const p = pathFor(platform);
|
|
84
|
+
const location = normalize(realPath(cwd), platform);
|
|
85
|
+
let deepest = -1;
|
|
86
|
+
let verdict;
|
|
87
|
+
for (const [raw, level] of Object.entries(rules)) {
|
|
88
|
+
const effective = normalize(realPath(level === 'TRUST_PARENT' ? p.dirname(raw) : raw), platform);
|
|
89
|
+
const depth = matchingDepth(effective, location, platform);
|
|
90
|
+
if (depth < 0)
|
|
91
|
+
continue;
|
|
92
|
+
const v = level === 'DO_NOT_TRUST' ? 'untrusted' : 'trusted';
|
|
93
|
+
if (depth > deepest || (depth === deepest && v === 'untrusted')) {
|
|
94
|
+
deepest = depth;
|
|
95
|
+
verdict = v;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return verdict ?? 'untrusted';
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=qwen-trust.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qwen-trust.js","sourceRoot":"","sources":["../../../src/lib/launch/qwen-trust.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"amp.d.ts","sourceRoot":"","sources":["../../../../../src/lib/launch/registry/agents/amp.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,eAAO,MAAM,GAAG,EAAE,SAWjB,CAAC"}
|