copilot-hub 0.1.28 → 0.1.29
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/apps/agent-engine/dist/config.js +11 -17
- package/apps/control-plane/.env.example +2 -3
- package/apps/control-plane/dist/config.js +11 -17
- package/apps/control-plane/dist/copilot-hub.js +16 -4
- package/apps/control-plane/dist/hub-token-config.js +37 -0
- package/apps/control-plane/dist/test/hub-token-config.test.js +46 -0
- package/package.json +1 -1
- package/packages/core/dist/env-config.d.ts +10 -0
- package/packages/core/dist/env-config.js +66 -0
- package/packages/core/dist/env-config.js.map +1 -0
- package/packages/core/dist/index.d.ts +2 -1
- package/packages/core/dist/index.js +2 -1
- package/packages/core/dist/index.js.map +1 -1
- package/packages/core/dist/workspace-paths.d.ts +12 -1
- package/packages/core/dist/workspace-paths.js +30 -6
- package/packages/core/dist/workspace-paths.js.map +1 -1
- package/packages/core/package.json +4 -0
- package/scripts/dist/configure.mjs +21 -7
- package/scripts/dist/daemon.mjs +17 -0
- package/scripts/src/configure.mts +27 -15
- package/scripts/src/daemon.mts +28 -0
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
|
-
import dotenv from "dotenv";
|
|
5
4
|
import { createWorkspaceBoundaryPolicy, assertWorkspaceAllowed, parseWorkspaceAllowedRoots, } from "@copilot-hub/core/workspace-policy";
|
|
6
5
|
import { parseTurnActivityTimeoutSetting } from "@copilot-hub/core/codex-app-utils";
|
|
7
|
-
import {
|
|
6
|
+
import { loadCopilotHubEnvironment } from "@copilot-hub/core";
|
|
7
|
+
import { resolveOptionalPathFromBase, resolvePathFromBase } from "@copilot-hub/core/config-paths";
|
|
8
8
|
import { getDefaultExternalWorkspaceBasePath, getKernelRootPath, } from "@copilot-hub/core/workspace-paths";
|
|
9
|
-
const
|
|
9
|
+
const loadedEnvironment = loadEnvironment();
|
|
10
|
+
const envBaseDir = loadedEnvironment.baseDir;
|
|
11
|
+
const envFilePath = loadedEnvironment.envPath;
|
|
12
|
+
const envFileValues = loadedEnvironment.fileValues;
|
|
13
|
+
const envOverrideKeys = loadedEnvironment.overriddenKeys;
|
|
10
14
|
const kernelRootPath = getKernelRootPath();
|
|
11
15
|
const configuredDefaultWorkspaceRoot = String(process.env.DEFAULT_WORKSPACE_ROOT ?? "").trim();
|
|
12
16
|
const defaultWorkspaceRoot = resolveWorkspaceRoot(configuredDefaultWorkspaceRoot || getDefaultExternalWorkspaceBasePath(kernelRootPath));
|
|
@@ -85,6 +89,9 @@ const defaultAllowedChatIds = new Set((process.env.TELEGRAM_ALLOWED_CHAT_IDS ??
|
|
|
85
89
|
fs.mkdirSync(dataDir, { recursive: true });
|
|
86
90
|
export const config = {
|
|
87
91
|
envBaseDir,
|
|
92
|
+
envFilePath,
|
|
93
|
+
envFileValues,
|
|
94
|
+
envOverrideKeys,
|
|
88
95
|
defaultProviderKind,
|
|
89
96
|
providerDefaults: {
|
|
90
97
|
defaultKind: defaultProviderKind,
|
|
@@ -125,22 +132,9 @@ export const config = {
|
|
|
125
132
|
defaultAllowedChatIds,
|
|
126
133
|
};
|
|
127
134
|
function loadEnvironment() {
|
|
128
|
-
|
|
129
|
-
const resolvedEnvPath = configuredEnvPath ? path.resolve(configuredEnvPath) : "";
|
|
130
|
-
const baseDir = resolveConfigBaseDir({
|
|
131
|
-
configuredBaseDir: process.env.COPILOT_HUB_ENV_BASE_DIR,
|
|
132
|
-
configuredEnvPath: resolvedEnvPath,
|
|
135
|
+
return loadCopilotHubEnvironment({
|
|
133
136
|
cwd: process.cwd(),
|
|
134
137
|
});
|
|
135
|
-
if (configuredEnvPath) {
|
|
136
|
-
process.env.COPILOT_HUB_ENV_PATH = resolvedEnvPath;
|
|
137
|
-
dotenv.config({ path: resolvedEnvPath });
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
dotenv.config();
|
|
141
|
-
}
|
|
142
|
-
process.env.COPILOT_HUB_ENV_BASE_DIR = baseDir;
|
|
143
|
-
return baseDir;
|
|
144
138
|
}
|
|
145
139
|
function resolveCodexBin(rawValue) {
|
|
146
140
|
const value = String(rawValue ?? "").trim();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
HUB_TELEGRAM_TOKEN_ENV=HUB_TELEGRAM_TOKEN_FILE
|
|
2
|
+
HUB_TELEGRAM_TOKEN_FILE=123456:replace_me
|
|
3
3
|
HUB_ID=copilot_hub
|
|
4
4
|
HUB_NAME=Copilot Hub
|
|
5
5
|
# Optional. If empty, defaults to Desktop/copilot_workspaces (Windows/macOS/Linux)
|
|
@@ -21,4 +21,3 @@ CODEX_SANDBOX=danger-full-access
|
|
|
21
21
|
CODEX_APPROVAL_POLICY=never
|
|
22
22
|
TURN_ACTIVITY_TIMEOUT_MS=0
|
|
23
23
|
MAX_THREAD_MESSAGES=200
|
|
24
|
-
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
|
-
import
|
|
4
|
+
import { loadCopilotHubEnvironment } from "@copilot-hub/core";
|
|
5
5
|
import { parseTurnActivityTimeoutSetting } from "@copilot-hub/core/codex-app-utils";
|
|
6
|
-
import {
|
|
6
|
+
import { resolveOptionalPathFromBase, resolvePathFromBase } from "@copilot-hub/core/config-paths";
|
|
7
7
|
import { createWorkspaceBoundaryPolicy, assertWorkspaceAllowed, parseWorkspaceAllowedRoots, } from "@copilot-hub/core/workspace-policy";
|
|
8
8
|
import { normalizeAdminBotId, normalizeAdminTokenEnv } from "./kernel/admin-contract.js";
|
|
9
9
|
import { getDefaultExternalWorkspaceBasePath, getKernelRootPath, } from "@copilot-hub/core/workspace-paths";
|
|
10
|
-
const
|
|
10
|
+
const loadedEnvironment = loadEnvironment();
|
|
11
|
+
const envBaseDir = loadedEnvironment.baseDir;
|
|
12
|
+
const envFilePath = loadedEnvironment.envPath;
|
|
13
|
+
const envFileValues = loadedEnvironment.fileValues;
|
|
14
|
+
const envOverrideKeys = loadedEnvironment.overriddenKeys;
|
|
11
15
|
const kernelRootPath = getKernelRootPath();
|
|
12
16
|
const configuredDefaultWorkspaceRoot = String(process.env.DEFAULT_WORKSPACE_ROOT ?? "").trim();
|
|
13
17
|
const defaultWorkspaceRoot = resolveWorkspaceRoot(configuredDefaultWorkspaceRoot || getDefaultExternalWorkspaceBasePath(kernelRootPath));
|
|
@@ -89,6 +93,9 @@ const defaultAllowedChatIds = new Set((process.env.TELEGRAM_ALLOWED_CHAT_IDS ??
|
|
|
89
93
|
fs.mkdirSync(dataDir, { recursive: true });
|
|
90
94
|
export const config = {
|
|
91
95
|
envBaseDir,
|
|
96
|
+
envFilePath,
|
|
97
|
+
envFileValues,
|
|
98
|
+
envOverrideKeys,
|
|
92
99
|
defaultProviderKind,
|
|
93
100
|
providerDefaults: {
|
|
94
101
|
defaultKind: defaultProviderKind,
|
|
@@ -132,22 +139,9 @@ export const config = {
|
|
|
132
139
|
defaultAllowedChatIds,
|
|
133
140
|
};
|
|
134
141
|
function loadEnvironment() {
|
|
135
|
-
|
|
136
|
-
const resolvedEnvPath = configuredEnvPath ? path.resolve(configuredEnvPath) : "";
|
|
137
|
-
const baseDir = resolveConfigBaseDir({
|
|
138
|
-
configuredBaseDir: process.env.COPILOT_HUB_ENV_BASE_DIR,
|
|
139
|
-
configuredEnvPath: resolvedEnvPath,
|
|
142
|
+
return loadCopilotHubEnvironment({
|
|
140
143
|
cwd: process.cwd(),
|
|
141
144
|
});
|
|
142
|
-
if (configuredEnvPath) {
|
|
143
|
-
process.env.COPILOT_HUB_ENV_PATH = resolvedEnvPath;
|
|
144
|
-
dotenv.config({ path: resolvedEnvPath });
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
dotenv.config();
|
|
148
|
-
}
|
|
149
|
-
process.env.COPILOT_HUB_ENV_BASE_DIR = baseDir;
|
|
150
|
-
return baseDir;
|
|
151
145
|
}
|
|
152
146
|
function resolveCodexBin(rawValue) {
|
|
153
147
|
const value = String(rawValue ?? "").trim();
|
|
@@ -3,16 +3,20 @@ import { BotRuntime } from "@copilot-hub/core/bot-runtime";
|
|
|
3
3
|
import { config } from "./config.js";
|
|
4
4
|
import { assertWorkspaceAllowed } from "@copilot-hub/core/workspace-policy";
|
|
5
5
|
import { createChannelAdapter } from "./channels/channel-factory.js";
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
6
|
+
import { isUsableTelegramToken, resolveHubTelegramToken } from "./hub-token-config.js";
|
|
7
|
+
const tokenResolution = resolveHubTelegramToken({
|
|
8
|
+
env: process.env,
|
|
9
|
+
envFileValues: config.envFileValues,
|
|
10
|
+
});
|
|
11
|
+
const tokenEnvName = tokenResolution.tokenEnvName;
|
|
12
|
+
const hubToken = tokenResolution.token;
|
|
9
13
|
if (!hubToken) {
|
|
10
14
|
throw new Error([
|
|
11
15
|
`Hub Telegram token is missing (${tokenEnvName}).`,
|
|
12
16
|
"Set this token to start copilot-hub.",
|
|
13
17
|
].join("\n"));
|
|
14
18
|
}
|
|
15
|
-
if (!
|
|
19
|
+
if (!isUsableTelegramToken(hubToken)) {
|
|
16
20
|
throw new Error([
|
|
17
21
|
`Hub Telegram token in ${tokenEnvName} is invalid.`,
|
|
18
22
|
"Run 'copilot-hub configure' and paste a real BotFather token.",
|
|
@@ -73,6 +77,14 @@ const runtime = new BotRuntime({
|
|
|
73
77
|
let shuttingDown = false;
|
|
74
78
|
await bootstrap();
|
|
75
79
|
async function bootstrap() {
|
|
80
|
+
for (const warning of tokenResolution.warnings) {
|
|
81
|
+
console.warn(`[copilot_hub] ${warning}`);
|
|
82
|
+
}
|
|
83
|
+
if (config.envOverrideKeys.includes("HUB_TELEGRAM_TOKEN_ENV") ||
|
|
84
|
+
config.envOverrideKeys.includes(tokenEnvName)) {
|
|
85
|
+
console.warn(`[copilot_hub] Config file '${config.envFilePath ?? ".env"}' overrode a pre-existing process environment value for the hub token settings.`);
|
|
86
|
+
}
|
|
87
|
+
console.log(`[copilot_hub] using hub Telegram token variable '${tokenEnvName}' from ${tokenResolution.source === "env_file" ? "config file" : "process environment"}.`);
|
|
76
88
|
await runtime.startChannels();
|
|
77
89
|
console.log(`[copilot_hub] online as '${hubId}' on workspace '${hubWorkspaceRoot}'.`);
|
|
78
90
|
registerSignals();
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const DEFAULT_HUB_TELEGRAM_TOKEN_ENV = "HUB_TELEGRAM_TOKEN_FILE";
|
|
2
|
+
const LEGACY_HUB_TELEGRAM_TOKEN_ENV = "HUB_TELEGRAM_TOKEN";
|
|
3
|
+
const TELEGRAM_TOKEN_PATTERN = /^\d{5,}:[A-Za-z0-9_-]{20,}$/;
|
|
4
|
+
export function resolveHubTelegramToken({ env = process.env, envFileValues = {}, } = {}) {
|
|
5
|
+
const fileTokenEnvName = String(envFileValues.HUB_TELEGRAM_TOKEN_ENV ?? "").trim();
|
|
6
|
+
const processTokenEnvName = String(env.HUB_TELEGRAM_TOKEN_ENV ?? "").trim();
|
|
7
|
+
const tokenEnvName = fileTokenEnvName || processTokenEnvName || DEFAULT_HUB_TELEGRAM_TOKEN_ENV;
|
|
8
|
+
const fileToken = String(envFileValues[tokenEnvName] ?? "").trim();
|
|
9
|
+
const processToken = String(env[tokenEnvName] ?? "").trim();
|
|
10
|
+
const token = fileToken || processToken;
|
|
11
|
+
const warnings = [];
|
|
12
|
+
if (fileTokenEnvName && processTokenEnvName && fileTokenEnvName !== processTokenEnvName) {
|
|
13
|
+
warnings.push(`Config file selects hub token variable '${fileTokenEnvName}', overriding pre-existing process env selector '${processTokenEnvName}'.`);
|
|
14
|
+
}
|
|
15
|
+
if (tokenEnvName === LEGACY_HUB_TELEGRAM_TOKEN_ENV) {
|
|
16
|
+
warnings.push(`Hub token variable '${LEGACY_HUB_TELEGRAM_TOKEN_ENV}' is deprecated. Run 'copilot-hub configure' to migrate to '${DEFAULT_HUB_TELEGRAM_TOKEN_ENV}'.`);
|
|
17
|
+
}
|
|
18
|
+
if (fileToken && processToken && fileToken !== processToken) {
|
|
19
|
+
const detail = isUsableTelegramToken(fileToken)
|
|
20
|
+
? `Using the token saved in the config file for '${tokenEnvName}' instead of the conflicting process environment value.`
|
|
21
|
+
: `Config file value for '${tokenEnvName}' overrides the conflicting process environment value.`;
|
|
22
|
+
warnings.push(detail);
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
tokenEnvName,
|
|
26
|
+
token,
|
|
27
|
+
source: fileToken ? "env_file" : "process_env",
|
|
28
|
+
warnings,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export function isUsableTelegramToken(value) {
|
|
32
|
+
const token = String(value ?? "").trim();
|
|
33
|
+
if (!token || token.toLowerCase().includes("replace_me")) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
return TELEGRAM_TOKEN_PATTERN.test(token);
|
|
37
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
let configPromise = null;
|
|
4
|
+
async function loadConfig() {
|
|
5
|
+
if (!configPromise) {
|
|
6
|
+
const specifier = ["..", "hub-token-config.js"].join("/");
|
|
7
|
+
configPromise = import(specifier);
|
|
8
|
+
}
|
|
9
|
+
return configPromise;
|
|
10
|
+
}
|
|
11
|
+
test("resolveHubTelegramToken prefers the config file token over a conflicting process env token", async () => {
|
|
12
|
+
const { resolveHubTelegramToken } = await loadConfig();
|
|
13
|
+
const result = resolveHubTelegramToken({
|
|
14
|
+
env: {
|
|
15
|
+
HUB_TELEGRAM_TOKEN_ENV: "HUB_TELEGRAM_TOKEN",
|
|
16
|
+
HUB_TELEGRAM_TOKEN: "123456:invalid_process_value_ABCDEFGHIJKLM",
|
|
17
|
+
},
|
|
18
|
+
envFileValues: {
|
|
19
|
+
HUB_TELEGRAM_TOKEN_ENV: "HUB_TELEGRAM_TOKEN",
|
|
20
|
+
HUB_TELEGRAM_TOKEN: "123456:valid_file_value_ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
assert.equal(result.tokenEnvName, "HUB_TELEGRAM_TOKEN");
|
|
24
|
+
assert.equal(result.source, "env_file");
|
|
25
|
+
assert.equal(result.token, "123456:valid_file_value_ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
|
26
|
+
assert.match(result.warnings.join("\n"), /deprecated/i);
|
|
27
|
+
});
|
|
28
|
+
test("resolveHubTelegramToken uses the dedicated file token variable by default", async () => {
|
|
29
|
+
const { resolveHubTelegramToken } = await loadConfig();
|
|
30
|
+
const result = resolveHubTelegramToken({
|
|
31
|
+
env: {},
|
|
32
|
+
envFileValues: {
|
|
33
|
+
HUB_TELEGRAM_TOKEN_ENV: "HUB_TELEGRAM_TOKEN_FILE",
|
|
34
|
+
HUB_TELEGRAM_TOKEN_FILE: "123456:valid_file_value_ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
assert.equal(result.tokenEnvName, "HUB_TELEGRAM_TOKEN_FILE");
|
|
38
|
+
assert.equal(result.source, "env_file");
|
|
39
|
+
assert.equal(result.warnings.length, 0);
|
|
40
|
+
});
|
|
41
|
+
test("isUsableTelegramToken recognizes valid telegram token formats", async () => {
|
|
42
|
+
const { isUsableTelegramToken } = await loadConfig();
|
|
43
|
+
assert.equal(isUsableTelegramToken("123456:valid_file_value_ABCDEFGHIJKLMNOPQRSTUVWXYZ"), true);
|
|
44
|
+
assert.equal(isUsableTelegramToken("123456:replace_me"), false);
|
|
45
|
+
assert.equal(isUsableTelegramToken(""), false);
|
|
46
|
+
});
|
package/package.json
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface LoadedCopilotHubEnvironment {
|
|
2
|
+
baseDir: string;
|
|
3
|
+
envPath: string | null;
|
|
4
|
+
fileValues: Record<string, string>;
|
|
5
|
+
overriddenKeys: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare function loadCopilotHubEnvironment({ env, cwd, }?: {
|
|
8
|
+
env?: NodeJS.ProcessEnv;
|
|
9
|
+
cwd?: string;
|
|
10
|
+
}): LoadedCopilotHubEnvironment;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import dotenv from "dotenv";
|
|
5
|
+
import { resolveConfigBaseDir } from "./config-paths.js";
|
|
6
|
+
export function loadCopilotHubEnvironment({ env = process.env, cwd = process.cwd(), } = {}) {
|
|
7
|
+
const configuredEnvPath = String(env.COPILOT_HUB_ENV_PATH ?? "").trim();
|
|
8
|
+
const resolvedEnvPath = configuredEnvPath ? path.resolve(configuredEnvPath) : "";
|
|
9
|
+
const discoveredEnvPath = resolvedEnvPath || resolveDefaultEnvPath(cwd);
|
|
10
|
+
const baseDir = resolveConfigBaseDir({
|
|
11
|
+
configuredBaseDir: env.COPILOT_HUB_ENV_BASE_DIR,
|
|
12
|
+
configuredEnvPath: discoveredEnvPath,
|
|
13
|
+
cwd,
|
|
14
|
+
});
|
|
15
|
+
const fileValues = loadEnvFileValues(discoveredEnvPath);
|
|
16
|
+
const overriddenKeys = applyEnvFileValues(env, fileValues);
|
|
17
|
+
if (resolvedEnvPath) {
|
|
18
|
+
env.COPILOT_HUB_ENV_PATH = resolvedEnvPath;
|
|
19
|
+
}
|
|
20
|
+
env.COPILOT_HUB_ENV_BASE_DIR = baseDir;
|
|
21
|
+
return {
|
|
22
|
+
baseDir,
|
|
23
|
+
envPath: discoveredEnvPath || null,
|
|
24
|
+
fileValues,
|
|
25
|
+
overriddenKeys,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function resolveDefaultEnvPath(cwd) {
|
|
29
|
+
const candidate = path.resolve(String(cwd ?? process.cwd()), ".env");
|
|
30
|
+
return fs.existsSync(candidate) ? candidate : "";
|
|
31
|
+
}
|
|
32
|
+
function loadEnvFileValues(filePath) {
|
|
33
|
+
if (!filePath || !fs.existsSync(filePath)) {
|
|
34
|
+
return {};
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
const raw = fs.readFileSync(filePath, "utf8");
|
|
38
|
+
return normalizeEnvMap(dotenv.parse(raw));
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return {};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function applyEnvFileValues(env, fileValues) {
|
|
45
|
+
const overriddenKeys = [];
|
|
46
|
+
for (const [key, value] of Object.entries(fileValues)) {
|
|
47
|
+
const previousValue = String(env[key] ?? "");
|
|
48
|
+
if (previousValue && previousValue !== value) {
|
|
49
|
+
overriddenKeys.push(key);
|
|
50
|
+
}
|
|
51
|
+
env[key] = value;
|
|
52
|
+
}
|
|
53
|
+
return overriddenKeys.sort();
|
|
54
|
+
}
|
|
55
|
+
function normalizeEnvMap(value) {
|
|
56
|
+
const output = {};
|
|
57
|
+
for (const [key, entry] of Object.entries(value ?? {})) {
|
|
58
|
+
const normalizedKey = String(key ?? "").trim();
|
|
59
|
+
if (!normalizedKey) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
output[normalizedKey] = String(entry ?? "").trim();
|
|
63
|
+
}
|
|
64
|
+
return output;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=env-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-config.js","sourceRoot":"","sources":["../src/env-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export { createWorkspaceBoundaryPolicy, assertWorkspaceAllowed, isPathInside, normalizeAbsolutePath, parseWorkspaceAllowedRoots, } from "./workspace-policy.js";
|
|
2
2
|
export { normalizeThreadId } from "./thread-id.js";
|
|
3
3
|
export { createProjectFingerprint } from "./project-fingerprint.js";
|
|
4
|
-
export { DEFAULT_EXTERNAL_WORKSPACES_DIRNAME, getKernelRootPath, getDefaultExternalWorkspaceBasePath, resolveDefaultWorkspaceForBot, isPathInside as isWorkspacePathInside, } from "./workspace-paths.js";
|
|
4
|
+
export { DEFAULT_EXTERNAL_WORKSPACES_DIRNAME, getKernelRootPath, resolveKernelRootPath, getDefaultExternalWorkspaceBasePath, resolveExternalWorkspaceBasePath, resolveDefaultWorkspaceForBot, isPathInside as isWorkspacePathInside, } from "./workspace-paths.js";
|
|
5
5
|
export { resolveConfigBaseDir, resolveProcessConfigBaseDir, resolvePathFromBase, resolveOptionalPathFromBase, } from "./config-paths.js";
|
|
6
|
+
export { loadCopilotHubEnvironment } from "./env-config.js";
|
|
6
7
|
export { InstanceLock } from "./instance-lock.js";
|
|
7
8
|
export { JsonStateStore } from "./state-store.js";
|
|
8
9
|
export { assertControlPermission } from "./control-permission.js";
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export { createWorkspaceBoundaryPolicy, assertWorkspaceAllowed, isPathInside, normalizeAbsolutePath, parseWorkspaceAllowedRoots, } from "./workspace-policy.js";
|
|
2
2
|
export { normalizeThreadId } from "./thread-id.js";
|
|
3
3
|
export { createProjectFingerprint } from "./project-fingerprint.js";
|
|
4
|
-
export { DEFAULT_EXTERNAL_WORKSPACES_DIRNAME, getKernelRootPath, getDefaultExternalWorkspaceBasePath, resolveDefaultWorkspaceForBot, isPathInside as isWorkspacePathInside, } from "./workspace-paths.js";
|
|
4
|
+
export { DEFAULT_EXTERNAL_WORKSPACES_DIRNAME, getKernelRootPath, resolveKernelRootPath, getDefaultExternalWorkspaceBasePath, resolveExternalWorkspaceBasePath, resolveDefaultWorkspaceForBot, isPathInside as isWorkspacePathInside, } from "./workspace-paths.js";
|
|
5
5
|
export { resolveConfigBaseDir, resolveProcessConfigBaseDir, resolvePathFromBase, resolveOptionalPathFromBase, } from "./config-paths.js";
|
|
6
|
+
export { loadCopilotHubEnvironment } from "./env-config.js";
|
|
6
7
|
export { InstanceLock } from "./instance-lock.js";
|
|
7
8
|
export { JsonStateStore } from "./state-store.js";
|
|
8
9
|
export { assertControlPermission } from "./control-permission.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,6BAA6B,EAC7B,sBAAsB,EACtB,YAAY,EACZ,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EACL,mCAAmC,EACnC,iBAAiB,EACjB,mCAAmC,EACnC,6BAA6B,EAC7B,YAAY,IAAI,qBAAqB,GACtC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,oBAAoB,EACpB,2BAA2B,EAC3B,mBAAmB,EACnB,2BAA2B,GAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,6BAA6B,GAC9B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,eAAe,EACf,oBAAoB,GACrB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC3F,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,6BAA6B,EAC7B,sBAAsB,EACtB,YAAY,EACZ,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EACL,mCAAmC,EACnC,iBAAiB,EACjB,qBAAqB,EACrB,mCAAmC,EACnC,gCAAgC,EAChC,6BAA6B,EAC7B,YAAY,IAAI,qBAAqB,GACtC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,oBAAoB,EACpB,2BAA2B,EAC3B,mBAAmB,EACnB,2BAA2B,GAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,6BAA6B,GAC9B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,eAAe,EACf,oBAAoB,GACrB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC3F,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC"}
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
export declare const DEFAULT_EXTERNAL_WORKSPACES_DIRNAME = "copilot_workspaces";
|
|
2
2
|
export declare function getKernelRootPath(): string;
|
|
3
|
-
export declare function
|
|
3
|
+
export declare function resolveKernelRootPath({ env, moduleUrl, cwd, }?: {
|
|
4
|
+
env?: NodeJS.ProcessEnv;
|
|
5
|
+
moduleUrl?: string;
|
|
6
|
+
cwd?: string;
|
|
7
|
+
}): string;
|
|
8
|
+
export declare function getDefaultExternalWorkspaceBasePath(kernelRoot?: string): string;
|
|
9
|
+
export declare function resolveExternalWorkspaceBasePath({ kernelRootPath, desktopCandidates, homeDir, tempDir, }: {
|
|
10
|
+
kernelRootPath: string;
|
|
11
|
+
desktopCandidates?: readonly string[];
|
|
12
|
+
homeDir?: string;
|
|
13
|
+
tempDir?: string;
|
|
14
|
+
}): string;
|
|
4
15
|
export declare function resolveDefaultWorkspaceForBot(botId: unknown, kernelRoot?: string): string;
|
|
5
16
|
export declare function isPathInside(parentPath: unknown, candidatePath: unknown): boolean;
|
|
@@ -1,18 +1,42 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import process from "node:process";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
4
6
|
export const DEFAULT_EXTERNAL_WORKSPACES_DIRNAME = "copilot_workspaces";
|
|
5
7
|
const DESKTOP_DIRNAME = "Desktop";
|
|
6
8
|
export function getKernelRootPath() {
|
|
7
|
-
return
|
|
9
|
+
return resolveKernelRootPath();
|
|
8
10
|
}
|
|
9
|
-
export function
|
|
10
|
-
const
|
|
11
|
-
|
|
11
|
+
export function resolveKernelRootPath({ env = process.env, moduleUrl = import.meta.url, cwd = process.cwd(), } = {}) {
|
|
12
|
+
const configuredRoot = String(env.COPILOT_HUB_KERNEL_ROOT ?? "").trim();
|
|
13
|
+
if (configuredRoot) {
|
|
14
|
+
return path.resolve(configuredRoot);
|
|
15
|
+
}
|
|
16
|
+
const moduleFilePath = String(moduleUrl ?? "").trim();
|
|
17
|
+
if (moduleFilePath) {
|
|
18
|
+
return path.resolve(path.dirname(fileURLToPath(moduleFilePath)), "..", "..", "..");
|
|
19
|
+
}
|
|
20
|
+
return path.resolve(String(cwd ?? process.cwd()));
|
|
21
|
+
}
|
|
22
|
+
export function getDefaultExternalWorkspaceBasePath(kernelRoot = getKernelRootPath()) {
|
|
23
|
+
return resolveExternalWorkspaceBasePath({
|
|
24
|
+
kernelRootPath: kernelRoot,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
export function resolveExternalWorkspaceBasePath({ kernelRootPath, desktopCandidates = getDesktopCandidates(), homeDir = os.homedir(), tempDir = os.tmpdir(), }) {
|
|
12
28
|
const desktopRoot = desktopCandidates.find((candidate) => directoryExists(candidate)) ??
|
|
13
29
|
desktopCandidates[0] ??
|
|
14
|
-
|
|
15
|
-
|
|
30
|
+
path.resolve(String(homeDir ?? "").trim() || process.cwd(), DESKTOP_DIRNAME);
|
|
31
|
+
const preferredRoot = path.resolve(desktopRoot, DEFAULT_EXTERNAL_WORKSPACES_DIRNAME);
|
|
32
|
+
if (!isPathInside(kernelRootPath, preferredRoot)) {
|
|
33
|
+
return preferredRoot;
|
|
34
|
+
}
|
|
35
|
+
const homeFallbackRoot = path.resolve(String(homeDir ?? "").trim() || process.cwd(), DEFAULT_EXTERNAL_WORKSPACES_DIRNAME);
|
|
36
|
+
if (!isPathInside(kernelRootPath, homeFallbackRoot)) {
|
|
37
|
+
return homeFallbackRoot;
|
|
38
|
+
}
|
|
39
|
+
return path.resolve(String(tempDir ?? "").trim() || process.cwd(), DEFAULT_EXTERNAL_WORKSPACES_DIRNAME);
|
|
16
40
|
}
|
|
17
41
|
export function resolveDefaultWorkspaceForBot(botId, kernelRoot = getKernelRootPath()) {
|
|
18
42
|
const id = String(botId ?? "").trim();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-paths.js","sourceRoot":"","sources":["../src/workspace-paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"workspace-paths.js","sourceRoot":"","sources":["../src/workspace-paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -34,6 +34,10 @@
|
|
|
34
34
|
"types": "./dist/config-paths.d.ts",
|
|
35
35
|
"import": "./dist/config-paths.js"
|
|
36
36
|
},
|
|
37
|
+
"./env-config": {
|
|
38
|
+
"types": "./dist/env-config.d.ts",
|
|
39
|
+
"import": "./dist/env-config.js"
|
|
40
|
+
},
|
|
37
41
|
"./instance-lock": {
|
|
38
42
|
"types": "./dist/instance-lock.d.ts",
|
|
39
43
|
"import": "./dist/instance-lock.js"
|
|
@@ -15,7 +15,8 @@ const engineExamplePath = path.join(repoRoot, "apps", "agent-engine", ".env.exam
|
|
|
15
15
|
const controlPlaneEnvPath = layout.controlPlaneEnvPath;
|
|
16
16
|
const controlPlaneExamplePath = path.join(repoRoot, "apps", "control-plane", ".env.example");
|
|
17
17
|
const TELEGRAM_TOKEN_PATTERN = /^\d{5,}:[A-Za-z0-9_-]{20,}$/;
|
|
18
|
-
const DEFAULT_CONTROL_PLANE_TOKEN_ENV = "
|
|
18
|
+
const DEFAULT_CONTROL_PLANE_TOKEN_ENV = "HUB_TELEGRAM_TOKEN_FILE";
|
|
19
|
+
const LEGACY_CONTROL_PLANE_TOKEN_ENV = "HUB_TELEGRAM_TOKEN";
|
|
19
20
|
const args = new Set(process.argv.slice(2));
|
|
20
21
|
const requiredOnly = args.has("--required-only");
|
|
21
22
|
await main();
|
|
@@ -44,9 +45,7 @@ async function main() {
|
|
|
44
45
|
writeLines(controlPlaneEnvPath, controlPlaneLines);
|
|
45
46
|
}
|
|
46
47
|
async function configureRequiredTokens({ rl, controlPlaneLines }) {
|
|
47
|
-
const
|
|
48
|
-
const controlPlaneTokenEnvName = nonEmpty(controlPlaneMap.HUB_TELEGRAM_TOKEN_ENV, DEFAULT_CONTROL_PLANE_TOKEN_ENV);
|
|
49
|
-
setEnvValue(controlPlaneLines, "HUB_TELEGRAM_TOKEN_ENV", controlPlaneTokenEnvName);
|
|
48
|
+
const controlPlaneTokenEnvName = migrateControlPlaneTokenEnv(controlPlaneLines);
|
|
50
49
|
const postControlPlaneMap = parseEnvMap(controlPlaneLines);
|
|
51
50
|
const currentToken = String(postControlPlaneMap[controlPlaneTokenEnvName] ?? "").trim();
|
|
52
51
|
if (isUsableTelegramToken(currentToken)) {
|
|
@@ -62,10 +61,8 @@ async function configureRequiredTokens({ rl, controlPlaneLines }) {
|
|
|
62
61
|
console.log("Required token saved.");
|
|
63
62
|
}
|
|
64
63
|
async function configureAll({ rl, controlPlaneLines }) {
|
|
65
|
-
const controlPlaneMap = parseEnvMap(controlPlaneLines);
|
|
66
64
|
console.log("\nCopilot Hub control-plane configuration\n");
|
|
67
|
-
const controlPlaneTokenEnvDefault =
|
|
68
|
-
setEnvValue(controlPlaneLines, "HUB_TELEGRAM_TOKEN_ENV", controlPlaneTokenEnvDefault);
|
|
65
|
+
const controlPlaneTokenEnvDefault = migrateControlPlaneTokenEnv(controlPlaneLines);
|
|
69
66
|
const currentControlPlaneToken = String(parseEnvMap(controlPlaneLines)[controlPlaneTokenEnvDefault] ?? "").trim();
|
|
70
67
|
const newControlPlaneToken = currentControlPlaneToken
|
|
71
68
|
? await askTelegramToken(rl, "Control-plane Telegram token (press Enter to keep current)", true)
|
|
@@ -77,6 +74,23 @@ async function configureAll({ rl, controlPlaneLines }) {
|
|
|
77
74
|
console.log("- Control-plane token left unchanged.");
|
|
78
75
|
}
|
|
79
76
|
}
|
|
77
|
+
function migrateControlPlaneTokenEnv(lines) {
|
|
78
|
+
const controlPlaneMap = parseEnvMap(lines);
|
|
79
|
+
const configuredTokenEnvName = nonEmpty(controlPlaneMap.HUB_TELEGRAM_TOKEN_ENV, DEFAULT_CONTROL_PLANE_TOKEN_ENV);
|
|
80
|
+
const shouldMigrateLegacyName = configuredTokenEnvName === LEGACY_CONTROL_PLANE_TOKEN_ENV;
|
|
81
|
+
const nextTokenEnvName = shouldMigrateLegacyName
|
|
82
|
+
? DEFAULT_CONTROL_PLANE_TOKEN_ENV
|
|
83
|
+
: configuredTokenEnvName;
|
|
84
|
+
setEnvValue(lines, "HUB_TELEGRAM_TOKEN_ENV", nextTokenEnvName);
|
|
85
|
+
if (shouldMigrateLegacyName) {
|
|
86
|
+
const legacyToken = String(controlPlaneMap[LEGACY_CONTROL_PLANE_TOKEN_ENV] ?? "").trim();
|
|
87
|
+
const dedicatedToken = String(controlPlaneMap[DEFAULT_CONTROL_PLANE_TOKEN_ENV] ?? "").trim();
|
|
88
|
+
if (legacyToken && !dedicatedToken) {
|
|
89
|
+
setEnvValue(lines, DEFAULT_CONTROL_PLANE_TOKEN_ENV, legacyToken);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return nextTokenEnvName;
|
|
93
|
+
}
|
|
80
94
|
function ensureEnvFile(envPath, examplePath) {
|
|
81
95
|
fs.mkdirSync(path.dirname(envPath), { recursive: true });
|
|
82
96
|
if (fs.existsSync(envPath)) {
|
package/scripts/dist/daemon.mjs
CHANGED
|
@@ -508,6 +508,23 @@ function detectFatalStartupError(ensureResult) {
|
|
|
508
508
|
detectedAt: new Date().toISOString(),
|
|
509
509
|
};
|
|
510
510
|
}
|
|
511
|
+
const invalidHubTokenLine = findLineContaining(evidenceChunks, (line) => line.includes("hub telegram token in") && line.includes("is invalid"));
|
|
512
|
+
if (invalidHubTokenLine) {
|
|
513
|
+
return {
|
|
514
|
+
reason: invalidHubTokenLine,
|
|
515
|
+
action: "Run 'copilot-hub configure' to save a valid hub token in the control-plane config, then retry service.",
|
|
516
|
+
detectedAt: new Date().toISOString(),
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
const workspaceRootLine = findLineContaining(evidenceChunks, (line) => line.includes("default_workspace_root must be outside kernel directory") ||
|
|
520
|
+
line.includes("hub_workspace_root must be outside kernel directory"));
|
|
521
|
+
if (workspaceRootLine) {
|
|
522
|
+
return {
|
|
523
|
+
reason: workspaceRootLine,
|
|
524
|
+
action: "Set DEFAULT_WORKSPACE_ROOT to a folder outside the copilot-hub installation, then retry service.",
|
|
525
|
+
detectedAt: new Date().toISOString(),
|
|
526
|
+
};
|
|
527
|
+
}
|
|
511
528
|
return null;
|
|
512
529
|
}
|
|
513
530
|
function readLogTail(filePath, maxLines = 120) {
|
|
@@ -18,7 +18,8 @@ const engineExamplePath = path.join(repoRoot, "apps", "agent-engine", ".env.exam
|
|
|
18
18
|
const controlPlaneEnvPath = layout.controlPlaneEnvPath;
|
|
19
19
|
const controlPlaneExamplePath = path.join(repoRoot, "apps", "control-plane", ".env.example");
|
|
20
20
|
const TELEGRAM_TOKEN_PATTERN = /^\d{5,}:[A-Za-z0-9_-]{20,}$/;
|
|
21
|
-
const DEFAULT_CONTROL_PLANE_TOKEN_ENV = "
|
|
21
|
+
const DEFAULT_CONTROL_PLANE_TOKEN_ENV = "HUB_TELEGRAM_TOKEN_FILE";
|
|
22
|
+
const LEGACY_CONTROL_PLANE_TOKEN_ENV = "HUB_TELEGRAM_TOKEN";
|
|
22
23
|
|
|
23
24
|
const args = new Set(process.argv.slice(2));
|
|
24
25
|
const requiredOnly = args.has("--required-only");
|
|
@@ -53,13 +54,7 @@ async function main() {
|
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
async function configureRequiredTokens({ rl, controlPlaneLines }) {
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
const controlPlaneTokenEnvName = nonEmpty(
|
|
59
|
-
controlPlaneMap.HUB_TELEGRAM_TOKEN_ENV,
|
|
60
|
-
DEFAULT_CONTROL_PLANE_TOKEN_ENV,
|
|
61
|
-
);
|
|
62
|
-
setEnvValue(controlPlaneLines, "HUB_TELEGRAM_TOKEN_ENV", controlPlaneTokenEnvName);
|
|
57
|
+
const controlPlaneTokenEnvName = migrateControlPlaneTokenEnv(controlPlaneLines);
|
|
63
58
|
|
|
64
59
|
const postControlPlaneMap = parseEnvMap(controlPlaneLines);
|
|
65
60
|
const currentToken = String(postControlPlaneMap[controlPlaneTokenEnvName] ?? "").trim();
|
|
@@ -82,15 +77,9 @@ async function configureRequiredTokens({ rl, controlPlaneLines }) {
|
|
|
82
77
|
}
|
|
83
78
|
|
|
84
79
|
async function configureAll({ rl, controlPlaneLines }) {
|
|
85
|
-
const controlPlaneMap = parseEnvMap(controlPlaneLines);
|
|
86
|
-
|
|
87
80
|
console.log("\nCopilot Hub control-plane configuration\n");
|
|
88
81
|
|
|
89
|
-
const controlPlaneTokenEnvDefault =
|
|
90
|
-
controlPlaneMap.HUB_TELEGRAM_TOKEN_ENV,
|
|
91
|
-
DEFAULT_CONTROL_PLANE_TOKEN_ENV,
|
|
92
|
-
);
|
|
93
|
-
setEnvValue(controlPlaneLines, "HUB_TELEGRAM_TOKEN_ENV", controlPlaneTokenEnvDefault);
|
|
82
|
+
const controlPlaneTokenEnvDefault = migrateControlPlaneTokenEnv(controlPlaneLines);
|
|
94
83
|
const currentControlPlaneToken = String(
|
|
95
84
|
parseEnvMap(controlPlaneLines)[controlPlaneTokenEnvDefault] ?? "",
|
|
96
85
|
).trim();
|
|
@@ -106,6 +95,29 @@ async function configureAll({ rl, controlPlaneLines }) {
|
|
|
106
95
|
}
|
|
107
96
|
}
|
|
108
97
|
|
|
98
|
+
function migrateControlPlaneTokenEnv(lines) {
|
|
99
|
+
const controlPlaneMap = parseEnvMap(lines);
|
|
100
|
+
const configuredTokenEnvName = nonEmpty(
|
|
101
|
+
controlPlaneMap.HUB_TELEGRAM_TOKEN_ENV,
|
|
102
|
+
DEFAULT_CONTROL_PLANE_TOKEN_ENV,
|
|
103
|
+
);
|
|
104
|
+
const shouldMigrateLegacyName = configuredTokenEnvName === LEGACY_CONTROL_PLANE_TOKEN_ENV;
|
|
105
|
+
const nextTokenEnvName = shouldMigrateLegacyName
|
|
106
|
+
? DEFAULT_CONTROL_PLANE_TOKEN_ENV
|
|
107
|
+
: configuredTokenEnvName;
|
|
108
|
+
setEnvValue(lines, "HUB_TELEGRAM_TOKEN_ENV", nextTokenEnvName);
|
|
109
|
+
|
|
110
|
+
if (shouldMigrateLegacyName) {
|
|
111
|
+
const legacyToken = String(controlPlaneMap[LEGACY_CONTROL_PLANE_TOKEN_ENV] ?? "").trim();
|
|
112
|
+
const dedicatedToken = String(controlPlaneMap[DEFAULT_CONTROL_PLANE_TOKEN_ENV] ?? "").trim();
|
|
113
|
+
if (legacyToken && !dedicatedToken) {
|
|
114
|
+
setEnvValue(lines, DEFAULT_CONTROL_PLANE_TOKEN_ENV, legacyToken);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return nextTokenEnvName;
|
|
119
|
+
}
|
|
120
|
+
|
|
109
121
|
function ensureEnvFile(envPath, examplePath) {
|
|
110
122
|
fs.mkdirSync(path.dirname(envPath), { recursive: true });
|
|
111
123
|
if (fs.existsSync(envPath)) {
|
package/scripts/src/daemon.mts
CHANGED
|
@@ -600,6 +600,34 @@ function detectFatalStartupError(ensureResult) {
|
|
|
600
600
|
};
|
|
601
601
|
}
|
|
602
602
|
|
|
603
|
+
const invalidHubTokenLine = findLineContaining(
|
|
604
|
+
evidenceChunks,
|
|
605
|
+
(line) => line.includes("hub telegram token in") && line.includes("is invalid"),
|
|
606
|
+
);
|
|
607
|
+
if (invalidHubTokenLine) {
|
|
608
|
+
return {
|
|
609
|
+
reason: invalidHubTokenLine,
|
|
610
|
+
action:
|
|
611
|
+
"Run 'copilot-hub configure' to save a valid hub token in the control-plane config, then retry service.",
|
|
612
|
+
detectedAt: new Date().toISOString(),
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
const workspaceRootLine = findLineContaining(
|
|
617
|
+
evidenceChunks,
|
|
618
|
+
(line) =>
|
|
619
|
+
line.includes("default_workspace_root must be outside kernel directory") ||
|
|
620
|
+
line.includes("hub_workspace_root must be outside kernel directory"),
|
|
621
|
+
);
|
|
622
|
+
if (workspaceRootLine) {
|
|
623
|
+
return {
|
|
624
|
+
reason: workspaceRootLine,
|
|
625
|
+
action:
|
|
626
|
+
"Set DEFAULT_WORKSPACE_ROOT to a folder outside the copilot-hub installation, then retry service.",
|
|
627
|
+
detectedAt: new Date().toISOString(),
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
|
|
603
631
|
return null;
|
|
604
632
|
}
|
|
605
633
|
|