@marcopeg/hal 1.0.32 → 1.0.34

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.
Files changed (101) hide show
  1. package/README.md +19 -44
  2. package/dist/bot/commands/loader.d.ts +1 -0
  3. package/dist/bot/commands/loader.d.ts.map +1 -1
  4. package/dist/bot/commands/loader.js +7 -0
  5. package/dist/bot/commands/loader.js.map +1 -1
  6. package/dist/bot/commands/message.d.ts.map +1 -1
  7. package/dist/bot/commands/message.js +1 -0
  8. package/dist/bot/commands/message.js.map +1 -1
  9. package/dist/bot/commands/npm/exec.d.ts +15 -0
  10. package/dist/bot/commands/npm/exec.d.ts.map +1 -0
  11. package/dist/bot/commands/npm/exec.js +66 -0
  12. package/dist/bot/commands/npm/exec.js.map +1 -0
  13. package/dist/bot/commands/npm/format.d.ts +11 -0
  14. package/dist/bot/commands/npm/format.d.ts.map +1 -0
  15. package/dist/bot/commands/npm/format.js +40 -0
  16. package/dist/bot/commands/npm/format.js.map +1 -0
  17. package/dist/bot/commands/npm/index.d.ts +5 -0
  18. package/dist/bot/commands/npm/index.d.ts.map +1 -0
  19. package/dist/bot/commands/npm/index.js +126 -0
  20. package/dist/bot/commands/npm/index.js.map +1 -0
  21. package/dist/bot/commands/npm/scripts.d.ts +18 -0
  22. package/dist/bot/commands/npm/scripts.d.ts.map +1 -0
  23. package/dist/bot/commands/npm/scripts.js +66 -0
  24. package/dist/bot/commands/npm/scripts.js.map +1 -0
  25. package/dist/bot.d.ts.map +1 -1
  26. package/dist/bot.js +6 -0
  27. package/dist/bot.js.map +1 -1
  28. package/dist/cli.js +207 -19
  29. package/dist/cli.js.map +1 -1
  30. package/dist/config.d.ts +40 -0
  31. package/dist/config.d.ts.map +1 -1
  32. package/dist/config.js +46 -2
  33. package/dist/config.js.map +1 -1
  34. package/dist/engine/adapters/copilot.d.ts.map +1 -1
  35. package/dist/engine/adapters/copilot.js +35 -1
  36. package/dist/engine/adapters/copilot.js.map +1 -1
  37. package/dist/wizard/analyzer.d.ts +17 -0
  38. package/dist/wizard/analyzer.d.ts.map +1 -0
  39. package/dist/wizard/analyzer.js +173 -0
  40. package/dist/wizard/analyzer.js.map +1 -0
  41. package/dist/wizard/config-builder.d.ts +15 -0
  42. package/dist/wizard/config-builder.d.ts.map +1 -0
  43. package/dist/wizard/config-builder.js +199 -0
  44. package/dist/wizard/config-builder.js.map +1 -0
  45. package/dist/wizard/confirm-and-write.d.ts +7 -0
  46. package/dist/wizard/confirm-and-write.d.ts.map +1 -0
  47. package/dist/wizard/confirm-and-write.js +135 -0
  48. package/dist/wizard/confirm-and-write.js.map +1 -0
  49. package/dist/wizard/engine-discovery.d.ts +8 -0
  50. package/dist/wizard/engine-discovery.d.ts.map +1 -0
  51. package/dist/wizard/engine-discovery.js +55 -0
  52. package/dist/wizard/engine-discovery.js.map +1 -0
  53. package/dist/wizard/index.d.ts +14 -0
  54. package/dist/wizard/index.d.ts.map +1 -0
  55. package/dist/wizard/index.js +116 -0
  56. package/dist/wizard/index.js.map +1 -0
  57. package/dist/wizard/runner.d.ts +16 -0
  58. package/dist/wizard/runner.d.ts.map +1 -0
  59. package/dist/wizard/runner.js +47 -0
  60. package/dist/wizard/runner.js.map +1 -0
  61. package/dist/wizard/steps/additional-users.d.ts +3 -0
  62. package/dist/wizard/steps/additional-users.d.ts.map +1 -0
  63. package/dist/wizard/steps/additional-users.js +57 -0
  64. package/dist/wizard/steps/additional-users.js.map +1 -0
  65. package/dist/wizard/steps/bot-token.d.ts +3 -0
  66. package/dist/wizard/steps/bot-token.d.ts.map +1 -0
  67. package/dist/wizard/steps/bot-token.js +130 -0
  68. package/dist/wizard/steps/bot-token.js.map +1 -0
  69. package/dist/wizard/steps/cwd.d.ts +3 -0
  70. package/dist/wizard/steps/cwd.d.ts.map +1 -0
  71. package/dist/wizard/steps/cwd.js +80 -0
  72. package/dist/wizard/steps/cwd.js.map +1 -0
  73. package/dist/wizard/steps/engine.d.ts +3 -0
  74. package/dist/wizard/steps/engine.d.ts.map +1 -0
  75. package/dist/wizard/steps/engine.js +118 -0
  76. package/dist/wizard/steps/engine.js.map +1 -0
  77. package/dist/wizard/steps/index.d.ts +5 -0
  78. package/dist/wizard/steps/index.d.ts.map +1 -0
  79. package/dist/wizard/steps/index.js +15 -0
  80. package/dist/wizard/steps/index.js.map +1 -0
  81. package/dist/wizard/steps/model.d.ts +3 -0
  82. package/dist/wizard/steps/model.d.ts.map +1 -0
  83. package/dist/wizard/steps/model.js +88 -0
  84. package/dist/wizard/steps/model.js.map +1 -0
  85. package/dist/wizard/steps/project-name.d.ts +3 -0
  86. package/dist/wizard/steps/project-name.d.ts.map +1 -0
  87. package/dist/wizard/steps/project-name.js +59 -0
  88. package/dist/wizard/steps/project-name.js.map +1 -0
  89. package/dist/wizard/steps/session.d.ts +3 -0
  90. package/dist/wizard/steps/session.d.ts.map +1 -0
  91. package/dist/wizard/steps/session.js +81 -0
  92. package/dist/wizard/steps/session.js.map +1 -0
  93. package/dist/wizard/steps/user-id.d.ts +3 -0
  94. package/dist/wizard/steps/user-id.d.ts.map +1 -0
  95. package/dist/wizard/steps/user-id.js +155 -0
  96. package/dist/wizard/steps/user-id.js.map +1 -0
  97. package/dist/wizard/types.d.ts +108 -0
  98. package/dist/wizard/types.d.ts.map +1 -0
  99. package/dist/wizard/types.js +2 -0
  100. package/dist/wizard/types.js.map +1 -0
  101. package/package.json +7 -2
