workspacecord 1.0.2
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/LICENSE +21 -0
- package/README.md +190 -0
- package/README.zh-CN.md +190 -0
- package/dist/bot-B5HN4ZW6.js +6710 -0
- package/dist/chunk-2LBNM64L.js +84 -0
- package/dist/chunk-K3NQKI34.js +10 -0
- package/dist/chunk-NIXZJTOZ.js +175 -0
- package/dist/chunk-OKI4UVGY.js +221 -0
- package/dist/chunk-TSBM3BNT.js +1224 -0
- package/dist/chunk-WE4X3JB3.js +130 -0
- package/dist/cli.js +71 -0
- package/dist/codex-launcher-IF2IPLBP.js +132 -0
- package/dist/codex-provider-7CI5W34X.js +304 -0
- package/dist/config-cli-F2B5SYHJ.js +120 -0
- package/dist/daemon-NW4WRMQK.js +252 -0
- package/dist/project-cli-FEMPZIRQ.js +121 -0
- package/dist/project-registry-DQT5ORUU.js +32 -0
- package/dist/setup-TKOVXSME.js +262 -0
- package/dist/thread-manager-5T46QTZF.js +78 -0
- package/dist/utils-72GMT2X5.js +36 -0
- package/package.json +79 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
getConfigValue,
|
|
4
|
+
setConfigValue
|
|
5
|
+
} from "./chunk-OKI4UVGY.js";
|
|
6
|
+
import "./chunk-K3NQKI34.js";
|
|
7
|
+
|
|
8
|
+
// src/setup.ts
|
|
9
|
+
import * as p from "@clack/prompts";
|
|
10
|
+
import "fs";
|
|
11
|
+
import "path";
|
|
12
|
+
import { execSync } from "child_process";
|
|
13
|
+
function color(text2, code) {
|
|
14
|
+
return `\x1B[${code}m${text2}\x1B[0m`;
|
|
15
|
+
}
|
|
16
|
+
var dim = (t) => color(t, 2);
|
|
17
|
+
var cyan = (t) => color(t, 36);
|
|
18
|
+
var green = (t) => color(t, 32);
|
|
19
|
+
var yellow = (t) => color(t, 33);
|
|
20
|
+
var bold = (t) => color(t, 1);
|
|
21
|
+
function cancelled() {
|
|
22
|
+
p.cancel("Setup cancelled.");
|
|
23
|
+
process.exit(0);
|
|
24
|
+
}
|
|
25
|
+
async function runSetup() {
|
|
26
|
+
const isReconfigure = !!getConfigValue("DISCORD_TOKEN");
|
|
27
|
+
p.intro(bold(" workspacecord setup "));
|
|
28
|
+
if (isReconfigure) {
|
|
29
|
+
p.note(
|
|
30
|
+
"Existing configuration detected.\nYour current values will be shown as defaults.",
|
|
31
|
+
"Reconfiguring"
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
const hasApp = await p.confirm({
|
|
35
|
+
message: "Do you already have a Discord Application created?",
|
|
36
|
+
initialValue: isReconfigure
|
|
37
|
+
});
|
|
38
|
+
if (p.isCancel(hasApp)) cancelled();
|
|
39
|
+
if (!hasApp) {
|
|
40
|
+
p.note(
|
|
41
|
+
[
|
|
42
|
+
`${bold("1.")} Go to ${cyan("https://discord.com/developers/applications")}`,
|
|
43
|
+
`${bold("2.")} Click ${green('"New Application"')} and give it a name`,
|
|
44
|
+
`${bold("3.")} Go to the ${bold("Bot")} tab on the left`,
|
|
45
|
+
`${bold("4.")} Click ${green('"Reset Token"')} and copy the token`,
|
|
46
|
+
`${bold("5.")} Under ${bold("Privileged Gateway Intents")}, enable:`,
|
|
47
|
+
` ${yellow("*")} Message Content Intent`,
|
|
48
|
+
` ${yellow("*")} Server Members Intent`,
|
|
49
|
+
`${bold("6.")} Go to the ${bold("General Information")} tab`,
|
|
50
|
+
`${bold("7.")} Copy the ${bold("Application ID")} (this is your Client ID)`,
|
|
51
|
+
"",
|
|
52
|
+
dim("Keep this tab open \u2014 you'll need the token and ID next.")
|
|
53
|
+
].join("\n"),
|
|
54
|
+
"Create a Discord App"
|
|
55
|
+
);
|
|
56
|
+
await p.confirm({
|
|
57
|
+
message: "Ready to continue?",
|
|
58
|
+
initialValue: true
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
const token = await p.password({
|
|
62
|
+
message: "Paste your Discord Bot Token:",
|
|
63
|
+
validate(value) {
|
|
64
|
+
if (!value || !value.trim()) return "Token is required";
|
|
65
|
+
if (value.length < 50) return "That doesn't look like a valid bot token";
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
if (p.isCancel(token)) cancelled();
|
|
69
|
+
const clientId = await p.text({
|
|
70
|
+
message: "Paste your Application (Client) ID:",
|
|
71
|
+
placeholder: getConfigValue("DISCORD_CLIENT_ID") || "123456789012345678",
|
|
72
|
+
initialValue: getConfigValue("DISCORD_CLIENT_ID"),
|
|
73
|
+
validate(value) {
|
|
74
|
+
if (!value || !value.trim()) return "Client ID is required";
|
|
75
|
+
if (!/^\d{17,20}$/.test(value.trim())) return "Client ID should be a 17-20 digit number";
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
if (p.isCancel(clientId)) cancelled();
|
|
79
|
+
const guildSetup = await p.confirm({
|
|
80
|
+
message: "Do you want to register commands to a specific server? (instant, recommended for testing)",
|
|
81
|
+
initialValue: !!getConfigValue("DISCORD_GUILD_ID")
|
|
82
|
+
});
|
|
83
|
+
if (p.isCancel(guildSetup)) cancelled();
|
|
84
|
+
let guildId = "";
|
|
85
|
+
if (guildSetup) {
|
|
86
|
+
if (!hasApp) {
|
|
87
|
+
p.note(
|
|
88
|
+
[
|
|
89
|
+
`${bold("1.")} Open Discord and go to ${bold("User Settings > Advanced")}`,
|
|
90
|
+
`${bold("2.")} Enable ${green('"Developer Mode"')}`,
|
|
91
|
+
`${bold("3.")} Right-click your server name and click ${green('"Copy Server ID"')}`
|
|
92
|
+
].join("\n"),
|
|
93
|
+
"How to get your Server ID"
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
const guildInput = await p.text({
|
|
97
|
+
message: "Paste your Server (Guild) ID:",
|
|
98
|
+
placeholder: getConfigValue("DISCORD_GUILD_ID") || "123456789012345678",
|
|
99
|
+
initialValue: getConfigValue("DISCORD_GUILD_ID"),
|
|
100
|
+
validate(value) {
|
|
101
|
+
if (!value || !value.trim()) return "Guild ID is required";
|
|
102
|
+
if (!/^\d{17,20}$/.test(value.trim())) return "Guild ID should be a 17-20 digit number";
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
if (p.isCancel(guildInput)) cancelled();
|
|
106
|
+
guildId = guildInput.trim();
|
|
107
|
+
}
|
|
108
|
+
const existingAllowAllUsers = getConfigValue("ALLOW_ALL_USERS") === "true";
|
|
109
|
+
const authMode = await p.select({
|
|
110
|
+
message: "Who should be allowed to use the bot?",
|
|
111
|
+
options: [
|
|
112
|
+
{
|
|
113
|
+
value: "whitelist",
|
|
114
|
+
label: "Specific users (recommended)",
|
|
115
|
+
hint: "comma-separated Discord user IDs"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
value: "all",
|
|
119
|
+
label: "Everyone in the server",
|
|
120
|
+
hint: "not recommended for shared servers"
|
|
121
|
+
}
|
|
122
|
+
],
|
|
123
|
+
initialValue: existingAllowAllUsers ? "all" : "whitelist"
|
|
124
|
+
});
|
|
125
|
+
if (p.isCancel(authMode)) cancelled();
|
|
126
|
+
let allowedUsers = "";
|
|
127
|
+
if (authMode === "whitelist") {
|
|
128
|
+
if (!hasApp && !getConfigValue("ALLOWED_USERS")) {
|
|
129
|
+
p.note(
|
|
130
|
+
[
|
|
131
|
+
`${bold("1.")} Open Discord with ${bold("Developer Mode")} enabled`,
|
|
132
|
+
`${bold("2.")} Click on your profile picture or username`,
|
|
133
|
+
`${bold("3.")} Click ${green('"Copy User ID"')}`,
|
|
134
|
+
"",
|
|
135
|
+
dim("You can add more users later with: workspacecord config set ALLOWED_USERS <ids>")
|
|
136
|
+
].join("\n"),
|
|
137
|
+
"How to get your User ID"
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
const usersInput = await p.text({
|
|
141
|
+
message: "Enter allowed Discord User IDs (comma-separated):",
|
|
142
|
+
placeholder: "123456789012345678",
|
|
143
|
+
initialValue: getConfigValue("ALLOWED_USERS"),
|
|
144
|
+
validate(value) {
|
|
145
|
+
if (!value || !value.trim()) return "At least one user ID is required";
|
|
146
|
+
const ids = value.split(",").map((s2) => s2.trim());
|
|
147
|
+
for (const id of ids) {
|
|
148
|
+
if (!/^\d{17,20}$/.test(id)) return `Invalid user ID: ${id}`;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
if (p.isCancel(usersInput)) cancelled();
|
|
153
|
+
allowedUsers = usersInput.trim();
|
|
154
|
+
}
|
|
155
|
+
const s = p.spinner();
|
|
156
|
+
s.start("Saving configuration...");
|
|
157
|
+
setConfigValue("DISCORD_TOKEN", token.trim());
|
|
158
|
+
setConfigValue("DISCORD_CLIENT_ID", clientId.trim());
|
|
159
|
+
if (guildId) setConfigValue("DISCORD_GUILD_ID", guildId);
|
|
160
|
+
if (authMode === "all") {
|
|
161
|
+
setConfigValue("ALLOW_ALL_USERS", "true");
|
|
162
|
+
} else {
|
|
163
|
+
setConfigValue("ALLOWED_USERS", allowedUsers);
|
|
164
|
+
setConfigValue("ALLOW_ALL_USERS", "false");
|
|
165
|
+
}
|
|
166
|
+
s.stop("Configuration saved to global store");
|
|
167
|
+
const permissions = 8;
|
|
168
|
+
const scopes = "bot%20applications.commands";
|
|
169
|
+
const inviteUrl = `https://discord.com/oauth2/authorize?client_id=${clientId.trim()}&permissions=${permissions}&scope=${scopes}`;
|
|
170
|
+
p.note(
|
|
171
|
+
[
|
|
172
|
+
bold("Add the bot to your server:"),
|
|
173
|
+
"",
|
|
174
|
+
cyan(inviteUrl),
|
|
175
|
+
"",
|
|
176
|
+
dim("Open this URL in your browser and select your server.")
|
|
177
|
+
].join("\n"),
|
|
178
|
+
"Invite Link"
|
|
179
|
+
);
|
|
180
|
+
const openBrowser = await p.confirm({
|
|
181
|
+
message: "Open the invite URL in your browser?",
|
|
182
|
+
initialValue: true
|
|
183
|
+
});
|
|
184
|
+
if (p.isCancel(openBrowser)) cancelled();
|
|
185
|
+
if (openBrowser) {
|
|
186
|
+
try {
|
|
187
|
+
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
188
|
+
execSync(`${cmd} "${inviteUrl}"`, { stdio: "ignore" });
|
|
189
|
+
} catch {
|
|
190
|
+
p.log.warn("Could not open browser. Please open the URL manually.");
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
const verify = await p.confirm({
|
|
194
|
+
message: "Test the bot connection now?",
|
|
195
|
+
initialValue: true
|
|
196
|
+
});
|
|
197
|
+
if (p.isCancel(verify)) cancelled();
|
|
198
|
+
if (verify) {
|
|
199
|
+
s.start("Connecting to Discord...");
|
|
200
|
+
try {
|
|
201
|
+
const { Client, GatewayIntentBits } = await import("discord.js");
|
|
202
|
+
const client = new Client({
|
|
203
|
+
intents: [GatewayIntentBits.Guilds]
|
|
204
|
+
});
|
|
205
|
+
const loginResult = await Promise.race([
|
|
206
|
+
new Promise((res, rej) => {
|
|
207
|
+
client.once("ready", () => {
|
|
208
|
+
const name = client.user?.tag || "Unknown";
|
|
209
|
+
const guildCount = client.guilds.cache.size;
|
|
210
|
+
client.destroy();
|
|
211
|
+
res(`${name} \u2014 connected to ${guildCount} server(s)`);
|
|
212
|
+
});
|
|
213
|
+
client.login(token.trim()).catch(rej);
|
|
214
|
+
}),
|
|
215
|
+
new Promise(
|
|
216
|
+
(_, rej) => setTimeout(() => rej(new Error("Connection timed out after 15s")), 15e3)
|
|
217
|
+
)
|
|
218
|
+
]);
|
|
219
|
+
s.stop(green(`Connected: ${loginResult}`));
|
|
220
|
+
} catch (err) {
|
|
221
|
+
s.stop(`Connection failed: ${err.message}`);
|
|
222
|
+
p.log.warn("Double-check your bot token and try again.");
|
|
223
|
+
p.log.info(`You can re-run setup with: ${cyan("workspacecord config setup")}`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
const installDaemon = await p.confirm({
|
|
227
|
+
message: "Start workspacecord as a background service? (auto-starts on boot, restarts on crash)",
|
|
228
|
+
initialValue: true
|
|
229
|
+
});
|
|
230
|
+
if (p.isCancel(installDaemon)) cancelled();
|
|
231
|
+
if (installDaemon) {
|
|
232
|
+
s.start("Installing background service...");
|
|
233
|
+
try {
|
|
234
|
+
const { handleDaemon } = await import("./daemon-NW4WRMQK.js");
|
|
235
|
+
await handleDaemon("install");
|
|
236
|
+
s.stop(green("Background service installed and running"));
|
|
237
|
+
} catch (err) {
|
|
238
|
+
s.stop(`Service install failed: ${err.message}`);
|
|
239
|
+
p.log.warn(`You can install it later with: ${cyan("workspacecord daemon install")}`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
const nextSteps = [
|
|
243
|
+
`Use ${bold("/project setup project:<name>")} and ${bold("/agent spawn label:<task>")} in Discord to create your first session.`
|
|
244
|
+
];
|
|
245
|
+
if (!installDaemon) {
|
|
246
|
+
nextSteps.unshift(`Start the bot: ${cyan("workspacecord")}`, "");
|
|
247
|
+
} else {
|
|
248
|
+
nextSteps.unshift(
|
|
249
|
+
`The bot is running in the background.`,
|
|
250
|
+
`Check status: ${cyan("workspacecord daemon status")}`,
|
|
251
|
+
`View logs: ${cyan("tail -f ~/.workspacecord/workspacecord.log")}`,
|
|
252
|
+
""
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
nextSteps.push("", `Re-run setup: ${cyan("workspacecord config setup")}`);
|
|
256
|
+
nextSteps.push(`View config: ${cyan("workspacecord config list")}`);
|
|
257
|
+
p.note(nextSteps.join("\n"), "Next Steps");
|
|
258
|
+
p.outro(green("Setup complete!"));
|
|
259
|
+
}
|
|
260
|
+
export {
|
|
261
|
+
runSetup
|
|
262
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
abortSession,
|
|
4
|
+
abortSessionWithReason,
|
|
5
|
+
consumeAbortReason,
|
|
6
|
+
continueSession,
|
|
7
|
+
continueSessionWithOverrides,
|
|
8
|
+
createSession,
|
|
9
|
+
endSession,
|
|
10
|
+
findCodexSessionByCwd,
|
|
11
|
+
findCodexSessionByProviderSessionId,
|
|
12
|
+
findCodexSessionForMonitor,
|
|
13
|
+
getAllSessions,
|
|
14
|
+
getSession,
|
|
15
|
+
getSessionByChannel,
|
|
16
|
+
getSessionByCodexId,
|
|
17
|
+
getSessionByProviderSession,
|
|
18
|
+
getSessionByProviderSessionId,
|
|
19
|
+
getSessionByThread,
|
|
20
|
+
getSessionsByCategory,
|
|
21
|
+
loadSessions,
|
|
22
|
+
registerLocalSession,
|
|
23
|
+
resetWorkflowState,
|
|
24
|
+
resolveCodexSessionFromMonitor,
|
|
25
|
+
sendMonitorPrompt,
|
|
26
|
+
sendPrompt,
|
|
27
|
+
setAgentPersona,
|
|
28
|
+
setCurrentInteractionMessage,
|
|
29
|
+
setMode,
|
|
30
|
+
setModel,
|
|
31
|
+
setMonitorGoal,
|
|
32
|
+
setStatusCardBinding,
|
|
33
|
+
setVerbose,
|
|
34
|
+
updateLocalObservation,
|
|
35
|
+
updateSession,
|
|
36
|
+
updateWorkflowState
|
|
37
|
+
} from "./chunk-TSBM3BNT.js";
|
|
38
|
+
import "./chunk-2LBNM64L.js";
|
|
39
|
+
import "./chunk-OKI4UVGY.js";
|
|
40
|
+
import "./chunk-NIXZJTOZ.js";
|
|
41
|
+
import "./chunk-WE4X3JB3.js";
|
|
42
|
+
import "./chunk-K3NQKI34.js";
|
|
43
|
+
export {
|
|
44
|
+
abortSession,
|
|
45
|
+
abortSessionWithReason,
|
|
46
|
+
consumeAbortReason,
|
|
47
|
+
continueSession,
|
|
48
|
+
continueSessionWithOverrides,
|
|
49
|
+
createSession,
|
|
50
|
+
endSession,
|
|
51
|
+
findCodexSessionByCwd,
|
|
52
|
+
findCodexSessionByProviderSessionId,
|
|
53
|
+
findCodexSessionForMonitor,
|
|
54
|
+
getAllSessions,
|
|
55
|
+
getSession,
|
|
56
|
+
getSessionByChannel,
|
|
57
|
+
getSessionByCodexId,
|
|
58
|
+
getSessionByProviderSession,
|
|
59
|
+
getSessionByProviderSessionId,
|
|
60
|
+
getSessionByThread,
|
|
61
|
+
getSessionsByCategory,
|
|
62
|
+
loadSessions,
|
|
63
|
+
registerLocalSession,
|
|
64
|
+
resetWorkflowState,
|
|
65
|
+
resolveCodexSessionFromMonitor,
|
|
66
|
+
sendMonitorPrompt,
|
|
67
|
+
sendPrompt,
|
|
68
|
+
setAgentPersona,
|
|
69
|
+
setCurrentInteractionMessage,
|
|
70
|
+
setMode,
|
|
71
|
+
setModel,
|
|
72
|
+
setMonitorGoal,
|
|
73
|
+
setStatusCardBinding,
|
|
74
|
+
setVerbose,
|
|
75
|
+
updateLocalObservation,
|
|
76
|
+
updateSession,
|
|
77
|
+
updateWorkflowState
|
|
78
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
detectNumberedOptions,
|
|
4
|
+
detectYesNoPrompt,
|
|
5
|
+
formatCost,
|
|
6
|
+
formatDuration,
|
|
7
|
+
formatRelative,
|
|
8
|
+
formatUptime,
|
|
9
|
+
isAbortError,
|
|
10
|
+
isAbortErrorMessage,
|
|
11
|
+
isPathAllowed,
|
|
12
|
+
isUserAllowed,
|
|
13
|
+
projectNameFromChannel,
|
|
14
|
+
resolvePath,
|
|
15
|
+
sanitizeName,
|
|
16
|
+
splitMessage,
|
|
17
|
+
truncate
|
|
18
|
+
} from "./chunk-WE4X3JB3.js";
|
|
19
|
+
import "./chunk-K3NQKI34.js";
|
|
20
|
+
export {
|
|
21
|
+
detectNumberedOptions,
|
|
22
|
+
detectYesNoPrompt,
|
|
23
|
+
formatCost,
|
|
24
|
+
formatDuration,
|
|
25
|
+
formatRelative,
|
|
26
|
+
formatUptime,
|
|
27
|
+
isAbortError,
|
|
28
|
+
isAbortErrorMessage,
|
|
29
|
+
isPathAllowed,
|
|
30
|
+
isUserAllowed,
|
|
31
|
+
projectNameFromChannel,
|
|
32
|
+
resolvePath,
|
|
33
|
+
sanitizeName,
|
|
34
|
+
splitMessage,
|
|
35
|
+
truncate
|
|
36
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "workspacecord",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "Turn Discord into a local workspace control plane for multi-agent coding sessions.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/xuhongbo/WorkspaceCord.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/xuhongbo/WorkspaceCord#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/xuhongbo/WorkspaceCord/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"discord",
|
|
17
|
+
"bot",
|
|
18
|
+
"ai",
|
|
19
|
+
"claude",
|
|
20
|
+
"codex",
|
|
21
|
+
"coding-assistant",
|
|
22
|
+
"agent",
|
|
23
|
+
"multi-agent",
|
|
24
|
+
"cli"
|
|
25
|
+
],
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"README.md",
|
|
29
|
+
"README.zh-CN.md",
|
|
30
|
+
"LICENSE"
|
|
31
|
+
],
|
|
32
|
+
"bin": {
|
|
33
|
+
"workspacecord": "./dist/cli.js",
|
|
34
|
+
"wsc": "./dist/cli.js"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@anthropic-ai/claude-agent-sdk": "^0.2.85",
|
|
38
|
+
"@clack/prompts": "^1.1.0",
|
|
39
|
+
"configstore": "^8.0.0",
|
|
40
|
+
"discord.js": "^14.25.1",
|
|
41
|
+
"execa": "^9.6.1",
|
|
42
|
+
"sharp": "^0.34.5"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@eslint/js": "^10.0.1",
|
|
46
|
+
"@types/configstore": "^6.0.2",
|
|
47
|
+
"@types/node": "^25.5.0",
|
|
48
|
+
"eslint": "^10.1.0",
|
|
49
|
+
"eslint-config-prettier": "^10.1.8",
|
|
50
|
+
"globals": "^17.4.0",
|
|
51
|
+
"prettier": "^3.8.1",
|
|
52
|
+
"tsup": "^8.5.1",
|
|
53
|
+
"typescript": "^6.0.2",
|
|
54
|
+
"typescript-eslint": "^8.57.2",
|
|
55
|
+
"vitest": "^4.1.2"
|
|
56
|
+
},
|
|
57
|
+
"optionalDependencies": {
|
|
58
|
+
"@openai/codex-sdk": "^0.117.0"
|
|
59
|
+
},
|
|
60
|
+
"engines": {
|
|
61
|
+
"node": ">=22.6.0"
|
|
62
|
+
},
|
|
63
|
+
"scripts": {
|
|
64
|
+
"build": "tsup",
|
|
65
|
+
"start": "node --experimental-strip-types src/cli.ts",
|
|
66
|
+
"dev": "tsup --watch",
|
|
67
|
+
"typecheck": "tsc --noEmit",
|
|
68
|
+
"test": "vitest run",
|
|
69
|
+
"test:integration:smoke": "node --experimental-strip-types scripts/integration-smoke.ts",
|
|
70
|
+
"test:multi-session:smoke": "node --experimental-strip-types scripts/multi-session-smoke.ts",
|
|
71
|
+
"test:session-sync:smoke": "node --experimental-strip-types scripts/session-sync-smoke.ts",
|
|
72
|
+
"test:monitor:e2e": "node --experimental-strip-types scripts/monitor-e2e.ts",
|
|
73
|
+
"test:acceptance:local": "node --experimental-strip-types scripts/local-acceptance-suite.ts",
|
|
74
|
+
"lint": "eslint .",
|
|
75
|
+
"lint:fix": "eslint . --fix",
|
|
76
|
+
"format": "prettier --write .",
|
|
77
|
+
"format:check": "prettier --check ."
|
|
78
|
+
}
|
|
79
|
+
}
|