copilot-hub 0.1.19 → 0.1.20

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "copilot-hub",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "description": "Copilot Hub CLI and runtime bundle",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -12,6 +12,7 @@ const engineExamplePath = path.join(repoRoot, "apps", "agent-engine", ".env.exam
12
12
  const controlPlaneEnvPath = path.join(repoRoot, "apps", "control-plane", ".env");
13
13
  const controlPlaneExamplePath = path.join(repoRoot, "apps", "control-plane", ".env.example");
14
14
  const TELEGRAM_TOKEN_PATTERN = /^\d{5,}:[A-Za-z0-9_-]{20,}$/;
15
+ const DEFAULT_CONTROL_PLANE_TOKEN_ENV = "HUB_TELEGRAM_TOKEN";
15
16
  const args = new Set(process.argv.slice(2));
16
17
  const requiredOnly = args.has("--required-only");
17
18
  await main();
@@ -26,9 +27,8 @@ async function main() {
26
27
  await configureRequiredTokens({ rl, controlPlaneLines });
27
28
  }
28
29
  else {
29
- await configureAll({ rl, engineLines, controlPlaneLines });
30
+ await configureAll({ rl, controlPlaneLines });
30
31
  console.log("\nSaved:");
31
- console.log(`- ${relativeFromRepo(engineEnvPath)}`);
32
32
  console.log(`- ${relativeFromRepo(controlPlaneEnvPath)}`);
33
33
  console.log("\nNext step:");
34
34
  console.log("1) npm run start");
@@ -42,7 +42,7 @@ async function main() {
42
42
  }
43
43
  async function configureRequiredTokens({ rl, controlPlaneLines }) {
44
44
  const controlPlaneMap = parseEnvMap(controlPlaneLines);
45
- const controlPlaneTokenEnvName = nonEmpty(controlPlaneMap.HUB_TELEGRAM_TOKEN_ENV, "HUB_TELEGRAM_TOKEN");
45
+ const controlPlaneTokenEnvName = nonEmpty(controlPlaneMap.HUB_TELEGRAM_TOKEN_ENV, DEFAULT_CONTROL_PLANE_TOKEN_ENV);
46
46
  setEnvValue(controlPlaneLines, "HUB_TELEGRAM_TOKEN_ENV", controlPlaneTokenEnvName);
47
47
  const postControlPlaneMap = parseEnvMap(controlPlaneLines);
48
48
  const currentToken = String(postControlPlaneMap[controlPlaneTokenEnvName] ?? "").trim();
@@ -54,35 +54,24 @@ async function configureRequiredTokens({ rl, controlPlaneLines }) {
54
54
  throw new Error("Missing required tokens and no interactive terminal. Run 'npm run configure'.");
55
55
  }
56
56
  console.log("Missing or invalid hub token. Please enter a valid Telegram bot token.");
57
- const value = await askRequiredTelegramToken(rl, `Token value for ${controlPlaneTokenEnvName} (control-plane)`);
57
+ const value = await askRequiredTelegramToken(rl, "Control-plane Telegram token");
58
58
  setEnvValue(controlPlaneLines, controlPlaneTokenEnvName, value);
59
59
  console.log("Required token saved.");
60
60
  }
61
- async function configureAll({ rl, engineLines, controlPlaneLines }) {
62
- const engineMap = parseEnvMap(engineLines);
61
+ async function configureAll({ rl, controlPlaneLines }) {
63
62
  const controlPlaneMap = parseEnvMap(controlPlaneLines);
64
- console.log("\nCopilot Hub token configuration\n");
65
- const controlPlaneTokenEnvDefault = nonEmpty(controlPlaneMap.HUB_TELEGRAM_TOKEN_ENV, "HUB_TELEGRAM_TOKEN");
66
- const controlPlaneTokenEnvName = await ask(rl, "control-plane token variable", controlPlaneTokenEnvDefault);
67
- setEnvValue(controlPlaneLines, "HUB_TELEGRAM_TOKEN_ENV", controlPlaneTokenEnvName);
68
- const currentControlPlaneToken = parseEnvMap(controlPlaneLines)[controlPlaneTokenEnvName] ?? "";
69
- const newControlPlaneToken = await ask(rl, `Token value for ${controlPlaneTokenEnvName} (control-plane, Enter to keep current)`, "");
63
+ console.log("\nCopilot Hub control-plane configuration\n");
64
+ const controlPlaneTokenEnvDefault = nonEmpty(controlPlaneMap.HUB_TELEGRAM_TOKEN_ENV, DEFAULT_CONTROL_PLANE_TOKEN_ENV);
65
+ setEnvValue(controlPlaneLines, "HUB_TELEGRAM_TOKEN_ENV", controlPlaneTokenEnvDefault);
66
+ const currentControlPlaneToken = String(parseEnvMap(controlPlaneLines)[controlPlaneTokenEnvDefault] ?? "").trim();
67
+ const newControlPlaneToken = currentControlPlaneToken
68
+ ? await askTelegramToken(rl, "Control-plane Telegram token (press Enter to keep current)", true)
69
+ : await askRequiredTelegramToken(rl, "Control-plane Telegram token");
70
70
  if (newControlPlaneToken) {
71
- setEnvValue(controlPlaneLines, controlPlaneTokenEnvName, newControlPlaneToken);
71
+ setEnvValue(controlPlaneLines, controlPlaneTokenEnvDefault, newControlPlaneToken);
72
72
  }
73
- else if (!currentControlPlaneToken) {
74
- console.log(`- No value set for ${controlPlaneTokenEnvName} yet.`);
75
- }
76
- const configureAgentToken = await askYesNo(rl, "Configure TELEGRAM_TOKEN_AGENT_1 now?", true);
77
- if (configureAgentToken) {
78
- const currentAgentToken = engineMap.TELEGRAM_TOKEN_AGENT_1 ?? "";
79
- const newAgentToken = await ask(rl, "Token value for TELEGRAM_TOKEN_AGENT_1 (agent-engine, Enter to keep current)", "");
80
- if (newAgentToken) {
81
- setEnvValue(engineLines, "TELEGRAM_TOKEN_AGENT_1", newAgentToken);
82
- }
83
- else if (!currentAgentToken) {
84
- console.log("- No value set for TELEGRAM_TOKEN_AGENT_1 yet.");
85
- }
73
+ else {
74
+ console.log("- Control-plane token left unchanged.");
86
75
  }
87
76
  }
88
77
  function ensureEnvFile(envPath, examplePath) {
@@ -157,14 +146,6 @@ function nonEmpty(value, fallback) {
157
146
  function escapeRegex(value) {
158
147
  return String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
159
148
  }
160
- async function ask(rl, label, fallback) {
161
- const value = await rl.question(`${label}${fallback ? ` [${fallback}]` : ""}: `);
162
- const normalized = String(value ?? "").trim();
163
- if (!normalized) {
164
- return String(fallback ?? "").trim();
165
- }
166
- return normalized;
167
- }
168
149
  async function askRequired(rl, label) {
169
150
  while (true) {
170
151
  const value = await rl.question(`${label}: `);
@@ -184,22 +165,18 @@ async function askRequiredTelegramToken(rl, label) {
184
165
  console.log("Token format looks invalid. Expected format like: 123456789:AA...");
185
166
  }
186
167
  }
187
- async function askYesNo(rl, label, defaultYes) {
188
- const suffix = defaultYes ? "[Y/n]" : "[y/N]";
189
- const answer = await rl.question(`${label} ${suffix}: `);
190
- const value = String(answer ?? "")
191
- .trim()
192
- .toLowerCase();
193
- if (!value) {
194
- return defaultYes;
195
- }
196
- if (value === "y" || value === "yes") {
197
- return true;
198
- }
199
- if (value === "n" || value === "no") {
200
- return false;
168
+ async function askTelegramToken(rl, label, allowEmpty) {
169
+ while (true) {
170
+ const value = await rl.question(`${label}: `);
171
+ const normalized = String(value ?? "").trim();
172
+ if (!normalized && allowEmpty) {
173
+ return "";
174
+ }
175
+ if (isUsableTelegramToken(normalized)) {
176
+ return normalized;
177
+ }
178
+ console.log("Token format looks invalid. Expected format like: 123456789:AA...");
201
179
  }
202
- return defaultYes;
203
180
  }
204
181
  function relativeFromRepo(filePath) {
205
182
  const relative = path.relative(repoRoot, filePath);
@@ -14,6 +14,7 @@ const engineExamplePath = path.join(repoRoot, "apps", "agent-engine", ".env.exam
14
14
  const controlPlaneEnvPath = path.join(repoRoot, "apps", "control-plane", ".env");
15
15
  const controlPlaneExamplePath = path.join(repoRoot, "apps", "control-plane", ".env.example");
16
16
  const TELEGRAM_TOKEN_PATTERN = /^\d{5,}:[A-Za-z0-9_-]{20,}$/;
17
+ const DEFAULT_CONTROL_PLANE_TOKEN_ENV = "HUB_TELEGRAM_TOKEN";
17
18
 
18
19
  const args = new Set(process.argv.slice(2));
19
20
  const requiredOnly = args.has("--required-only");
@@ -33,9 +34,8 @@ async function main() {
33
34
  if (requiredOnly) {
34
35
  await configureRequiredTokens({ rl, controlPlaneLines });
35
36
  } else {
36
- await configureAll({ rl, engineLines, controlPlaneLines });
37
+ await configureAll({ rl, controlPlaneLines });
37
38
  console.log("\nSaved:");
38
- console.log(`- ${relativeFromRepo(engineEnvPath)}`);
39
39
  console.log(`- ${relativeFromRepo(controlPlaneEnvPath)}`);
40
40
  console.log("\nNext step:");
41
41
  console.log("1) npm run start");
@@ -53,7 +53,7 @@ async function configureRequiredTokens({ rl, controlPlaneLines }) {
53
53
 
54
54
  const controlPlaneTokenEnvName = nonEmpty(
55
55
  controlPlaneMap.HUB_TELEGRAM_TOKEN_ENV,
56
- "HUB_TELEGRAM_TOKEN",
56
+ DEFAULT_CONTROL_PLANE_TOKEN_ENV,
57
57
  );
58
58
  setEnvValue(controlPlaneLines, "HUB_TELEGRAM_TOKEN_ENV", controlPlaneTokenEnvName);
59
59
 
@@ -72,55 +72,33 @@ async function configureRequiredTokens({ rl, controlPlaneLines }) {
72
72
  }
73
73
 
74
74
  console.log("Missing or invalid hub token. Please enter a valid Telegram bot token.");
75
- const value = await askRequiredTelegramToken(
76
- rl,
77
- `Token value for ${controlPlaneTokenEnvName} (control-plane)`,
78
- );
75
+ const value = await askRequiredTelegramToken(rl, "Control-plane Telegram token");
79
76
  setEnvValue(controlPlaneLines, controlPlaneTokenEnvName, value);
80
77
  console.log("Required token saved.");
81
78
  }
82
79
 
83
- async function configureAll({ rl, engineLines, controlPlaneLines }) {
84
- const engineMap = parseEnvMap(engineLines);
80
+ async function configureAll({ rl, controlPlaneLines }) {
85
81
  const controlPlaneMap = parseEnvMap(controlPlaneLines);
86
82
 
87
- console.log("\nCopilot Hub token configuration\n");
83
+ console.log("\nCopilot Hub control-plane configuration\n");
88
84
 
89
85
  const controlPlaneTokenEnvDefault = nonEmpty(
90
86
  controlPlaneMap.HUB_TELEGRAM_TOKEN_ENV,
91
- "HUB_TELEGRAM_TOKEN",
92
- );
93
- const controlPlaneTokenEnvName = await ask(
94
- rl,
95
- "control-plane token variable",
96
- controlPlaneTokenEnvDefault,
97
- );
98
- setEnvValue(controlPlaneLines, "HUB_TELEGRAM_TOKEN_ENV", controlPlaneTokenEnvName);
99
- const currentControlPlaneToken = parseEnvMap(controlPlaneLines)[controlPlaneTokenEnvName] ?? "";
100
- const newControlPlaneToken = await ask(
101
- rl,
102
- `Token value for ${controlPlaneTokenEnvName} (control-plane, Enter to keep current)`,
103
- "",
87
+ DEFAULT_CONTROL_PLANE_TOKEN_ENV,
104
88
  );
105
- if (newControlPlaneToken) {
106
- setEnvValue(controlPlaneLines, controlPlaneTokenEnvName, newControlPlaneToken);
107
- } else if (!currentControlPlaneToken) {
108
- console.log(`- No value set for ${controlPlaneTokenEnvName} yet.`);
109
- }
89
+ setEnvValue(controlPlaneLines, "HUB_TELEGRAM_TOKEN_ENV", controlPlaneTokenEnvDefault);
90
+ const currentControlPlaneToken = String(
91
+ parseEnvMap(controlPlaneLines)[controlPlaneTokenEnvDefault] ?? "",
92
+ ).trim();
110
93
 
111
- const configureAgentToken = await askYesNo(rl, "Configure TELEGRAM_TOKEN_AGENT_1 now?", true);
112
- if (configureAgentToken) {
113
- const currentAgentToken = engineMap.TELEGRAM_TOKEN_AGENT_1 ?? "";
114
- const newAgentToken = await ask(
115
- rl,
116
- "Token value for TELEGRAM_TOKEN_AGENT_1 (agent-engine, Enter to keep current)",
117
- "",
118
- );
119
- if (newAgentToken) {
120
- setEnvValue(engineLines, "TELEGRAM_TOKEN_AGENT_1", newAgentToken);
121
- } else if (!currentAgentToken) {
122
- console.log("- No value set for TELEGRAM_TOKEN_AGENT_1 yet.");
123
- }
94
+ const newControlPlaneToken = currentControlPlaneToken
95
+ ? await askTelegramToken(rl, "Control-plane Telegram token (press Enter to keep current)", true)
96
+ : await askRequiredTelegramToken(rl, "Control-plane Telegram token");
97
+
98
+ if (newControlPlaneToken) {
99
+ setEnvValue(controlPlaneLines, controlPlaneTokenEnvDefault, newControlPlaneToken);
100
+ } else {
101
+ console.log("- Control-plane token left unchanged.");
124
102
  }
125
103
  }
126
104
 
@@ -212,15 +190,6 @@ function escapeRegex(value) {
212
190
  return String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
213
191
  }
214
192
 
215
- async function ask(rl, label, fallback) {
216
- const value = await rl.question(`${label}${fallback ? ` [${fallback}]` : ""}: `);
217
- const normalized = String(value ?? "").trim();
218
- if (!normalized) {
219
- return String(fallback ?? "").trim();
220
- }
221
- return normalized;
222
- }
223
-
224
193
  async function askRequired(rl, label) {
225
194
  while (true) {
226
195
  const value = await rl.question(`${label}: `);
@@ -242,22 +211,18 @@ async function askRequiredTelegramToken(rl, label) {
242
211
  }
243
212
  }
244
213
 
245
- async function askYesNo(rl, label, defaultYes) {
246
- const suffix = defaultYes ? "[Y/n]" : "[y/N]";
247
- const answer = await rl.question(`${label} ${suffix}: `);
248
- const value = String(answer ?? "")
249
- .trim()
250
- .toLowerCase();
251
- if (!value) {
252
- return defaultYes;
253
- }
254
- if (value === "y" || value === "yes") {
255
- return true;
256
- }
257
- if (value === "n" || value === "no") {
258
- return false;
214
+ async function askTelegramToken(rl, label, allowEmpty) {
215
+ while (true) {
216
+ const value = await rl.question(`${label}: `);
217
+ const normalized = String(value ?? "").trim();
218
+ if (!normalized && allowEmpty) {
219
+ return "";
220
+ }
221
+ if (isUsableTelegramToken(normalized)) {
222
+ return normalized;
223
+ }
224
+ console.log("Token format looks invalid. Expected format like: 123456789:AA...");
259
225
  }
260
- return defaultYes;
261
226
  }
262
227
 
263
228
  function relativeFromRepo(filePath) {