copilot-hub 0.1.28 → 0.1.30
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/.env.example +6 -8
- package/apps/agent-engine/dist/config.js +18 -17
- package/apps/control-plane/.env.example +4 -4
- package/apps/control-plane/dist/config.js +19 -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 +2 -1
- package/packages/core/dist/env-config.d.ts +11 -0
- package/packages/core/dist/env-config.js +70 -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/cli.mjs +52 -1
- package/scripts/dist/configure.mjs +26 -68
- package/scripts/dist/daemon.mjs +17 -0
- package/scripts/dist/env-file-utils.mjs +83 -0
- package/scripts/dist/install-layout.mjs +130 -1
- package/scripts/dist/supervisor.mjs +5 -0
- package/scripts/src/cli.mts +65 -1
- package/scripts/src/configure.mts +32 -88
- package/scripts/src/daemon.mts +28 -0
- package/scripts/src/env-file-utils.mts +98 -0
- package/scripts/src/install-layout.mts +172 -2
- package/scripts/src/supervisor.mts +5 -0
- package/scripts/test/install-layout.test.mjs +54 -2
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
# Runtime state files are managed automatically by copilot-hub.
|
|
2
|
+
# Override only if you intentionally want a custom location.
|
|
3
|
+
# BOT_DATA_DIR=
|
|
4
|
+
# BOT_REGISTRY_FILE=
|
|
5
|
+
# SECRET_STORE_FILE=
|
|
6
6
|
|
|
7
7
|
# Worker defaults
|
|
8
8
|
# If empty, runtime uses Desktop/copilot_workspaces by default
|
|
@@ -27,7 +27,7 @@ SHARED_THREAD_ID=shared-main
|
|
|
27
27
|
TELEGRAM_ALLOWED_CHAT_IDS=
|
|
28
28
|
|
|
29
29
|
INSTANCE_LOCK_ENABLED=true
|
|
30
|
-
INSTANCE_LOCK_FILE
|
|
30
|
+
# INSTANCE_LOCK_FILE=
|
|
31
31
|
|
|
32
32
|
WEB_HOST=127.0.0.1
|
|
33
33
|
WEB_PORT=8787
|
|
@@ -37,5 +37,3 @@ WEB_PORT_SEARCH_MAX=30
|
|
|
37
37
|
|
|
38
38
|
# Optional worker token environment variables used in bot-registry.json
|
|
39
39
|
TELEGRAM_TOKEN_AGENT_1=
|
|
40
|
-
|
|
41
|
-
|
|
@@ -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,16 @@ 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(),
|
|
137
|
+
preserveExistingKeys: [
|
|
138
|
+
"BOT_DATA_DIR",
|
|
139
|
+
"BOT_REGISTRY_FILE",
|
|
140
|
+
"SECRET_STORE_FILE",
|
|
141
|
+
"INSTANCE_LOCK_FILE",
|
|
142
|
+
"COPILOT_HUB_HOME_DIR",
|
|
143
|
+
],
|
|
134
144
|
});
|
|
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
145
|
}
|
|
145
146
|
function resolveCodexBin(rawValue) {
|
|
146
147
|
const value = String(rawValue ?? "").trim();
|
|
@@ -1,10 +1,11 @@
|
|
|
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)
|
|
6
6
|
HUB_WORKSPACE_ROOT=
|
|
7
|
-
|
|
7
|
+
# Runtime state paths are managed automatically by copilot-hub.
|
|
8
|
+
# HUB_DATA_DIR=
|
|
8
9
|
HUB_THREAD_MODE=per_chat
|
|
9
10
|
HUB_SHARED_THREAD_ID=shared-copilot-hub
|
|
10
11
|
HUB_ALLOWED_CHAT_IDS=
|
|
@@ -21,4 +22,3 @@ CODEX_SANDBOX=danger-full-access
|
|
|
21
22
|
CODEX_APPROVAL_POLICY=never
|
|
22
23
|
TURN_ACTIVITY_TIMEOUT_MS=0
|
|
23
24
|
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,17 @@ 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(),
|
|
144
|
+
preserveExistingKeys: [
|
|
145
|
+
"BOT_DATA_DIR",
|
|
146
|
+
"BOT_REGISTRY_FILE",
|
|
147
|
+
"SECRET_STORE_FILE",
|
|
148
|
+
"INSTANCE_LOCK_FILE",
|
|
149
|
+
"HUB_DATA_DIR",
|
|
150
|
+
"COPILOT_HUB_HOME_DIR",
|
|
151
|
+
],
|
|
141
152
|
});
|
|
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
153
|
}
|
|
152
154
|
function resolveCodexBin(rawValue) {
|
|
153
155
|
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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "copilot-hub",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.30",
|
|
4
4
|
"description": "Copilot Hub CLI and runtime bundle",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
"status": "npm run build:scripts --silent && node scripts/dist/cli.mjs status",
|
|
59
59
|
"logs": "npm run build:scripts --silent && node scripts/dist/cli.mjs logs",
|
|
60
60
|
"configure": "npm run build:scripts --silent && node scripts/dist/cli.mjs configure",
|
|
61
|
+
"reset-config": "npm run build:scripts --silent && node scripts/dist/cli.mjs reset-config",
|
|
61
62
|
"test:scripts": "npm run build:scripts --silent && node --test scripts/test/*.test.mjs",
|
|
62
63
|
"test": "npm run test:scripts && npm run test --workspaces --if-present",
|
|
63
64
|
"lint": "eslint .",
|
|
@@ -0,0 +1,11 @@
|
|
|
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, preserveExistingKeys, }?: {
|
|
8
|
+
env?: NodeJS.ProcessEnv;
|
|
9
|
+
cwd?: string;
|
|
10
|
+
preserveExistingKeys?: Iterable<string>;
|
|
11
|
+
}): LoadedCopilotHubEnvironment;
|
|
@@ -0,0 +1,70 @@
|
|
|
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(), preserveExistingKeys = [], } = {}) {
|
|
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, preserveExistingKeys);
|
|
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, preserveExistingKeys) {
|
|
45
|
+
const overriddenKeys = [];
|
|
46
|
+
const preservedKeys = new Set([...preserveExistingKeys].map((key) => String(key ?? "").trim()).filter(Boolean));
|
|
47
|
+
for (const [key, value] of Object.entries(fileValues)) {
|
|
48
|
+
const previousValue = String(env[key] ?? "");
|
|
49
|
+
if (previousValue && preservedKeys.has(key)) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (previousValue && previousValue !== value) {
|
|
53
|
+
overriddenKeys.push(key);
|
|
54
|
+
}
|
|
55
|
+
env[key] = value;
|
|
56
|
+
}
|
|
57
|
+
return overriddenKeys.sort();
|
|
58
|
+
}
|
|
59
|
+
function normalizeEnvMap(value) {
|
|
60
|
+
const output = {};
|
|
61
|
+
for (const [key, entry] of Object.entries(value ?? {})) {
|
|
62
|
+
const normalizedKey = String(key ?? "").trim();
|
|
63
|
+
if (!normalizedKey) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
output[normalizedKey] = String(entry ?? "").trim();
|
|
67
|
+
}
|
|
68
|
+
return output;
|
|
69
|
+
}
|
|
70
|
+
//# 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":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,CAAC,MAAM,mCAAmC,GAAG,oBAAoB,CAAC;AACxE,MAAM,eAAe,GAAG,SAAS,CAAC;AAElC,MAAM,UAAU,iBAAiB;IAC/B,OAAO,qBAAqB,EAAE,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,EACpC,GAAG,GAAG,OAAO,CAAC,GAAG,EACjB,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAC3B,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,MAKjB,EAAE;IACJ,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACxE,IAAI,cAAc,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,cAAc,GAAG,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACtD,IAAI,cAAc,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACrF,CAAC;IAED,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,mCAAmC,CAAC,UAAU,GAAG,iBAAiB,EAAE;IAClF,OAAO,gCAAgC,CAAC;QACtC,cAAc,EAAE,UAAU;KAC3B,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,gCAAgC,CAAC,EAC/C,cAAc,EACd,iBAAiB,GAAG,oBAAoB,EAAE,EAC1C,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,EACtB,OAAO,GAAG,EAAE,CAAC,MAAM,EAAE,GAMtB;IACC,MAAM,WAAW,GACf,iBAAiB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QACjE,iBAAiB,CAAC,CAAC,CAAC;QACpB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,eAAe,CAAC,CAAC;IAE/E,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,mCAAmC,CAAC,CAAC;IACrF,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE,aAAa,CAAC,EAAE,CAAC;QACjD,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,CACnC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,OAAO,CAAC,GAAG,EAAE,EAC7C,mCAAmC,CACpC,CAAC;IACF,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE,gBAAgB,CAAC,EAAE,CAAC;QACpD,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,OAAO,IAAI,CAAC,OAAO,CACjB,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,OAAO,CAAC,GAAG,EAAE,EAC7C,mCAAmC,CACpC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,6BAA6B,CAC3C,KAAc,EACd,UAAU,GAAG,iBAAiB,EAAE;IAEhC,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACtC,OAAO,IAAI,CAAC,OAAO,CAAC,mCAAmC,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,UAAmB,EAAE,aAAsB;IACtE,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACrF,MAAM,mBAAmB,GAAG,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3F,IAAI,CAAC,gBAAgB,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,gBAAgB,KAAK,mBAAmB,EAAE,CAAC;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,CAAC;IACtE,OAAO,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;AACvF,CAAC;AAED,SAAS,oBAAoB;IAC3B,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACjE,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/D,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAElD,MAAM,aAAa,GAAG;QACpB,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI;QACjE,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI;QAC/D,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI;KACxD,CAAC;IAEF,OAAO,mBAAmB,CAAC,aAAa,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa;IACxC,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC1E,CAAC;AAED,SAAS,eAAe,CAAC,aAAqB;IAC5C,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,WAAW,EAAE,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,MAA4B;IACvD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACvC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,SAAS;QACX,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACnC,MAAM,UAAU,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QACjD,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YACxC,SAAS;QACX,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACrB,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -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"
|
package/scripts/dist/cli.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { createInterface } from "node:readline/promises";
|
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
import { spawnCodexSync } from "./codex-spawn.mjs";
|
|
9
9
|
import { codexInstallPackageSpec } from "./codex-version.mjs";
|
|
10
|
-
import { initializeCopilotHubLayout, resolveCopilotHubLayout } from "./install-layout.mjs";
|
|
10
|
+
import { initializeCopilotHubLayout, resetCopilotHubConfig, resolveCopilotHubLayout, } from "./install-layout.mjs";
|
|
11
11
|
import { buildCodexCompatibilityError, buildCodexCompatibilityNotice, probeCodexVersion, resolveCodexBinForStart, resolveCompatibleInstalledCodexBin, } from "./codex-runtime.mjs";
|
|
12
12
|
const __filename = fileURLToPath(import.meta.url);
|
|
13
13
|
const __dirname = path.dirname(__filename);
|
|
@@ -27,6 +27,7 @@ const rawArgs = process.argv
|
|
|
27
27
|
.filter(Boolean);
|
|
28
28
|
const wantsVersion = rawArgs.includes("--version") || rawArgs.includes("-v");
|
|
29
29
|
const wantsHelp = rawArgs.includes("--help") || rawArgs.includes("-h");
|
|
30
|
+
const wantsYes = rawArgs.includes("--yes") || rawArgs.includes("-y");
|
|
30
31
|
const action = String(rawArgs[0] ?? "start")
|
|
31
32
|
.trim()
|
|
32
33
|
.toLowerCase();
|
|
@@ -92,6 +93,13 @@ async function main() {
|
|
|
92
93
|
runNode(["scripts/dist/configure.mjs"]);
|
|
93
94
|
return;
|
|
94
95
|
}
|
|
96
|
+
case "reset-config":
|
|
97
|
+
case "reset_config": {
|
|
98
|
+
await resetConfig({
|
|
99
|
+
force: wantsYes,
|
|
100
|
+
});
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
95
103
|
case "service": {
|
|
96
104
|
const serviceAction = String(rawArgs[1] ?? "")
|
|
97
105
|
.trim()
|
|
@@ -111,6 +119,47 @@ async function main() {
|
|
|
111
119
|
}
|
|
112
120
|
}
|
|
113
121
|
}
|
|
122
|
+
async function resetConfig({ force }) {
|
|
123
|
+
if (!force) {
|
|
124
|
+
if (!process.stdin.isTTY) {
|
|
125
|
+
throw new Error("reset-config requires confirmation. Re-run with '--yes' in non-interactive mode.");
|
|
126
|
+
}
|
|
127
|
+
const rl = createInterface({ input, output });
|
|
128
|
+
try {
|
|
129
|
+
const confirmed = await askYesNo(rl, [
|
|
130
|
+
"Reset Copilot Hub config and runtime state?",
|
|
131
|
+
"This removes persisted config, bot registry, secrets, logs, and runtime state.",
|
|
132
|
+
"Agent workspaces are kept.",
|
|
133
|
+
].join(" "), false);
|
|
134
|
+
if (!confirmed) {
|
|
135
|
+
console.log("Reset canceled.");
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
rl.close();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (isServiceAlreadyInstalled()) {
|
|
144
|
+
runNodeCapture(["scripts/dist/service.mjs", "stop"], "inherit");
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
runNodeCapture(["scripts/dist/supervisor.mjs", "down"], "inherit");
|
|
148
|
+
}
|
|
149
|
+
const reset = resetCopilotHubConfig({ layout });
|
|
150
|
+
initializeCopilotHubLayout({ repoRoot, layout });
|
|
151
|
+
console.log("Copilot Hub config reset completed.");
|
|
152
|
+
if (reset.removedPaths.length > 0) {
|
|
153
|
+
console.log("Removed:");
|
|
154
|
+
for (const removedPath of reset.removedPaths) {
|
|
155
|
+
console.log(`- ${removedPath}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
console.log("Kept:");
|
|
159
|
+
console.log("- package installation");
|
|
160
|
+
console.log("- external workspaces (for example Desktop/copilot_workspaces)");
|
|
161
|
+
console.log("Next step: run 'copilot-hub configure' then 'copilot-hub start'.");
|
|
162
|
+
}
|
|
114
163
|
function runNode(scriptArgs) {
|
|
115
164
|
const result = runNodeCapture(scriptArgs, "inherit");
|
|
116
165
|
const code = Number.isInteger(result.status) ? result.status : 1;
|
|
@@ -485,6 +534,8 @@ function spawnNpm(args, options) {
|
|
|
485
534
|
function printUsage() {
|
|
486
535
|
console.log([
|
|
487
536
|
"Usage: node scripts/dist/cli.mjs <start|stop|restart|status|logs|configure|service|version|help>",
|
|
537
|
+
"Reset persistent state:",
|
|
538
|
+
" node scripts/dist/cli.mjs reset-config [--yes]",
|
|
488
539
|
"Service management:",
|
|
489
540
|
" node scripts/dist/cli.mjs service <install|uninstall|status|start|stop|help>",
|
|
490
541
|
].join("\n"));
|