sparkecoder 0.1.107 → 0.1.109
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/agent/index.d.ts +3 -3
- package/dist/agent/index.js +14 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/cli.js +109 -12
- package/dist/cli.js.map +1 -1
- package/dist/db/index.d.ts +2 -2
- package/dist/{index-D5l-DMGC.d.ts → index-Biy5JTop.d.ts} +96 -83
- package/dist/index.d.ts +5 -5
- package/dist/index.js +87 -10
- package/dist/index.js.map +1 -1
- package/dist/{schema-ecQSnCMz.d.ts → schema-CYSKJZ3m.d.ts} +3 -3
- package/dist/{search-DOzC4ojH.d.ts → search-CVVfuBPZ.d.ts} +4 -4
- package/dist/server/index.js +87 -10
- package/dist/server/index.js.map +1 -1
- package/dist/tools/index.d.ts +3 -3
- package/dist/tools/index.js +8 -0
- package/dist/tools/index.js.map +1 -1
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.html +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p/agents/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p/agents.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.html +1 -1
- package/web/.next/standalone/web/.next/server/app/index.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.html +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
- package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
- /package/web/.next/standalone/web/.next/static/{9B80CeRYeYvnsEougmuLs → 56Y89huUkFkd-4Ip1HcYY}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{9B80CeRYeYvnsEougmuLs → 56Y89huUkFkd-4Ip1HcYY}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/{9B80CeRYeYvnsEougmuLs → 56Y89huUkFkd-4Ip1HcYY}/_ssgManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{9B80CeRYeYvnsEougmuLs → 56Y89huUkFkd-4Ip1HcYY}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{9B80CeRYeYvnsEougmuLs → 56Y89huUkFkd-4Ip1HcYY}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/static/{9B80CeRYeYvnsEougmuLs → 56Y89huUkFkd-4Ip1HcYY}/_ssgManifest.js +0 -0
- /package/web/.next/static/{9B80CeRYeYvnsEougmuLs → 56Y89huUkFkd-4Ip1HcYY}/_buildManifest.js +0 -0
- /package/web/.next/static/{9B80CeRYeYvnsEougmuLs → 56Y89huUkFkd-4Ip1HcYY}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{9B80CeRYeYvnsEougmuLs → 56Y89huUkFkd-4Ip1HcYY}/_ssgManifest.js +0 -0
package/dist/cli.js
CHANGED
|
@@ -854,6 +854,14 @@ var init_types = __esm({
|
|
|
854
854
|
// If not set, defaults to http://{host}:{port}
|
|
855
855
|
publicUrl: z.string().url().optional()
|
|
856
856
|
}).default({ port: 3141, host: "127.0.0.1" }),
|
|
857
|
+
// Per-tunnel unguessable webhook URL prefix. Set by
|
|
858
|
+
// `cloudflared-setup --remote` from the response of POST
|
|
859
|
+
// /tunnels/ensure. When present, the local server mounts public
|
|
860
|
+
// inbound webhooks (Slack events, inbox) under /w/<token>/...
|
|
861
|
+
// instead of /api/*. When absent, falls back to /api/*.
|
|
862
|
+
webhooks: z.object({
|
|
863
|
+
token: z.string().optional()
|
|
864
|
+
}).optional(),
|
|
857
865
|
// Database path (used for local SQLite - ignored if remoteServer is configured)
|
|
858
866
|
databasePath: z.string().optional().default("./sparkecoder.db"),
|
|
859
867
|
// Remote server configuration (for centralized storage)
|
|
@@ -961,7 +969,9 @@ __export(config_exports, {
|
|
|
961
969
|
saveAuthKey: () => saveAuthKey,
|
|
962
970
|
setApiKey: () => setApiKey,
|
|
963
971
|
setMcpServers: () => setMcpServers,
|
|
964
|
-
|
|
972
|
+
setPublicUrl: () => setPublicUrl,
|
|
973
|
+
setSlackConfig: () => setSlackConfig,
|
|
974
|
+
setWebhookToken: () => setWebhookToken
|
|
965
975
|
});
|
|
966
976
|
import { existsSync, readFileSync, mkdirSync, writeFileSync } from "fs";
|
|
967
977
|
import { resolve, dirname, join } from "path";
|
|
@@ -1223,6 +1233,55 @@ function setMcpServers(servers2) {
|
|
|
1223
1233
|
console.warn("[config] failed to persist mcp config:", err?.message || err);
|
|
1224
1234
|
}
|
|
1225
1235
|
}
|
|
1236
|
+
function setWebhookToken(token) {
|
|
1237
|
+
if (cachedConfig) {
|
|
1238
|
+
cachedConfig.webhooks = {
|
|
1239
|
+
...cachedConfig.webhooks ?? {},
|
|
1240
|
+
token
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1243
|
+
try {
|
|
1244
|
+
const cwdPath = resolve(process.cwd(), "sparkecoder.config.json");
|
|
1245
|
+
const target = existsSync(cwdPath) ? cwdPath : join(ensureAppDataDirectory(), "sparkecoder.config.json");
|
|
1246
|
+
let raw = {};
|
|
1247
|
+
if (existsSync(target)) {
|
|
1248
|
+
try {
|
|
1249
|
+
raw = JSON.parse(readFileSync(target, "utf-8"));
|
|
1250
|
+
} catch {
|
|
1251
|
+
raw = {};
|
|
1252
|
+
}
|
|
1253
|
+
} else {
|
|
1254
|
+
raw = createDefaultConfig();
|
|
1255
|
+
}
|
|
1256
|
+
raw.webhooks = { ...raw.webhooks || {}, token };
|
|
1257
|
+
writeFileSync(target, JSON.stringify(raw, null, 2));
|
|
1258
|
+
} catch (err) {
|
|
1259
|
+
console.warn("[config] failed to persist webhook token:", err?.message || err);
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
function setPublicUrl(publicUrl) {
|
|
1263
|
+
if (cachedConfig) {
|
|
1264
|
+
cachedConfig.server = { ...cachedConfig.server ?? {}, publicUrl };
|
|
1265
|
+
}
|
|
1266
|
+
try {
|
|
1267
|
+
const cwdPath = resolve(process.cwd(), "sparkecoder.config.json");
|
|
1268
|
+
const target = existsSync(cwdPath) ? cwdPath : join(ensureAppDataDirectory(), "sparkecoder.config.json");
|
|
1269
|
+
let raw = {};
|
|
1270
|
+
if (existsSync(target)) {
|
|
1271
|
+
try {
|
|
1272
|
+
raw = JSON.parse(readFileSync(target, "utf-8"));
|
|
1273
|
+
} catch {
|
|
1274
|
+
raw = {};
|
|
1275
|
+
}
|
|
1276
|
+
} else {
|
|
1277
|
+
raw = createDefaultConfig();
|
|
1278
|
+
}
|
|
1279
|
+
raw.server = { ...raw.server || {}, publicUrl };
|
|
1280
|
+
writeFileSync(target, JSON.stringify(raw, null, 2));
|
|
1281
|
+
} catch (err) {
|
|
1282
|
+
console.warn("[config] failed to persist publicUrl:", err?.message || err);
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1226
1285
|
function clearSlackConfig() {
|
|
1227
1286
|
if (cachedConfig) cachedConfig.slack = {};
|
|
1228
1287
|
try {
|
|
@@ -9557,7 +9616,9 @@ function buildScheduleTool(opts) {
|
|
|
9557
9616
|
}
|
|
9558
9617
|
function buildWebhookUrl(opts, token) {
|
|
9559
9618
|
const base = opts.publicBaseUrl?.replace(/\/$/, "") || opts.baseUrl.replace(/\/$/, "");
|
|
9560
|
-
|
|
9619
|
+
const cfg = getConfig();
|
|
9620
|
+
const webhookPrefix2 = cfg?.webhooks?.token ? `/w/${cfg.webhooks.token}` : "/api";
|
|
9621
|
+
return `${base}${webhookPrefix2}/inbox/${token}`;
|
|
9561
9622
|
}
|
|
9562
9623
|
function buildWebhookTool(opts) {
|
|
9563
9624
|
return tool14({
|
|
@@ -9607,6 +9668,7 @@ var init_orchestrator_actions = __esm({
|
|
|
9607
9668
|
"use strict";
|
|
9608
9669
|
init_messenger();
|
|
9609
9670
|
init_schedules_store();
|
|
9671
|
+
init_config();
|
|
9610
9672
|
init_webhooks_store();
|
|
9611
9673
|
AGENT_STATUS_ENUM = z15.enum(["running", "needs_attention", "completed", "failed", "idle"]);
|
|
9612
9674
|
agentInputSchema = z15.object({
|
|
@@ -14656,8 +14718,8 @@ async function findOrCreateOrchestratorId() {
|
|
|
14656
14718
|
const all = await sessionQueries.list(500, 0);
|
|
14657
14719
|
const existing = all.find((s) => s.config?.role === "orchestrator");
|
|
14658
14720
|
if (existing) return existing.id;
|
|
14659
|
-
const { getConfig:
|
|
14660
|
-
const cfg =
|
|
14721
|
+
const { getConfig: getConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
14722
|
+
const cfg = getConfig2();
|
|
14661
14723
|
const created = await sessionQueries.create({
|
|
14662
14724
|
name: getDefaultOrchestratorName() || "Orchestrator",
|
|
14663
14725
|
workingDirectory: cfg.resolvedWorkingDirectory,
|
|
@@ -14782,6 +14844,11 @@ function publicBase() {
|
|
|
14782
14844
|
const cfg = getConfig();
|
|
14783
14845
|
return cfg.server?.publicUrl?.replace(/\/$/, "") || `http://${cfg.server?.host || "127.0.0.1"}:${cfg.server?.port || 3141}`;
|
|
14784
14846
|
}
|
|
14847
|
+
function webhookPrefix() {
|
|
14848
|
+
const cfg = getConfig();
|
|
14849
|
+
const token = cfg?.webhooks?.token;
|
|
14850
|
+
return token ? `/w/${token}` : "/api";
|
|
14851
|
+
}
|
|
14785
14852
|
integrations.get("/", async (c) => {
|
|
14786
14853
|
const cfg = getConfig();
|
|
14787
14854
|
return c.json({
|
|
@@ -14791,7 +14858,7 @@ integrations.get("/", async (c) => {
|
|
|
14791
14858
|
botTokenSet: !!cfg?.slack?.botToken,
|
|
14792
14859
|
signingSecretSet: !!cfg?.slack?.signingSecret,
|
|
14793
14860
|
defaultOrchestratorName: cfg?.slack?.defaultOrchestratorName || null,
|
|
14794
|
-
eventsUrl: `${publicBase()}/
|
|
14861
|
+
eventsUrl: `${publicBase()}${webhookPrefix()}/slack/events`,
|
|
14795
14862
|
allowedUsers: cfg?.slack?.allowedUsers ?? [],
|
|
14796
14863
|
allowedChannels: cfg?.slack?.allowedChannels ?? [],
|
|
14797
14864
|
allowDmsFromAnyone: cfg?.slack?.allowDmsFromAnyone !== false,
|
|
@@ -14884,7 +14951,7 @@ schedulesRouter.delete("/:id", async (c) => {
|
|
|
14884
14951
|
});
|
|
14885
14952
|
var webhooksRouter = new Hono8();
|
|
14886
14953
|
function withUrl(row) {
|
|
14887
|
-
return { ...row, url: `${publicBase()}/
|
|
14954
|
+
return { ...row, url: `${publicBase()}${webhookPrefix()}/inbox/${row.token}` };
|
|
14888
14955
|
}
|
|
14889
14956
|
webhooksRouter.get("/", async (c) => {
|
|
14890
14957
|
const orcId = await getOrchestratorId();
|
|
@@ -14987,7 +15054,7 @@ mcpRouter.post("/:id/test", async (c) => {
|
|
|
14987
15054
|
// src/server/auth/cf-access.ts
|
|
14988
15055
|
init_config();
|
|
14989
15056
|
import { createRemoteJWKSet, jwtVerify } from "jose";
|
|
14990
|
-
var EXEMPT_PATH_PREFIXES = ["/health", "/api/slack/events", "/api/inbox/"];
|
|
15057
|
+
var EXEMPT_PATH_PREFIXES = ["/health", "/api/slack/events", "/api/inbox/", "/w/"];
|
|
14991
15058
|
var cachedJWKS = null;
|
|
14992
15059
|
var cachedJWKSUrl = null;
|
|
14993
15060
|
function getOrCreateJWKS(teamDomain) {
|
|
@@ -15512,13 +15579,23 @@ async function createApp(options = {}) {
|
|
|
15512
15579
|
app.route("/sessions", terminals);
|
|
15513
15580
|
app.route("/terminals", terminals);
|
|
15514
15581
|
app.route("/tasks", tasks_default);
|
|
15515
|
-
app.route("/api/slack", slack);
|
|
15516
|
-
app.route("/api/inbox", inbox);
|
|
15517
15582
|
app.route("/api/integrations", integrations);
|
|
15518
15583
|
app.route("/api/schedules", schedulesRouter);
|
|
15519
|
-
app.route("/api/webhooks", webhooksRouter);
|
|
15520
15584
|
app.route("/api/orchestrator", orchestratorRouter);
|
|
15521
15585
|
app.route("/api/mcp", mcpRouter);
|
|
15586
|
+
app.route("/api/webhooks", webhooksRouter);
|
|
15587
|
+
const config = getConfig();
|
|
15588
|
+
const webhookToken = config?.webhooks?.token;
|
|
15589
|
+
if (webhookToken) {
|
|
15590
|
+
app.route(`/w/${webhookToken}/slack`, slack);
|
|
15591
|
+
app.route(`/w/${webhookToken}/inbox`, inbox);
|
|
15592
|
+
if (!options.quiet) {
|
|
15593
|
+
console.log(` \u2192 Public webhooks mounted at /w/${webhookToken.slice(0, 4)}\u2026/<service>`);
|
|
15594
|
+
}
|
|
15595
|
+
} else {
|
|
15596
|
+
app.route("/api/slack", slack);
|
|
15597
|
+
app.route("/api/inbox", inbox);
|
|
15598
|
+
}
|
|
15522
15599
|
app.get("/openapi.json", async (c) => {
|
|
15523
15600
|
return c.json(generateOpenAPISpec());
|
|
15524
15601
|
});
|
|
@@ -16703,13 +16780,19 @@ program.name("sparkecoder").description("AI coding agent - just type sparkecoder
|
|
|
16703
16780
|
}
|
|
16704
16781
|
await runChat(options);
|
|
16705
16782
|
});
|
|
16706
|
-
program.command("server").description("Start the SparkECoder server (API + Web UI)").option("-p, --port <port>", "API server port", "3141").option("-h, --host <host>", "Server host", "127.0.0.1").option("-c, --config <path>", "Path to config file").option("-w, --working-dir <path>", "Working directory").option("--web-port <port>", "Web UI port", "6969").option("--no-web", "Do not start web UI").option("--public-url <url>", "Public URL for web UI to connect to API (for Docker/remote access)").option("-v, --verbose", "Enable verbose logging for web server").option("--enable-computer-use", "Enable the Anthropic computer use tool for all new sessions by default (macOS only)").action(async (options) => {
|
|
16783
|
+
program.command("server").description("Start the SparkECoder server (API + Web UI)").option("-p, --port <port>", "API server port", "3141").option("-h, --host <host>", "Server host", "127.0.0.1").option("-c, --config <path>", "Path to config file").option("-w, --working-dir <path>", "Working directory").option("--web-port <port>", "Web UI port", "6969").option("--no-web", "Do not start web UI").option("--public-url <url>", "Public URL for web UI to connect to API (for Docker/remote access)").option("-v, --verbose", "Enable verbose logging for web server").option("--enable-computer-use", "Enable the Anthropic computer use tool for all new sessions by default (macOS only)").option("--setup-secret <secret>", "Setup secret (or short-lived JWT) used for /auth/register and /tunnels when the remote server has SETUP_SECRET configured. Equivalent to setting SPARKECODER_SETUP_SECRET env.").action(async (options) => {
|
|
16707
16784
|
const globalOpts = program.opts();
|
|
16708
16785
|
const enableCU = options.enableComputerUse || globalOpts.enableComputerUse;
|
|
16709
16786
|
if (enableCU) {
|
|
16710
16787
|
process.env.SPARKECODER_COMPUTER_USE = "1";
|
|
16711
16788
|
console.log(chalk.cyan("\u2192 Computer use enabled by default for new sessions."));
|
|
16712
16789
|
}
|
|
16790
|
+
if (options.setupSecret) {
|
|
16791
|
+
process.env.SPARKECODER_SETUP_SECRET = options.setupSecret;
|
|
16792
|
+
if (!process.env.SPARKECODER_TUNNEL_SECRET) {
|
|
16793
|
+
process.env.SPARKECODER_TUNNEL_SECRET = options.setupSecret;
|
|
16794
|
+
}
|
|
16795
|
+
}
|
|
16713
16796
|
await ensureDependencies({ quiet: false });
|
|
16714
16797
|
const spinner = ora("Starting SparkECoder server...").start();
|
|
16715
16798
|
try {
|
|
@@ -17004,10 +17087,24 @@ program.command("cloudflared-setup").description("Auto-detect cloudflared + set
|
|
|
17004
17087
|
process.exitCode = 1;
|
|
17005
17088
|
return;
|
|
17006
17089
|
}
|
|
17007
|
-
const { tunnelToken, hostname: provisionedHost, apiHostname, reused } = await res.json();
|
|
17090
|
+
const { tunnelToken, hostname: provisionedHost, apiHostname, reused, webhookToken, webhookBaseUrl } = await res.json();
|
|
17008
17091
|
if (reused) {
|
|
17009
17092
|
console.log(chalk.dim("\u2713 Re-using existing tunnel \u2014 no new tunnel created on Cloudflare."));
|
|
17010
17093
|
}
|
|
17094
|
+
try {
|
|
17095
|
+
setPublicUrl(`https://${apiHostname}`);
|
|
17096
|
+
console.log(chalk.dim(`\u2713 Saved publicUrl = https://${apiHostname} into config.`));
|
|
17097
|
+
} catch (err) {
|
|
17098
|
+
console.warn(chalk.yellow(`Could not persist publicUrl: ${err?.message ?? err}`));
|
|
17099
|
+
}
|
|
17100
|
+
if (webhookToken) {
|
|
17101
|
+
try {
|
|
17102
|
+
setWebhookToken(webhookToken);
|
|
17103
|
+
console.log(chalk.dim(`\u2713 Saved webhook prefix into config: ${webhookBaseUrl ?? `https://${apiHostname}/w/${webhookToken}`}`));
|
|
17104
|
+
} catch (err) {
|
|
17105
|
+
console.warn(chalk.yellow(`Could not persist webhook token: ${err?.message ?? err}`));
|
|
17106
|
+
}
|
|
17107
|
+
}
|
|
17011
17108
|
const cfPath = await installCloudflaredIfNeeded();
|
|
17012
17109
|
if (!cfPath) {
|
|
17013
17110
|
console.log(chalk.yellow("cloudflared not installed; run this once installed:"));
|