sparkecoder 0.1.118 → 0.1.119
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.js +1 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/cli.js +74 -10
- package/dist/cli.js.map +1 -1
- package/dist/index.js +73 -9
- package/dist/index.js.map +1 -1
- package/dist/server/index.js +73 -9
- package/dist/server/index.js.map +1 -1
- 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/{T8x1J_CS0n9FaWBr5GhLe → Bt00m8W4k5F79ALhN700F}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{T8x1J_CS0n9FaWBr5GhLe → Bt00m8W4k5F79ALhN700F}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/{T8x1J_CS0n9FaWBr5GhLe → Bt00m8W4k5F79ALhN700F}/_ssgManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{T8x1J_CS0n9FaWBr5GhLe → Bt00m8W4k5F79ALhN700F}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{T8x1J_CS0n9FaWBr5GhLe → Bt00m8W4k5F79ALhN700F}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/static/{T8x1J_CS0n9FaWBr5GhLe → Bt00m8W4k5F79ALhN700F}/_ssgManifest.js +0 -0
- /package/web/.next/static/{T8x1J_CS0n9FaWBr5GhLe → Bt00m8W4k5F79ALhN700F}/_buildManifest.js +0 -0
- /package/web/.next/static/{T8x1J_CS0n9FaWBr5GhLe → Bt00m8W4k5F79ALhN700F}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{T8x1J_CS0n9FaWBr5GhLe → Bt00m8W4k5F79ALhN700F}/_ssgManifest.js +0 -0
package/dist/cli.js
CHANGED
|
@@ -1160,7 +1160,7 @@ function loadConfig(configPath, workingDirectory) {
|
|
|
1160
1160
|
...config,
|
|
1161
1161
|
server: {
|
|
1162
1162
|
port: config.server.port,
|
|
1163
|
-
host: config.server.host ?? "
|
|
1163
|
+
host: config.server.host ?? "0.0.0.0",
|
|
1164
1164
|
publicUrl: config.server.publicUrl
|
|
1165
1165
|
},
|
|
1166
1166
|
resolvedWorkingDirectory,
|
|
@@ -1327,7 +1327,7 @@ function createDefaultConfig() {
|
|
|
1327
1327
|
},
|
|
1328
1328
|
server: {
|
|
1329
1329
|
port: 3141,
|
|
1330
|
-
host: "
|
|
1330
|
+
host: "0.0.0.0"
|
|
1331
1331
|
},
|
|
1332
1332
|
databasePath: "./sparkecoder.db"
|
|
1333
1333
|
};
|
|
@@ -8548,6 +8548,44 @@ function getSlackSigningSecret() {
|
|
|
8548
8548
|
function getDefaultOrchestratorName() {
|
|
8549
8549
|
return readSlackConfig()?.defaultOrchestratorName ?? null;
|
|
8550
8550
|
}
|
|
8551
|
+
function getCachedSlackSelfIdentity() {
|
|
8552
|
+
const cfg = readSlackConfig();
|
|
8553
|
+
if (!cfg) return null;
|
|
8554
|
+
if (cachedSelf && cachedSelf.token === cfg.botToken) return cachedSelf.identity;
|
|
8555
|
+
return null;
|
|
8556
|
+
}
|
|
8557
|
+
async function ensureSlackSelfIdentity() {
|
|
8558
|
+
const cfg = readSlackConfig();
|
|
8559
|
+
if (!cfg) return null;
|
|
8560
|
+
if (cachedSelf && cachedSelf.token === cfg.botToken) return cachedSelf.identity;
|
|
8561
|
+
if (selfInflight) return selfInflight;
|
|
8562
|
+
selfInflight = (async () => {
|
|
8563
|
+
try {
|
|
8564
|
+
const res = await fetch("https://slack.com/api/auth.test", {
|
|
8565
|
+
method: "POST",
|
|
8566
|
+
headers: { Authorization: `Bearer ${cfg.botToken}` }
|
|
8567
|
+
});
|
|
8568
|
+
const data = await res.json().catch(() => ({}));
|
|
8569
|
+
if (!data?.ok) {
|
|
8570
|
+
console.warn(`[slack] auth.test failed: ${data?.error || `HTTP ${res.status}`}`);
|
|
8571
|
+
return null;
|
|
8572
|
+
}
|
|
8573
|
+
const identity = {
|
|
8574
|
+
botUserId: String(data.user_id || ""),
|
|
8575
|
+
botId: String(data.bot_id || ""),
|
|
8576
|
+
teamId: data.team_id ? String(data.team_id) : void 0
|
|
8577
|
+
};
|
|
8578
|
+
cachedSelf = { token: cfg.botToken, identity };
|
|
8579
|
+
return identity;
|
|
8580
|
+
} catch (err) {
|
|
8581
|
+
console.warn("[slack] auth.test error:", err?.message || err);
|
|
8582
|
+
return null;
|
|
8583
|
+
} finally {
|
|
8584
|
+
selfInflight = null;
|
|
8585
|
+
}
|
|
8586
|
+
})();
|
|
8587
|
+
return selfInflight;
|
|
8588
|
+
}
|
|
8551
8589
|
function getSlackAllowlistPolicy() {
|
|
8552
8590
|
try {
|
|
8553
8591
|
const cfg = getConfig();
|
|
@@ -8573,11 +8611,13 @@ function getSlackDeniedReplyPolicy() {
|
|
|
8573
8611
|
return { enabled: true, template: DEFAULT_DENIED_TEMPLATE };
|
|
8574
8612
|
}
|
|
8575
8613
|
}
|
|
8576
|
-
var DEFAULT_DENIED_TEMPLATE;
|
|
8614
|
+
var cachedSelf, selfInflight, DEFAULT_DENIED_TEMPLATE;
|
|
8577
8615
|
var init_client3 = __esm({
|
|
8578
8616
|
"src/integrations/slack/client.ts"() {
|
|
8579
8617
|
"use strict";
|
|
8580
8618
|
init_config();
|
|
8619
|
+
cachedSelf = null;
|
|
8620
|
+
selfInflight = null;
|
|
8581
8621
|
DEFAULT_DENIED_TEMPLATE = "Sorry, you don't have permission to use this bot. (Contact the bot owner if you think this is a mistake.)";
|
|
8582
8622
|
}
|
|
8583
8623
|
});
|
|
@@ -8595,9 +8635,19 @@ function isThreadOwned(channel, threadTs) {
|
|
|
8595
8635
|
function stripMention(text) {
|
|
8596
8636
|
return String(text || "").replace(/<@[^>]+>/g, "").trim();
|
|
8597
8637
|
}
|
|
8598
|
-
function
|
|
8638
|
+
function isSelfAuthored(event, self) {
|
|
8639
|
+
if (!self) return true;
|
|
8640
|
+
if (self.botId && event.bot_id && event.bot_id === self.botId) return true;
|
|
8641
|
+
if (self.botUserId && event.user && event.user === self.botUserId) return true;
|
|
8642
|
+
return false;
|
|
8643
|
+
}
|
|
8644
|
+
function slackEventToInboundResult(event, opts = {}) {
|
|
8599
8645
|
if (!event) return { event: null, dropReason: "empty_text" };
|
|
8600
|
-
|
|
8646
|
+
const self = opts.self ?? getCachedSlackSelfIdentity();
|
|
8647
|
+
const isBotAuthored = !!event.bot_id || event.type === "message" && event.subtype === "bot_message";
|
|
8648
|
+
if (isBotAuthored && isSelfAuthored(event, self)) {
|
|
8649
|
+
return { event: null, dropReason: "bot_message" };
|
|
8650
|
+
}
|
|
8601
8651
|
if (event.type === "message" && event.subtype && IGNORED_MESSAGE_SUBTYPES.has(event.subtype)) {
|
|
8602
8652
|
return { event: null, dropReason: "bot_message" };
|
|
8603
8653
|
}
|
|
@@ -8674,7 +8724,6 @@ var init_slack = __esm({
|
|
|
8674
8724
|
}
|
|
8675
8725
|
};
|
|
8676
8726
|
IGNORED_MESSAGE_SUBTYPES = /* @__PURE__ */ new Set([
|
|
8677
|
-
"bot_message",
|
|
8678
8727
|
"message_changed",
|
|
8679
8728
|
"message_deleted",
|
|
8680
8729
|
"channel_join",
|
|
@@ -14626,7 +14675,8 @@ slack.post("/events", async (c) => {
|
|
|
14626
14675
|
updateEvent(auditId, { status: "dropped", dropReason: "duplicate_delivery" });
|
|
14627
14676
|
return c.json({ ok: true });
|
|
14628
14677
|
}
|
|
14629
|
-
const
|
|
14678
|
+
const self = await ensureSlackSelfIdentity();
|
|
14679
|
+
const { event: inbound, dropReason } = slackEventToInboundResult(ev, { self });
|
|
14630
14680
|
if (inbound) {
|
|
14631
14681
|
const isThreadReply = ev.type === "message" && ev.channel_type !== "im" && typeof ev.thread_ts === "string" && ev.thread_ts !== ev.ts;
|
|
14632
14682
|
if (isThreadReply) {
|
|
@@ -15696,13 +15746,15 @@ async function startServer(options = {}) {
|
|
|
15696
15746
|
if (!options.quiet) console.warn(`[scheduler] start skipped: ${err.message}`);
|
|
15697
15747
|
}
|
|
15698
15748
|
const port = options.port || config.server.port;
|
|
15699
|
-
const
|
|
15749
|
+
const envHost = process.env.SPARKECODER_API_HOST || process.env.SPARKECODER_HOST;
|
|
15750
|
+
const host = envHost || options.host || config.server.host || "0.0.0.0";
|
|
15751
|
+
const hostSource = envHost ? process.env.SPARKECODER_API_HOST ? "env SPARKECODER_API_HOST" : "env SPARKECODER_HOST" : options.host ? "--host flag" : config.server.host ? "config.server.host" : "default";
|
|
15700
15752
|
const publicUrl = options.publicUrl || config.server.publicUrl;
|
|
15701
15753
|
const app = await createApp({ quiet: options.quiet });
|
|
15702
15754
|
if (!options.quiet) {
|
|
15703
15755
|
console.log(`
|
|
15704
15756
|
\u{1F680} SparkECoder API Server`);
|
|
15705
|
-
console.log(` \u2192
|
|
15757
|
+
console.log(` \u2192 Binding to ${host}:${port} (source: ${hostSource})`);
|
|
15706
15758
|
if (publicUrl) {
|
|
15707
15759
|
console.log(` \u2192 Public URL: ${publicUrl}`);
|
|
15708
15760
|
}
|
|
@@ -15711,10 +15763,22 @@ async function startServer(options = {}) {
|
|
|
15711
15763
|
console.log(` \u2192 OpenAPI spec: http://${host}:${port}/openapi.json
|
|
15712
15764
|
`);
|
|
15713
15765
|
}
|
|
15766
|
+
if (host === "127.0.0.1" || host === "localhost") {
|
|
15767
|
+
console.log(`[sparkecoder] \u26A0 API bound to ${host} only \u2014 not reachable from outside the machine.`);
|
|
15768
|
+
console.log(`[sparkecoder] For tunnels/reverse proxies (Modal/Fly/Docker), set --host 0.0.0.0 or SPARKECODER_API_HOST=0.0.0.0.`);
|
|
15769
|
+
}
|
|
15714
15770
|
serverInstance = serve({
|
|
15715
15771
|
fetch: app.fetch,
|
|
15716
15772
|
port,
|
|
15717
15773
|
hostname: host
|
|
15774
|
+
}, (info) => {
|
|
15775
|
+
const actual = `${info.address}:${info.port}`;
|
|
15776
|
+
const requested = `${host}:${port}`;
|
|
15777
|
+
if (info.address === "127.0.0.1" && host !== "127.0.0.1" && host !== "localhost") {
|
|
15778
|
+
console.warn(`[sparkecoder] \u2717 API listener bound to ${actual} but ${requested} was requested. External requests will be refused.`);
|
|
15779
|
+
} else {
|
|
15780
|
+
console.log(`[sparkecoder] \u2713 API listening on ${actual}`);
|
|
15781
|
+
}
|
|
15718
15782
|
});
|
|
15719
15783
|
let webPort;
|
|
15720
15784
|
let webStarted;
|
|
@@ -16782,7 +16846,7 @@ var program = new Command();
|
|
|
16782
16846
|
program.name("sparkecoder").description("AI coding agent - just type sparkecoder to start chatting").version(getCliVersion()).option("-s, --session <id>", "Resume an existing session").option("-n, --name <name>", "Name for the new session").option("-m, --model <model>", "Model to use").option("-w, --working-dir <path>", "Working directory").option("-c, --config <path>", "Path to config file").option("-p, --port <port>", "Server port", "3141").option("-H, --host <host>", "Server host", "127.0.0.1").option("--no-auto-start", "Do not auto-start server if not running").option("--web-port <port>", "Web UI port", "6969").option("--no-web", "Do not start web UI when auto-starting server").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("--dangerously-skip-approvals", "Auto-approve all tool calls (no confirmation prompts)").action(async (options) => {
|
|
16783
16847
|
await runChat(options);
|
|
16784
16848
|
});
|
|
16785
|
-
program.command("server").description("Start the SparkECoder server (API + Web UI)").option("-p, --port <port>", "API server port", "3141").option("-h, --host <host>", "Server
|
|
16849
|
+
program.command("server").description("Start the SparkECoder server (API + Web UI)").option("-p, --port <port>", "API server port", "3141").option("-h, --host <host>", "Server bind address (use 127.0.0.1 to restrict to loopback). Overridable via SPARKECODER_API_HOST / SPARKECODER_HOST env.", "0.0.0.0").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("--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) => {
|
|
16786
16850
|
if (options.setupSecret) {
|
|
16787
16851
|
process.env.SPARKECODER_SETUP_SECRET = options.setupSecret;
|
|
16788
16852
|
if (!process.env.SPARKECODER_TUNNEL_SECRET) {
|