workspacecord 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/archive-manager-KMNAWQIN.js +21 -0
- package/dist/attachment-cli-QEF7IZBI.js +62 -0
- package/dist/{chunk-OKI4UVGY.js → chunk-52OOARML.js} +65 -2
- package/dist/{chunk-NIXZJTOZ.js → chunk-7KESUGJP.js} +3 -46
- package/dist/chunk-CBNENUW6.js +55 -0
- package/dist/{chunk-2LBNM64L.js → chunk-D6J3X35H.js} +23 -11
- package/dist/{bot-B5HN4ZW6.js → chunk-G6CCOBUY.js} +6556 -5956
- package/dist/{chunk-TSBM3BNT.js → chunk-IFSOU4XI.js} +393 -140
- package/dist/chunk-PUKMHDXS.js +196 -0
- package/dist/chunk-Q2AJ4UEK.js +199 -0
- package/dist/cli-framework-KMQXM2PO.js +17 -0
- package/dist/cli.js +20 -68
- package/dist/{codex-launcher-IF2IPLBP.js → codex-launcher-OOF2WYQF.js} +1 -1
- package/dist/{codex-provider-7CI5W34X.js → codex-provider-P7TDYK6B.js} +2 -2
- package/dist/{config-cli-F2B5SYHJ.js → config-cli-YSKOXADF.js} +2 -2
- package/dist/{project-cli-FEMPZIRQ.js → project-cli-QW5QYT6A.js} +2 -1
- package/dist/{project-registry-DQT5ORUU.js → project-registry-LL75XEUV.js} +2 -1
- package/dist/{setup-TKOVXSME.js → setup-QJ4HVVCU.js} +1 -1
- package/dist/{thread-manager-5T46QTZF.js → thread-manager-DRWNFXXY.js} +17 -7
- package/package.json +7 -2
- package/dist/chunk-WE4X3JB3.js +0 -130
- package/dist/utils-72GMT2X5.js +0 -36
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
archiveSession,
|
|
4
|
+
checkAutoArchive,
|
|
5
|
+
getArchivedSessions,
|
|
6
|
+
isArchivedProviderSession,
|
|
7
|
+
loadArchived
|
|
8
|
+
} from "./chunk-PUKMHDXS.js";
|
|
9
|
+
import "./chunk-IFSOU4XI.js";
|
|
10
|
+
import "./chunk-D6J3X35H.js";
|
|
11
|
+
import "./chunk-7KESUGJP.js";
|
|
12
|
+
import "./chunk-CBNENUW6.js";
|
|
13
|
+
import "./chunk-52OOARML.js";
|
|
14
|
+
import "./chunk-K3NQKI34.js";
|
|
15
|
+
export {
|
|
16
|
+
archiveSession,
|
|
17
|
+
checkAutoArchive,
|
|
18
|
+
getArchivedSessions,
|
|
19
|
+
isArchivedProviderSession,
|
|
20
|
+
loadArchived
|
|
21
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
fetchRegisteredAttachments
|
|
4
|
+
} from "./chunk-Q2AJ4UEK.js";
|
|
5
|
+
import "./chunk-CBNENUW6.js";
|
|
6
|
+
import "./chunk-K3NQKI34.js";
|
|
7
|
+
|
|
8
|
+
// src/attachment-cli.ts
|
|
9
|
+
function printHelp() {
|
|
10
|
+
console.log(`
|
|
11
|
+
workspacecord attachment \u2014 fetch registered Discord attachments
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
workspacecord attachment fetch --session <session-id> --message <message-id> --attachment <attachment-id>
|
|
15
|
+
workspacecord attachment fetch --session <session-id> --message <message-id> --all
|
|
16
|
+
`);
|
|
17
|
+
}
|
|
18
|
+
function readFlag(args, flag) {
|
|
19
|
+
const index = args.indexOf(flag);
|
|
20
|
+
if (index < 0) return void 0;
|
|
21
|
+
return args[index + 1];
|
|
22
|
+
}
|
|
23
|
+
async function handleAttachment(args) {
|
|
24
|
+
const [subcommand, ...rest] = args;
|
|
25
|
+
switch (subcommand) {
|
|
26
|
+
case "fetch": {
|
|
27
|
+
const sessionId = readFlag(rest, "--session");
|
|
28
|
+
const messageId = readFlag(rest, "--message");
|
|
29
|
+
const attachmentId = readFlag(rest, "--attachment");
|
|
30
|
+
const all = rest.includes("--all");
|
|
31
|
+
const currentSessionId = readFlag(rest, "--current-session") ?? process.env.workspacecord_CURRENT_SESSION_ID ?? sessionId;
|
|
32
|
+
if (!sessionId || !messageId || !attachmentId && !all) {
|
|
33
|
+
console.error(
|
|
34
|
+
"Usage: workspacecord attachment fetch --session <session-id> --message <message-id> (--attachment <attachment-id> | --all)"
|
|
35
|
+
);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
const downloaded = await fetchRegisteredAttachments({
|
|
39
|
+
sessionId,
|
|
40
|
+
messageId,
|
|
41
|
+
attachmentId,
|
|
42
|
+
all,
|
|
43
|
+
currentSessionId
|
|
44
|
+
});
|
|
45
|
+
console.log(JSON.stringify(downloaded, null, 2));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
case void 0:
|
|
49
|
+
case "help":
|
|
50
|
+
case "--help":
|
|
51
|
+
case "-h":
|
|
52
|
+
printHelp();
|
|
53
|
+
return;
|
|
54
|
+
default:
|
|
55
|
+
console.error(`Unknown attachment subcommand: ${subcommand}`);
|
|
56
|
+
printHelp();
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export {
|
|
61
|
+
handleAttachment
|
|
62
|
+
};
|
|
@@ -30,20 +30,53 @@ var VALID_KEYS = /* @__PURE__ */ new Set([
|
|
|
30
30
|
"ANTHROPIC_BASE_URL",
|
|
31
31
|
"MESSAGE_RETENTION_DAYS",
|
|
32
32
|
"RATE_LIMIT_MS",
|
|
33
|
+
"ACK_REACTION",
|
|
34
|
+
"REPLY_TO_MODE",
|
|
35
|
+
"TEXT_CHUNK_LIMIT",
|
|
36
|
+
"CHUNK_MODE",
|
|
37
|
+
"IPC_SOCKET_PATH",
|
|
33
38
|
"SHELL_ENABLED",
|
|
34
39
|
"SHELL_ALLOWED_USERS",
|
|
35
40
|
"SESSION_SYNC_INTERVAL_MS",
|
|
41
|
+
"SESSION_SYNC_RECENT_DAYS",
|
|
36
42
|
"HEALTH_REPORT_ENABLED",
|
|
37
43
|
"HEALTH_REPORT_INTERVAL_MS",
|
|
38
44
|
"HEALTH_CHECK_STUCK_THRESHOLD_MS",
|
|
39
|
-
"HEALTH_CHECK_IDLE_THRESHOLD_MS"
|
|
45
|
+
"HEALTH_CHECK_IDLE_THRESHOLD_MS",
|
|
46
|
+
"HOOK_SECRET"
|
|
40
47
|
]);
|
|
41
48
|
var CODEX_SANDBOX_MODES = /* @__PURE__ */ new Set(["read-only", "workspace-write", "danger-full-access"]);
|
|
42
49
|
var CODEX_APPROVAL_POLICIES = /* @__PURE__ */ new Set(["never", "on-request", "on-failure", "untrusted"]);
|
|
43
50
|
var store = null;
|
|
51
|
+
var DEFAULT_TEST_CONFIG_PATH = join(process.cwd(), ".workspacecord-config.json");
|
|
52
|
+
var DEFAULT_TEST_FALLBACK_PATH = join(process.cwd(), ".workspacecord-config-fallback.json");
|
|
53
|
+
function isTestEnvironment() {
|
|
54
|
+
return process.env.VITEST === "true" || process.env.NODE_ENV === "test";
|
|
55
|
+
}
|
|
56
|
+
function resolveGlobalConfigPath() {
|
|
57
|
+
if (process.env.WORKSPACECORD_CONFIG_PATH) {
|
|
58
|
+
return process.env.WORKSPACECORD_CONFIG_PATH;
|
|
59
|
+
}
|
|
60
|
+
if (isTestEnvironment()) {
|
|
61
|
+
return DEFAULT_TEST_CONFIG_PATH;
|
|
62
|
+
}
|
|
63
|
+
const baseDir = process.env.WORKSPACECORD_CONFIG_DIR ? process.env.WORKSPACECORD_CONFIG_DIR : join(homedir(), ".config", "workspacecord");
|
|
64
|
+
return join(baseDir, "config.json");
|
|
65
|
+
}
|
|
66
|
+
function createConfigStore(path) {
|
|
67
|
+
try {
|
|
68
|
+
return new Configstore("workspacecord", {}, { configPath: path });
|
|
69
|
+
} catch (err) {
|
|
70
|
+
if (!isTestEnvironment() || path === DEFAULT_TEST_CONFIG_PATH || path === DEFAULT_TEST_FALLBACK_PATH) {
|
|
71
|
+
throw err;
|
|
72
|
+
}
|
|
73
|
+
return new Configstore("workspacecord", {}, { configPath: DEFAULT_TEST_FALLBACK_PATH });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
44
76
|
function getStore() {
|
|
45
77
|
if (!store) {
|
|
46
|
-
|
|
78
|
+
const path = resolveGlobalConfigPath();
|
|
79
|
+
store = createConfigStore(path);
|
|
47
80
|
}
|
|
48
81
|
return store;
|
|
49
82
|
}
|
|
@@ -72,8 +105,38 @@ function validateConfigValue(key, value) {
|
|
|
72
105
|
return `Invalid value for SHELL_ENABLED. Expected "true" or "false"`;
|
|
73
106
|
}
|
|
74
107
|
break;
|
|
108
|
+
case "TEXT_CHUNK_LIMIT": {
|
|
109
|
+
const n = Number(value);
|
|
110
|
+
if (!Number.isInteger(n) || n < 1 || n > 2e3) {
|
|
111
|
+
return `Invalid value for ${key}. Expected an integer between 1 and 2000`;
|
|
112
|
+
}
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
case "ACK_REACTION":
|
|
116
|
+
if (value === "") break;
|
|
117
|
+
if (/^<a?:[A-Za-z0-9_~]+:\d+>$/.test(value)) break;
|
|
118
|
+
if (/\s/.test(value)) {
|
|
119
|
+
return "Invalid value for ACK_REACTION. Expected a Unicode emoji, empty string, or custom emoji like <:name:id>";
|
|
120
|
+
}
|
|
121
|
+
break;
|
|
122
|
+
case "IPC_SOCKET_PATH":
|
|
123
|
+
if (!value.trim()) {
|
|
124
|
+
return "Invalid value for IPC_SOCKET_PATH. Expected a non-empty socket path";
|
|
125
|
+
}
|
|
126
|
+
break;
|
|
127
|
+
case "REPLY_TO_MODE":
|
|
128
|
+
if (!["off", "first", "all"].includes(value)) {
|
|
129
|
+
return `Invalid value for REPLY_TO_MODE. Expected one of: off, first, all`;
|
|
130
|
+
}
|
|
131
|
+
break;
|
|
132
|
+
case "CHUNK_MODE":
|
|
133
|
+
if (!["length", "newline"].includes(value)) {
|
|
134
|
+
return `Invalid value for CHUNK_MODE. Expected one of: length, newline`;
|
|
135
|
+
}
|
|
136
|
+
break;
|
|
75
137
|
case "RATE_LIMIT_MS":
|
|
76
138
|
case "SESSION_SYNC_INTERVAL_MS":
|
|
139
|
+
case "SESSION_SYNC_RECENT_DAYS":
|
|
77
140
|
case "HEALTH_REPORT_INTERVAL_MS":
|
|
78
141
|
case "HEALTH_CHECK_STUCK_THRESHOLD_MS":
|
|
79
142
|
case "HEALTH_CHECK_IDLE_THRESHOLD_MS": {
|
|
@@ -1,53 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
Store
|
|
4
|
+
} from "./chunk-CBNENUW6.js";
|
|
2
5
|
|
|
3
6
|
// src/project-registry.ts
|
|
4
7
|
import { randomUUID } from "crypto";
|
|
5
8
|
import { resolve } from "path";
|
|
6
|
-
|
|
7
|
-
// src/persistence.ts
|
|
8
|
-
import { readFile, writeFile, mkdir, rename } from "fs/promises";
|
|
9
|
-
import { existsSync } from "fs";
|
|
10
|
-
import { dirname, join } from "path";
|
|
11
|
-
import { homedir } from "os";
|
|
12
|
-
var dataDirOverride = null;
|
|
13
|
-
function getDataDir() {
|
|
14
|
-
return dataDirOverride ?? join(homedir(), ".workspacecord");
|
|
15
|
-
}
|
|
16
|
-
var Store = class {
|
|
17
|
-
filename;
|
|
18
|
-
writeQueue = Promise.resolve();
|
|
19
|
-
constructor(filename) {
|
|
20
|
-
this.filename = filename;
|
|
21
|
-
}
|
|
22
|
-
get filePath() {
|
|
23
|
-
return join(getDataDir(), this.filename);
|
|
24
|
-
}
|
|
25
|
-
async read() {
|
|
26
|
-
try {
|
|
27
|
-
const data = await readFile(this.filePath, "utf-8");
|
|
28
|
-
return JSON.parse(data);
|
|
29
|
-
} catch {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
async write(data) {
|
|
34
|
-
const nextWrite = this.writeQueue.catch(() => {
|
|
35
|
-
}).then(async () => {
|
|
36
|
-
const filePath = this.filePath;
|
|
37
|
-
const dir = dirname(filePath);
|
|
38
|
-
if (!existsSync(dir)) {
|
|
39
|
-
await mkdir(dir, { recursive: true });
|
|
40
|
-
}
|
|
41
|
-
const tmpPath = filePath + ".tmp";
|
|
42
|
-
await writeFile(tmpPath, JSON.stringify(data, null, 2), "utf-8");
|
|
43
|
-
await rename(tmpPath, filePath);
|
|
44
|
-
});
|
|
45
|
-
this.writeQueue = nextWrite;
|
|
46
|
-
await nextWrite;
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
// src/project-registry.ts
|
|
51
9
|
var store = new Store("projects.json");
|
|
52
10
|
var projects = [];
|
|
53
11
|
function normalizePath(path) {
|
|
@@ -158,7 +116,6 @@ async function updateProject(project) {
|
|
|
158
116
|
}
|
|
159
117
|
|
|
160
118
|
export {
|
|
161
|
-
Store,
|
|
162
119
|
loadRegistry,
|
|
163
120
|
getProjectByName,
|
|
164
121
|
getProjectByPath,
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/persistence.ts
|
|
4
|
+
import { readFile, writeFile, mkdir, rename } from "fs/promises";
|
|
5
|
+
import { existsSync } from "fs";
|
|
6
|
+
import { dirname, join } from "path";
|
|
7
|
+
import { homedir } from "os";
|
|
8
|
+
var dataDirOverride = null;
|
|
9
|
+
var DEFAULT_TEST_DATA_DIR = join(process.cwd(), ".workspacecord-data");
|
|
10
|
+
function getDataDir() {
|
|
11
|
+
if (dataDirOverride) return dataDirOverride;
|
|
12
|
+
if (process.env.WORKSPACECORD_DATA_DIR) return process.env.WORKSPACECORD_DATA_DIR;
|
|
13
|
+
if (process.env.VITEST === "true" || process.env.NODE_ENV === "test") {
|
|
14
|
+
return DEFAULT_TEST_DATA_DIR;
|
|
15
|
+
}
|
|
16
|
+
return join(homedir(), ".workspacecord");
|
|
17
|
+
}
|
|
18
|
+
var Store = class {
|
|
19
|
+
filename;
|
|
20
|
+
writeQueue = Promise.resolve();
|
|
21
|
+
constructor(filename) {
|
|
22
|
+
this.filename = filename;
|
|
23
|
+
}
|
|
24
|
+
get filePath() {
|
|
25
|
+
return join(getDataDir(), this.filename);
|
|
26
|
+
}
|
|
27
|
+
async read() {
|
|
28
|
+
try {
|
|
29
|
+
const data = await readFile(this.filePath, "utf-8");
|
|
30
|
+
return JSON.parse(data);
|
|
31
|
+
} catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async write(data) {
|
|
36
|
+
const nextWrite = this.writeQueue.catch(() => {
|
|
37
|
+
}).then(async () => {
|
|
38
|
+
const filePath = this.filePath;
|
|
39
|
+
const dir = dirname(filePath);
|
|
40
|
+
if (!existsSync(dir)) {
|
|
41
|
+
await mkdir(dir, { recursive: true });
|
|
42
|
+
}
|
|
43
|
+
const tmpPath = filePath + ".tmp";
|
|
44
|
+
await writeFile(tmpPath, JSON.stringify(data, null, 2), "utf-8");
|
|
45
|
+
await rename(tmpPath, filePath);
|
|
46
|
+
});
|
|
47
|
+
this.writeQueue = nextWrite;
|
|
48
|
+
await nextWrite;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
getDataDir,
|
|
54
|
+
Store
|
|
55
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
getConfigValue
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-52OOARML.js";
|
|
5
5
|
|
|
6
6
|
// src/config.ts
|
|
7
7
|
import { homedir } from "os";
|
|
@@ -37,6 +37,11 @@ function optionalBool(key, fallback) {
|
|
|
37
37
|
if (!value) return fallback;
|
|
38
38
|
return value === "true" || value === "1";
|
|
39
39
|
}
|
|
40
|
+
function optionalEnum(key, fallback, allowed) {
|
|
41
|
+
const value = getConfigValue(key);
|
|
42
|
+
if (!value) return fallback;
|
|
43
|
+
return allowed.includes(value) ? value : fallback;
|
|
44
|
+
}
|
|
40
45
|
var config = {
|
|
41
46
|
token: required("DISCORD_TOKEN"),
|
|
42
47
|
clientId: required("DISCORD_CLIENT_ID"),
|
|
@@ -44,37 +49,44 @@ var config = {
|
|
|
44
49
|
allowedUsers: optionalList("ALLOWED_USERS"),
|
|
45
50
|
allowAllUsers: optionalBool("ALLOW_ALL_USERS", false),
|
|
46
51
|
dataDir: join(homedir(), ".workspacecord"),
|
|
47
|
-
defaultProvider:
|
|
48
|
-
defaultMode:
|
|
49
|
-
claudePermissionMode:
|
|
52
|
+
defaultProvider: optionalEnum("DEFAULT_PROVIDER", "codex", ["claude", "codex"]),
|
|
53
|
+
defaultMode: optionalEnum("DEFAULT_MODE", "auto", ["auto", "plan", "normal", "monitor"]),
|
|
54
|
+
claudePermissionMode: optionalEnum("CLAUDE_PERMISSION_MODE", "normal", ["bypass", "normal"]),
|
|
50
55
|
maxSubagentDepth: optionalInt("MAX_SUBAGENT_DEPTH", 3),
|
|
51
56
|
maxActiveSessionsPerProject: optionalInt("MAX_ACTIVE_SESSIONS", 20),
|
|
52
57
|
autoArchiveDays: optionalInt("AUTO_ARCHIVE_DAYS", 7),
|
|
53
58
|
messageRetentionDays: optionalInt("MESSAGE_RETENTION_DAYS", 0),
|
|
54
59
|
rateLimitMs: optionalInt("RATE_LIMIT_MS", 1e3),
|
|
60
|
+
ackReaction: optional("ACK_REACTION", "\u{1F440}"),
|
|
61
|
+
replyToMode: optionalEnum("REPLY_TO_MODE", "first", ["off", "first", "all"]),
|
|
62
|
+
textChunkLimit: Math.max(1, Math.min(optionalInt("TEXT_CHUNK_LIMIT", 2e3), 2e3)),
|
|
63
|
+
chunkMode: optionalEnum("CHUNK_MODE", "length", ["length", "newline"]),
|
|
64
|
+
socketPath: optional("IPC_SOCKET_PATH", "/tmp/workspacecord.sock"),
|
|
55
65
|
shellEnabled: optionalBool("SHELL_ENABLED", false),
|
|
56
66
|
shellAllowedUsers: optionalList("SHELL_ALLOWED_USERS"),
|
|
57
|
-
codexSandboxMode:
|
|
58
|
-
codexApprovalPolicy:
|
|
59
|
-
codexNetworkAccessEnabled: optionalBool("CODEX_NETWORK_ACCESS_ENABLED",
|
|
60
|
-
codexWebSearchMode:
|
|
61
|
-
codexReasoningEffort:
|
|
67
|
+
codexSandboxMode: optionalEnum("CODEX_SANDBOX_MODE", "workspace-write", ["read-only", "workspace-write", "danger-full-access"]),
|
|
68
|
+
codexApprovalPolicy: optionalEnum("CODEX_APPROVAL_POLICY", "on-failure", ["never", "on-request", "on-failure", "untrusted"]),
|
|
69
|
+
codexNetworkAccessEnabled: optionalBool("CODEX_NETWORK_ACCESS_ENABLED", true),
|
|
70
|
+
codexWebSearchMode: optionalEnum("CODEX_WEB_SEARCH", "live", ["disabled", "cached", "live"]),
|
|
71
|
+
codexReasoningEffort: optionalEnum("CODEX_REASONING_EFFORT", "", ["", "minimal", "low", "medium", "high", "xhigh"]),
|
|
62
72
|
codexBaseUrl: optional("CODEX_BASE_URL", ""),
|
|
63
73
|
codexApiKey: optional("CODEX_API_KEY", ""),
|
|
64
74
|
codexPath: optional("CODEX_PATH", ""),
|
|
65
75
|
anthropicApiKey: optional("ANTHROPIC_API_KEY", ""),
|
|
66
76
|
anthropicBaseUrl: optional("ANTHROPIC_BASE_URL", ""),
|
|
67
77
|
sessionSyncIntervalMs: optionalInt("SESSION_SYNC_INTERVAL_MS", 3e4),
|
|
78
|
+
sessionSyncRecentDays: optionalInt("SESSION_SYNC_RECENT_DAYS", 3),
|
|
68
79
|
healthReportIntervalMs: optionalInt("HEALTH_REPORT_INTERVAL_MS", 6e5),
|
|
69
80
|
healthReportEnabled: optionalBool("HEALTH_REPORT_ENABLED", true),
|
|
70
81
|
healthCheckStuckThresholdMs: optionalInt("HEALTH_CHECK_STUCK_THRESHOLD_MS", 18e5),
|
|
71
|
-
healthCheckIdleThresholdMs: optionalInt("HEALTH_CHECK_IDLE_THRESHOLD_MS", 72e5)
|
|
82
|
+
healthCheckIdleThresholdMs: optionalInt("HEALTH_CHECK_IDLE_THRESHOLD_MS", 72e5),
|
|
83
|
+
hookSecret: optional("HOOK_SECRET", "")
|
|
72
84
|
};
|
|
73
85
|
if (config.anthropicApiKey) process.env.ANTHROPIC_API_KEY = config.anthropicApiKey;
|
|
74
86
|
if (config.anthropicBaseUrl) process.env.ANTHROPIC_BASE_URL = config.anthropicBaseUrl;
|
|
75
87
|
if (config.allowedUsers.length === 0 && !config.allowAllUsers) {
|
|
76
88
|
if (process.env.NODE_ENV !== "test" && process.env.VITEST !== "true") {
|
|
77
|
-
console.error("ERROR:
|
|
89
|
+
console.error("ERROR: no users are allowed because neither ALLOWED_USERS nor ALLOW_ALL_USERS is configured");
|
|
78
90
|
process.exit(1);
|
|
79
91
|
}
|
|
80
92
|
}
|