@@ -0,0 +1,199 @@
1
+ import { stringify as stringifyYaml } from "yaml";
2
+ const DOCS_CONFIG = "https://github.com/marcopeg/hal/blob/main/docs/config/README.md";
3
+ /**
4
+ * Build the final config object by merging wizard results over the existing
5
+ * config (if any), then serialize it in the appropriate format.
6
+ */
7
+ export function buildConfigFromResults(ctx) {
8
+ const results = ctx.results;
9
+ const secretsMode = results.secretsMode ?? "env";
10
+ const projectEdits = ctx.results.projectEdits ?? {};
11
+ // Determine project key and name
12
+ const projectKey = results.projectKey ??
13
+ (ctx.existingConfig?.projects
14
+ ? Object.keys(ctx.existingConfig.projects)[0]
15
+ : undefined) ??
16
+ "prj1";
17
+ const projectName = results.projectName;
18
+ // Start from existing config or a fresh skeleton
19
+ const base = ctx.existingConfig
20
+ ? JSON.parse(JSON.stringify(ctx.existingConfig)) // deep clone
21
+ : {};
22
+ // Ensure projects map exists
23
+ if (!base.projects)
24
+ base.projects = {};
25
+ if (!base.projects[projectKey])
26
+ base.projects[projectKey] = {};
27
+ const project = base.projects[projectKey];
28
+ // Apply project name
29
+ if (projectEdits[projectKey]?.name) {
30
+ project.name = projectEdits[projectKey].name;
31
+ }
32
+ else if (projectName) {
33
+ project.name = projectName;
34
+ }
35
+ else {
36
+ // Do not force deletion for existing projects; only remove when explicitly reset in future.
37
+ if (!ctx.existingConfig)
38
+ delete project.name;
39
+ }
40
+ // Apply cwd
41
+ if (projectEdits[projectKey]?.cwd) {
42
+ project.cwd = projectEdits[projectKey].cwd;
43
+ }
44
+ else if (results.cwd) {
45
+ project.cwd = results.cwd;
46
+ }
47
+ // Apply cwd edits for any other projects
48
+ for (const [k, edit] of Object.entries(projectEdits)) {
49
+ if (!edit.cwd)
50
+ continue;
51
+ if (!base.projects[k])
52
+ base.projects[k] = {};
53
+ base.projects[k].cwd = edit.cwd;
54
+ if (edit.name && edit.name.trim() !== "") {
55
+ base.projects[k].name = edit.name;
56
+ }
57
+ }
58
+ // Engines enabled (providers) + default engine (globals)
59
+ if (Array.isArray(results.enabledEngines)) {
60
+ // Create a providers map that enables /engine switching.
61
+ // Use null so it stays lean; runtime CLI discovery can still populate names.
62
+ const enabled = results.enabledEngines;
63
+ base.providers = base.providers ?? {};
64
+ const providers = {};
65
+ for (const e of enabled)
66
+ providers[e] = null;
67
+ base.providers = providers;
68
+ }
69
+ if (results.engine || results.model || results.session !== undefined) {
70
+ base.globals = base.globals ?? {};
71
+ base.globals.engine = base.globals.engine ?? {};
72
+ const globalsEngine = base.globals.engine;
73
+ if (results.engine)
74
+ globalsEngine.name = results.engine;
75
+ if (results.model)
76
+ globalsEngine.model = results.model;
77
+ if (results.session !== undefined) {
78
+ globalsEngine.session = results.session;
79
+ }
80
+ // Keep project config lean: remove project.engine when it only duplicates globals
81
+ if (results.engine) {
82
+ const projects = base.projects ?? {};
83
+ for (const p of Object.values(projects)) {
84
+ if (!p.engine)
85
+ continue;
86
+ const pe = p.engine;
87
+ const sameName = pe.name === globalsEngine.name;
88
+ const sameModel = pe.model === globalsEngine.model;
89
+ const sameSession = pe.session === globalsEngine.session ||
90
+ pe.session === undefined;
91
+ if (sameName && sameModel && sameSession) {
92
+ delete p.engine;
93
+ }
94
+ }
95
+ }
96
+ }
97
+ // Secrets: bot token + user IDs can be inline or via .env placeholders
98
+ let envEntries;
99
+ const editedProjectKeys = Object.keys(projectEdits);
100
+ const tokenTargets = editedProjectKeys.length > 0
101
+ ? editedProjectKeys
102
+ : results.botToken
103
+ ? [projectKey]
104
+ : [];
105
+ for (const k of tokenTargets) {
106
+ if (!base.projects[k])
107
+ base.projects[k] = {};
108
+ const p = base.projects[k];
109
+ const token = projectEdits[k]?.botToken ??
110
+ (k === projectKey ? results.botToken : undefined);
111
+ if (!token)
112
+ continue;
113
+ if (!p.telegram)
114
+ p.telegram = {};
115
+ if (secretsMode === "inline") {
116
+ p.telegram.botToken = token;
117
+ continue;
118
+ }
119
+ // Prefer keeping an existing placeholder var name when present.
120
+ const existing = p.telegram.botToken;
121
+ let varName = null;
122
+ if (typeof existing === "string") {
123
+ const m = /^\$\{([^}]+)\}$/.exec(existing.trim());
124
+ if (m)
125
+ varName = m[1]?.trim() || null;
126
+ }
127
+ if (!varName) {
128
+ varName = `${k.replace(/[^A-Za-z0-9]+/g, "_").toUpperCase()}_TELEGRAM_TOKEN`;
129
+ }
130
+ // Intentional placeholder — not a template literal
131
+ p.telegram.botToken = String.raw `\${${varName}}`;
132
+ envEntries = { ...(envEntries ?? {}), [varName]: token };
133
+ }
134
+ // Apply user IDs to globals.access
135
+ const allUserIds = [];
136
+ if (results.userId)
137
+ allUserIds.push(results.userId);
138
+ if (Array.isArray(results.additionalUserIds)) {
139
+ allUserIds.push(...results.additionalUserIds);
140
+ }
141
+ if (allUserIds.length > 0) {
142
+ base.globals = base.globals ?? {};
143
+ base.globals.access = base.globals.access ?? {};
144
+ if (secretsMode === "inline") {
145
+ base.globals.access.allowedUserIds = allUserIds;
146
+ }
147
+ else {
148
+ const placeholders = [];
149
+ allUserIds.forEach((id, idx) => {
150
+ const key = idx === 0 ? "TELEGRAM_USER_ID" : `TELEGRAM_USER_ID_${idx + 1}`;
151
+ placeholders.push(`\${${key}}`);
152
+ envEntries = { ...(envEntries ?? {}), [key]: String(id) };
153
+ });
154
+ base.globals.access.allowedUserIds = placeholders;
155
+ }
156
+ }
157
+ // Serialize with fixed key order: providers, globals, projects
158
+ const format = ctx.existingConfigFormat ?? "yaml";
159
+ const targetPath = ctx.existingConfigPath ?? `${ctx.cwd}/hal.config.yaml`;
160
+ let content;
161
+ if (format === "yaml") {
162
+ content = buildYamlContent(base);
163
+ }
164
+ else {
165
+ const ordered = orderTopLevelKeys(base);
166
+ content = `${JSON.stringify(ordered, null, 2)}\n`;
167
+ }
168
+ return { content, targetPath, envEntries };
169
+ }
170
+ /** Top-level key order and blank line between sections. */
171
+ const TOP_LEVEL_ORDER = [
172
+ "providers",
173
+ "globals",
174
+ "projects",
175
+ ];
176
+ function orderTopLevelKeys(config) {
177
+ const out = {};
178
+ for (const key of TOP_LEVEL_ORDER) {
179
+ const v = config[key];
180
+ if (v !== undefined && v !== null)
181
+ out[key] = v;
182
+ }
183
+ return out;
184
+ }
185
+ function buildYamlContent(config) {
186
+ const header = [
187
+ "# HAL configuration",
188
+ `# Full config docs: ${DOCS_CONFIG}`,
189
+ "",
190
+ ].join("\n");
191
+ const ordered = orderTopLevelKeys(config);
192
+ const body = stringifyYaml(ordered, { indent: 2 });
193
+ // Insert blank line before each top-level key except the first
194
+ const withBlanks = body
195
+ .replace(/\n(globals:)/m, "\n\n$1")
196
+ .replace(/\n(projects:)/m, "\n\n$1");
197
+ return `${header}\n${withBlanks}`;
198
+ }
199
+ //# sourceMappingURL=config-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-builder.js","sourceRoot":"","sources":["../../src/wizard/config-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { WizardContext } from "./types.js";
2
+ /**
3
+ * Final wizard step: show summary, confirm, write config, offer to start.
4
+ * Stores `ctx.results.startBot = true` when the user wants to start.
5
+ */
6
+ export declare function runConfirmAndWrite(ctx: WizardContext): Promise<void>;
7
+ //# sourceMappingURL=confirm-and-write.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confirm-and-write.d.ts","sourceRoot":"","sources":["../../src/wizard/confirm-and-write.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAgG1E"}
@@ -0,0 +1,135 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { confirm, select } from "@clack/prompts";
4
+ import { resolveCustomEnvPaths } from "../config.js";
5
+ import { getEngine } from "../engine/index.js";
6
+ import { buildConfigFromResults } from "./config-builder.js";
7
+ import { guardCancel } from "./runner.js";
8
+ /**
9
+ * Final wizard step: show summary, confirm, write config, offer to start.
10
+ * Stores `ctx.results.startBot = true` when the user wants to start.
11
+ */
12
+ export async function runConfirmAndWrite(ctx) {
13
+ // Ask secrets mode before generating previews
14
+ const secretsMode = await select({
15
+ message: "Where should API keys and user IDs be stored?",
16
+ options: [
17
+ { value: "env", label: "Use .env variables (recommended)" },
18
+ { value: "inline", label: "Inline in config file" },
19
+ ],
20
+ });
21
+ guardCancel(secretsMode);
22
+ ctx.results.secretsMode = secretsMode;
23
+ const built = buildConfigFromResults(ctx);
24
+ console.log("\n─── Proposed configuration ──────────────────────────────\n");
25
+ console.log(built.content);
26
+ console.log("─────────────────────────────────────────────────────────\n");
27
+ if (built.envEntries && Object.keys(built.envEntries).length > 0) {
28
+ const envPath = pickEnvPath(ctx);
29
+ console.log(`Proposed ${envPath} entries:\n`);
30
+ for (const [k, v] of Object.entries(built.envEntries)) {
31
+ console.log(` ${k}=${v}`);
32
+ }
33
+ console.log("\n─────────────────────────────────────────────────────────\n");
34
+ }
35
+ const ok = await confirm({
36
+ message: built.envEntries && Object.keys(built.envEntries).length > 0
37
+ ? "Write config and .env changes?"
38
+ : "Write this configuration?",
39
+ });
40
+ guardCancel(ok);
41
+ if (!ok) {
42
+ console.log("Aborted. No files were written.");
43
+ process.exit(0);
44
+ }
45
+ // Write config file
46
+ writeFileSync(built.targetPath, built.content, "utf-8");
47
+ console.log(`\n Config written: ${built.targetPath}`);
48
+ // Write env entries
49
+ if (built.envEntries && Object.keys(built.envEntries).length > 0) {
50
+ const envPath = pickEnvPath(ctx);
51
+ upsertEnvFile(envPath, built.envEntries);
52
+ console.log(` Env updated: ${envPath}`);
53
+ }
54
+ // Create engine instructions file if missing
55
+ const engineName = ctx.results.engine;
56
+ if (engineName) {
57
+ try {
58
+ const engine = getEngine(engineName, undefined, "");
59
+ const instrFile = engine.instructionsFile();
60
+ const instrPath = join(ctx.cwd, instrFile);
61
+ if (!existsSync(instrPath)) {
62
+ writeFileSync(instrPath, "# Project Instructions\n\nAdd your project-specific instructions here.\n", "utf-8");
63
+ console.log(` Created: ${instrFile}`);
64
+ }
65
+ }
66
+ catch {
67
+ // engine lookup failed — not critical
68
+ }
69
+ }
70
+ console.log("");
71
+ const action = await select({
72
+ message: "What would you like to do next?",
73
+ options: [
74
+ { value: "start", label: "Start the bot now" },
75
+ { value: "exit", label: "Exit" },
76
+ ],
77
+ });
78
+ guardCancel(action);
79
+ if (action === "start") {
80
+ ctx.results.startBot = true;
81
+ }
82
+ else {
83
+ console.log("Setup complete! Run `npx @marcopeg/hal` when you're ready.");
84
+ process.exit(0);
85
+ }
86
+ }
87
+ function pickEnvPath(ctx) {
88
+ // Respect existing config's custom env path (task 041).
89
+ const configured = ctx.existingConfig?.env;
90
+ if (typeof configured === "string" && configured.trim() !== "") {
91
+ const { mainPath } = resolveCustomEnvPaths(ctx.cwd, configured);
92
+ return mainPath;
93
+ }
94
+ const envLocal = join(ctx.cwd, ".env.local");
95
+ const env = join(ctx.cwd, ".env");
96
+ if (existsSync(env))
97
+ return env;
98
+ if (existsSync(envLocal))
99
+ return envLocal;
100
+ return env;
101
+ }
102
+ function upsertEnvFile(envPath, entries) {
103
+ const content = existsSync(envPath) ? readFileSync(envPath, "utf-8") : "";
104
+ const lines = content.split(/\r?\n/);
105
+ const keys = new Set(Object.keys(entries));
106
+ const out = [];
107
+ const seen = new Set();
108
+ for (const line of lines) {
109
+ const m = /^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/.exec(line);
110
+ if (!m) {
111
+ out.push(line);
112
+ continue;
113
+ }
114
+ const key = m[1];
115
+ if (!keys.has(key)) {
116
+ out.push(line);
117
+ continue;
118
+ }
119
+ if (seen.has(key))
120
+ continue;
121
+ out.push(`${key}=${entries[key]}`);
122
+ seen.add(key);
123
+ }
124
+ for (const [k, v] of Object.entries(entries)) {
125
+ if (seen.has(k))
126
+ continue;
127
+ if (out.length > 0 && out[out.length - 1] !== "")
128
+ out.push("");
129
+ out.push(`${k}=${v}`);
130
+ }
131
+ // Ensure trailing newline
132
+ const final = out.join("\n").replace(/\n*$/, "\n");
133
+ writeFileSync(envPath, final, "utf-8");
134
+ }
135
+ //# sourceMappingURL=confirm-and-write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confirm-and-write.js","sourceRoot":"","sources":["../../src/wizard/confirm-and-write.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export type EngineName = "claude" | "copilot" | "codex" | "opencode" | "cursor" | "antigravity";
2
+ /**
3
+ * Async (non-blocking) engine availability discovery.
4
+ * Runs `<cmd> --version` checks in parallel (with a per-engine timeout).
5
+ */
6
+ export declare function discoverAvailableEngines(timeoutMsPerEngine?: number): Promise<EngineName[]>;
7
+ export declare function defaultEngineCommand(engine: EngineName): string;
8
+ //# sourceMappingURL=engine-discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine-discovery.d.ts","sourceRoot":"","sources":["../../src/wizard/engine-discovery.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,UAAU,GAClB,QAAQ,GACR,SAAS,GACT,OAAO,GACP,UAAU,GACV,QAAQ,GACR,aAAa,CAAC;AAiClB;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,kBAAkB,SAAO,GACxB,OAAO,CAAC,UAAU,EAAE,CAAC,CAiBvB;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAE/D"}
@@ -0,0 +1,55 @@
1
+ import { spawn } from "node:child_process";
2
+ const DEFAULT_ENGINE_COMMAND = {
3
+ claude: "claude",
4
+ copilot: "copilot",
5
+ codex: "codex",
6
+ opencode: "opencode",
7
+ cursor: "agent",
8
+ antigravity: "gemini",
9
+ };
10
+ function runVersionCheck(command, timeoutMs) {
11
+ return new Promise((resolve) => {
12
+ const proc = spawn(command, ["--version"], {
13
+ stdio: ["ignore", "ignore", "ignore"],
14
+ });
15
+ const timer = setTimeout(() => {
16
+ try {
17
+ proc.kill();
18
+ }
19
+ catch { }
20
+ resolve(false);
21
+ }, timeoutMs);
22
+ proc.on("error", () => {
23
+ clearTimeout(timer);
24
+ resolve(false);
25
+ });
26
+ proc.on("exit", (code) => {
27
+ clearTimeout(timer);
28
+ resolve(code === 0);
29
+ });
30
+ });
31
+ }
32
+ /**
33
+ * Async (non-blocking) engine availability discovery.
34
+ * Runs `<cmd> --version` checks in parallel (with a per-engine timeout).
35
+ */
36
+ export async function discoverAvailableEngines(timeoutMsPerEngine = 1500) {
37
+ const engines = [
38
+ "claude",
39
+ "copilot",
40
+ "codex",
41
+ "opencode",
42
+ "cursor",
43
+ "antigravity",
44
+ ];
45
+ const checks = await Promise.all(engines.map(async (e) => {
46
+ const cmd = DEFAULT_ENGINE_COMMAND[e];
47
+ const ok = await runVersionCheck(cmd, timeoutMsPerEngine);
48
+ return ok ? e : null;
49
+ }));
50
+ return checks.filter((x) => x !== null);
51
+ }
52
+ export function defaultEngineCommand(engine) {
53
+ return DEFAULT_ENGINE_COMMAND[engine];
54
+ }
55
+ //# sourceMappingURL=engine-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine-discovery.js","sourceRoot":"","sources":["../../src/wizard/engine-discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAU3C,MAAM,sBAAsB,GAA+B;IACzD,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,OAAO;IACf,WAAW,EAAE,QAAQ;CACtB,CAAC;AAEF,SAAS,eAAe,CAAC,OAAe,EAAE,SAAiB;IACzD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE;YACzC,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;SACtC,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,IAAI,CAAC;gBACH,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YACV,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC,EAAE,SAAS,CAAC,CAAC;QACd,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACpB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YACvB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,kBAAkB,GAAG,IAAI;IAEzB,MAAM,OAAO,GAAiB;QAC5B,QAAQ;QACR,SAAS;QACT,OAAO;QACP,UAAU;QACV,QAAQ;QACR,aAAa;KACd,CAAC;IACF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QACtB,MAAM,GAAG,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,EAAE,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;QAC1D,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACvB,CAAC,CAAC,CACH,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAmB,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAkB;IACrD,OAAO,sBAAsB,CAAC,MAAM,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { PrefillFlags } from "./types.js";
2
+ export type { PrefillFlags };
3
+ /**
4
+ * Main entry point for the interactive setup wizard.
5
+ *
6
+ * @param cwd Config directory (where hal.config.* lives or will be created).
7
+ * @param prefill Pre-fill values from CLI flags; their steps are skipped.
8
+ * @param reset When true, re-ask all questions even if values already exist.
9
+ * @returns true when the wizard completes and requests bot start; false otherwise.
10
+ */
11
+ export declare function startWizard(cwd: string, prefill: PrefillFlags, reset: boolean, options?: {
12
+ showBanner?: boolean;
13
+ }): Promise<boolean>;
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/wizard/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAiB,YAAY,EAAiB,MAAM,YAAY,CAAC;AAE7E,YAAY,EAAE,YAAY,EAAE,CAAC;AAsC7B;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,YAAY,EACrB,KAAK,EAAE,OAAO,EACd,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACjC,OAAO,CAAC,OAAO,CAAC,CA+ElB"}
@@ -0,0 +1,116 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { parseConfigContent, resolveConfigFile } from "../config.js";
3
+ import { runConfirmAndWrite } from "./confirm-and-write.js";
4
+ import { discoverAvailableEngines } from "./engine-discovery.js";
5
+ import { runWizard } from "./runner.js";
6
+ import { finalSteps, globalSteps, projectSteps } from "./steps/index.js";
7
+ function supportsAnsiColor(out = process.stdout, env = process.env) {
8
+ if (!out.isTTY)
9
+ return false;
10
+ if ("NO_COLOR" in env)
11
+ return false;
12
+ if ((env.TERM ?? "").toLowerCase() === "dumb")
13
+ return false;
14
+ return true;
15
+ }
16
+ function renderHalBanner(useColor) {
17
+ const subtitle = "MULTI-ENGINE TELEGRAM COMMAND DECK FOR AI CODING AGENTS";
18
+ const frame = "================================================================";
19
+ const accentStart = useColor ? "\u001b[31;1m" : "";
20
+ const accentEnd = useColor ? "\u001b[0m" : "";
21
+ return [
22
+ frame,
23
+ "",
24
+ " _ _ _ _ ",
25
+ "| | | | / \\ | | ",
26
+ "| |_| | / _ \\ | | ",
27
+ "| _ | / ___ \\ | |___ ",
28
+ "|_| |_| /_/ \\_\\ |_____|",
29
+ "",
30
+ `${accentStart}${subtitle}${accentEnd}`,
31
+ "",
32
+ frame,
33
+ ].join("\n");
34
+ }
35
+ function printWizardBanner(out = process.stdout) {
36
+ const banner = renderHalBanner(supportsAnsiColor(out));
37
+ out.write(`${banner}\n\n`);
38
+ }
39
+ /**
40
+ * Main entry point for the interactive setup wizard.
41
+ *
42
+ * @param cwd Config directory (where hal.config.* lives or will be created).
43
+ * @param prefill Pre-fill values from CLI flags; their steps are skipped.
44
+ * @param reset When true, re-ask all questions even if values already exist.
45
+ * @returns true when the wizard completes and requests bot start; false otherwise.
46
+ */
47
+ export async function startWizard(cwd, prefill, reset, options) {
48
+ if (options?.showBanner !== false) {
49
+ printWizardBanner();
50
+ }
51
+ let existingConfig = null;
52
+ let existingConfigPath = null;
53
+ let existingConfigFormat = null;
54
+ const resolved = resolveConfigFile(cwd, "hal.config");
55
+ if (resolved) {
56
+ existingConfigPath = resolved.path;
57
+ existingConfigFormat = resolved.format;
58
+ try {
59
+ const raw = readFileSync(resolved.path, "utf-8");
60
+ existingConfig = parseConfigContent(raw, resolved.format, resolved.path);
61
+ }
62
+ catch {
63
+ existingConfig = null;
64
+ }
65
+ }
66
+ const ctx = {
67
+ cwd,
68
+ existingConfig,
69
+ existingConfigPath,
70
+ existingConfigFormat,
71
+ prefill,
72
+ reset,
73
+ availableEnginesPromise: discoverAvailableEngines(),
74
+ targetProjectKeys: undefined,
75
+ currentProjectKey: null,
76
+ results: {},
77
+ };
78
+ // Identify projects to fill.
79
+ const existingKeys = Object.keys(existingConfig?.projects ?? {});
80
+ if (existingKeys.length === 0) {
81
+ // Fresh setup: default to a single project (key prj1); name is asked after cwd.
82
+ ctx.targetProjectKeys = ["prj1"];
83
+ ctx.results.projectKey = "prj1";
84
+ }
85
+ else {
86
+ // Existing config: fill only active projects (active !== false).
87
+ const keys = existingKeys.filter((k) => {
88
+ const p = existingConfig?.projects?.[k];
89
+ return p?.active !== false;
90
+ });
91
+ ctx.targetProjectKeys = keys.length > 0 ? keys : existingKeys;
92
+ // Primary project key drives which project is considered for "engine is configured" checks.
93
+ ctx.results.projectKey = ctx.targetProjectKeys[0];
94
+ }
95
+ // Global missing info (access list, enabled providers/default engine, etc.)
96
+ await runWizard(ctx, globalSteps);
97
+ // Project-scoped missing info (cwd, name, bot token, etc.)
98
+ const targets = ctx.targetProjectKeys ?? [];
99
+ if (targets.length > 1) {
100
+ process.stdout.write("\nFilling missing project settings...\n");
101
+ }
102
+ for (const projectKey of targets) {
103
+ ctx.currentProjectKey = projectKey;
104
+ if (targets.length > 1) {
105
+ process.stdout.write(`\nProject: ${projectKey}\n`);
106
+ }
107
+ await runWizard(ctx, projectSteps);
108
+ }
109
+ // Final global required info (user id)
110
+ ctx.currentProjectKey = null;
111
+ await runWizard(ctx, finalSteps);
112
+ await runConfirmAndWrite(ctx);
113
+ // confirm-and-write stores startBot = true when user chooses to start
114
+ return ctx.results.startBot === true;
115
+ }
116
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/wizard/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { WizardContext, WizardStep } from "./types.js";
2
+ /**
3
+ * Iterates through the step registry. For each step:
4
+ * - Skips if isConfigured() returns true AND --reset is false.
5
+ * - If shouldSkip() returns true (e.g. prefill provided), runs the step without prompting.
6
+ * - Shows progress ("Step N of M").
7
+ * - Calls run().
8
+ * - Handles Ctrl+C (isCancel) at any point via a thrown symbol that prompts catch.
9
+ */
10
+ export declare function runWizard(ctx: WizardContext, steps: WizardStep[]): Promise<void>;
11
+ /**
12
+ * Call after any @clack/prompts prompt returns a value to check for cancellation.
13
+ * Exits the process cleanly if the user pressed Ctrl+C.
14
+ */
15
+ export declare function guardCancel(value: unknown): void;
16
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/wizard/runner.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE5D;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAC7B,GAAG,EAAE,aAAa,EAClB,KAAK,EAAE,UAAU,EAAE,GAClB,OAAO,CAAC,IAAI,CAAC,CA8Bf;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAKhD"}
@@ -0,0 +1,47 @@
1
+ import { isCancel, outro } from "@clack/prompts";
2
+ /**
3
+ * Iterates through the step registry. For each step:
4
+ * - Skips if isConfigured() returns true AND --reset is false.
5
+ * - If shouldSkip() returns true (e.g. prefill provided), runs the step without prompting.
6
+ * - Shows progress ("Step N of M").
7
+ * - Calls run().
8
+ * - Handles Ctrl+C (isCancel) at any point via a thrown symbol that prompts catch.
9
+ */
10
+ export async function runWizard(ctx, steps) {
11
+ const promptingSteps = ctx.reset
12
+ ? steps
13
+ : steps.filter((s) => {
14
+ const skip = s.shouldSkip?.(ctx) ?? false;
15
+ if (skip)
16
+ return false;
17
+ if (s.isConfigured(ctx))
18
+ return false;
19
+ return true;
20
+ });
21
+ let shown = 0;
22
+ for (const step of steps) {
23
+ const skip = !ctx.reset && (step.shouldSkip?.(ctx) ?? false);
24
+ const configured = !ctx.reset && step.isConfigured(ctx);
25
+ if (configured)
26
+ continue;
27
+ if (skip) {
28
+ // Apply prefill silently (no progress line, no prompt expected).
29
+ await step.run(ctx);
30
+ continue;
31
+ }
32
+ shown += 1;
33
+ process.stdout.write(`\n[Step ${shown}/${promptingSteps.length}] ${step.label}\n`);
34
+ await step.run(ctx);
35
+ }
36
+ }
37
+ /**
38
+ * Call after any @clack/prompts prompt returns a value to check for cancellation.
39
+ * Exits the process cleanly if the user pressed Ctrl+C.
40
+ */
41
+ export function guardCancel(value) {
42
+ if (isCancel(value)) {
43
+ outro("Setup cancelled. No files were written.");
44
+ process.exit(0);
45
+ }
46
+ }
47
+ //# sourceMappingURL=runner.js.map