sparkecoder 0.1.114 → 0.1.116
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 +42 -0
- package/dist/agent/index.js.map +1 -1
- package/dist/cli.js +477 -93
- package/dist/cli.js.map +1 -1
- package/dist/db/index.d.ts +2 -2
- package/dist/{index-Bi8Ek02A.d.ts → index-Biy5JTop.d.ts} +104 -104
- package/dist/index.d.ts +5 -5
- package/dist/index.js +293 -64
- 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 +293 -64
- package/dist/server/index.js.map +1 -1
- package/dist/skills/default/computer-use.md +27 -13
- package/dist/skills/default/recording.md +71 -42
- package/dist/tools/index.d.ts +3 -3
- package/package.json +1 -1
- package/src/skills/default/computer-use.md +27 -13
- package/src/skills/default/recording.md +71 -42
- 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/(main)/agents/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/(main)/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page.js.nft.json +1 -1
- package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/(main)/settings/page.js.nft.json +1 -1
- package/web/.next/standalone/web/.next/server/app/(main)/settings/page_client-reference-manifest.js +1 -1
- 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/page_client-reference-manifest.js +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 +2 -2
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/web/.next/standalone/web/.next/server/app/agents.html +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/web/.next/standalone/web/.next/server/app/agents.segments/_tree.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation/page_client-reference-manifest.js +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 +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +2 -2
- 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 +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +2 -2
- 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/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills/page_client-reference-manifest.js +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 +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +2 -2
- 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 +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +2 -2
- 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/page_client-reference-manifest.js +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 +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +2 -2
- 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 +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +2 -2
- 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 +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +2 -2
- 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 +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- 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 +2 -2
- package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/settings.html +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.rsc +3 -3
- package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings/__PAGE__.segment.rsc +2 -2
- 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 +3 -3
- 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 +2 -2
- package/web/.next/standalone/web/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/chunks/ssr/2374f_lucide-react_dist_esm_icons_7340c8b3._.js +3 -0
- package/web/.next/standalone/web/.next/server/chunks/ssr/[root-of-the-server]__f3e6443f._.js +15 -0
- package/web/.next/standalone/web/.next/server/chunks/ssr/web_41927ef5._.js +3 -0
- package/web/.next/standalone/web/.next/server/chunks/ssr/web_src_app_(main)_settings_page_tsx_eb320e07._.js +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/chunks/2c3c1d478808e4e4.js +1 -0
- package/web/.next/standalone/web/.next/static/chunks/3b0501ec3249235f.js +7 -0
- package/web/.next/standalone/web/.next/static/chunks/44c575e006ddb992.js +13 -0
- package/web/.next/standalone/web/.next/static/chunks/9a3afb48c245fb2a.js +1 -0
- package/web/.next/standalone/web/.next/static/chunks/b3bc7244f3477729.css +1 -0
- package/web/.next/standalone/web/.next/static/static/chunks/2c3c1d478808e4e4.js +1 -0
- package/web/.next/standalone/web/.next/static/static/chunks/3b0501ec3249235f.js +7 -0
- package/web/.next/standalone/web/.next/static/static/chunks/44c575e006ddb992.js +13 -0
- package/web/.next/standalone/web/.next/static/static/chunks/9a3afb48c245fb2a.js +1 -0
- package/web/.next/standalone/web/.next/static/static/chunks/b3bc7244f3477729.css +1 -0
- package/web/.next/standalone/web/src/app/(main)/settings/page.tsx +255 -3
- package/web/.next/static/chunks/2c3c1d478808e4e4.js +1 -0
- package/web/.next/static/chunks/3b0501ec3249235f.js +7 -0
- package/web/.next/static/chunks/44c575e006ddb992.js +13 -0
- package/web/.next/static/chunks/9a3afb48c245fb2a.js +1 -0
- package/web/.next/static/chunks/b3bc7244f3477729.css +1 -0
- package/web/.next/standalone/web/.next/server/chunks/ssr/2374f_lucide-react_dist_esm_icons_50c2f239._.js +0 -3
- package/web/.next/standalone/web/.next/server/chunks/ssr/[root-of-the-server]__6097da17._.js +0 -15
- package/web/.next/standalone/web/.next/server/chunks/ssr/web_3b9a2423._.js +0 -3
- package/web/.next/standalone/web/.next/static/chunks/60359bdd369c0c72.js +0 -1
- package/web/.next/standalone/web/.next/static/chunks/a189cacf6d83cf0b.js +0 -13
- package/web/.next/standalone/web/.next/static/chunks/bef6931fdd8428c8.js +0 -1
- package/web/.next/standalone/web/.next/static/chunks/c1f73b3fa4353c31.css +0 -1
- package/web/.next/standalone/web/.next/static/chunks/fbdcbd65f9a38f4b.js +0 -7
- package/web/.next/standalone/web/.next/static/static/chunks/60359bdd369c0c72.js +0 -1
- package/web/.next/standalone/web/.next/static/static/chunks/a189cacf6d83cf0b.js +0 -13
- package/web/.next/standalone/web/.next/static/static/chunks/bef6931fdd8428c8.js +0 -1
- package/web/.next/standalone/web/.next/static/static/chunks/c1f73b3fa4353c31.css +0 -1
- package/web/.next/standalone/web/.next/static/static/chunks/fbdcbd65f9a38f4b.js +0 -7
- package/web/.next/static/chunks/60359bdd369c0c72.js +0 -1
- package/web/.next/static/chunks/a189cacf6d83cf0b.js +0 -13
- package/web/.next/static/chunks/bef6931fdd8428c8.js +0 -1
- package/web/.next/static/chunks/c1f73b3fa4353c31.css +0 -1
- package/web/.next/static/chunks/fbdcbd65f9a38f4b.js +0 -7
- /package/web/.next/standalone/web/.next/static/{N09EiHl0JwEgsGMdCtwpB → 7tYFi20tEUZNGXmy2DJ1K}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{N09EiHl0JwEgsGMdCtwpB → 7tYFi20tEUZNGXmy2DJ1K}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/{N09EiHl0JwEgsGMdCtwpB → 7tYFi20tEUZNGXmy2DJ1K}/_ssgManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{N09EiHl0JwEgsGMdCtwpB → 7tYFi20tEUZNGXmy2DJ1K}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{N09EiHl0JwEgsGMdCtwpB → 7tYFi20tEUZNGXmy2DJ1K}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/static/{N09EiHl0JwEgsGMdCtwpB → 7tYFi20tEUZNGXmy2DJ1K}/_ssgManifest.js +0 -0
- /package/web/.next/static/{N09EiHl0JwEgsGMdCtwpB → 7tYFi20tEUZNGXmy2DJ1K}/_buildManifest.js +0 -0
- /package/web/.next/static/{N09EiHl0JwEgsGMdCtwpB → 7tYFi20tEUZNGXmy2DJ1K}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{N09EiHl0JwEgsGMdCtwpB → 7tYFi20tEUZNGXmy2DJ1K}/_ssgManifest.js +0 -0
package/dist/server/index.js
CHANGED
|
@@ -7654,6 +7654,48 @@ Headless workers never interfere with desktop workers (they don't touch the scre
|
|
|
7654
7654
|
When you spawn a **desktop worker**, include a one-liner in the goal asking it to **record the session by default** (\`screencapture -v -V <seconds> -C\` on macOS) and return the recording path in its result, *unless* the task is long-running / boring / contains sensitive content. The recording lets you (and the user) replay what actually happened on screen. When the worker reports back, mention the recording path in your reply via the original channel.` : ""}
|
|
7655
7655
|
|
|
7656
7656
|
Default bias: **when in doubt, decompose**. Two workers running in parallel and reporting independently is almost always better UX than one worker doing things sequentially.
|
|
7657
|
+
|
|
7658
|
+
### How to write a worker goal (and what NOT to put in it)
|
|
7659
|
+
|
|
7660
|
+
You delegate; the worker executes. Stay at the **what** level, not the **how**.
|
|
7661
|
+
|
|
7662
|
+
**DO** put in the goal:
|
|
7663
|
+
|
|
7664
|
+
- The end objective ("open the macOS Weather app and capture the forecast for Anchorage as a screen recording").
|
|
7665
|
+
- Which skills the worker should load up-front (\`load_skill recording\`, \`load_skill computer-use\`).
|
|
7666
|
+
- Acceptance criteria ("verify the city name is visible in the screenshot before reporting done").
|
|
7667
|
+
- Routing back ("post the recording URL to Slack channel C0123 thread 1700.001").
|
|
7668
|
+
|
|
7669
|
+
**DO NOT** put in the goal (when you're inventing commands from memory):
|
|
7670
|
+
|
|
7671
|
+
- Literal shell commands (\`screencapture -v -V 45 -C /tmp/...\`, \`osascript -e ...\`, \`cliclick kp:cmd+f\`).
|
|
7672
|
+
- Pre-written step-by-step bash that you're drafting from training-data recall.
|
|
7673
|
+
- The names of tools you can't see in your current toolset.
|
|
7674
|
+
|
|
7675
|
+
If you have to reach for memory to write a command, **you're guessing** \u2014 your training data has lots of plausible-looking commands that are subtly wrong or stale. The worker will dutifully follow your wrong instructions instead of consulting the source of truth.
|
|
7676
|
+
|
|
7677
|
+
**Exceptions \u2014 concrete steps ARE appropriate ONLY when relayed verbatim:**
|
|
7678
|
+
|
|
7679
|
+
You CAN include literal step-by-step commands when one of these is true:
|
|
7680
|
+
|
|
7681
|
+
1. **The user gave the steps to you.** Their message says "first run X, then Y, then commit" \u2192 forward those verbatim. That's the user's intent, not your guess.
|
|
7682
|
+
2. **A previous turn already established them.** An earlier worker reported "the deploy script lives at \`./scripts/deploy.sh --env prod\`" \u2192 you can hand that command to the next worker.
|
|
7683
|
+
3. **The conversation history contains them.** A documented \`bash\` invocation from earlier in the chat, an error message that revealed the right path, a CI log the user shared \u2014 anything already concrete in context.
|
|
7684
|
+
|
|
7685
|
+
In all three cases, **label the source** in the goal: *"Per your instructions earlier: 1. run X, 2. run Y..."* or *"Reusing the command worker-foo found last turn: \`./scripts/deploy.sh\`"*.
|
|
7686
|
+
|
|
7687
|
+
What you do NOT do:
|
|
7688
|
+
|
|
7689
|
+
- **Don't paraphrase or "improve" a skill into the goal.** If the recording skill describes \`sparkecoder record start/stop\`, the goal just says *"per the recording skill, bracket the work with start/stop"* \u2014 never quote the exact command. The worker loads the skill and reads the canonical version itself. You quoting it just adds a way for the quote to drift behind the source of truth.
|
|
7690
|
+
- **Don't reason your way to a command.** "I think macOS uses \`open -a Weather\` to launch apps" is exactly the kind of training-data recall that produces stale or wrong commands. Don't include it.
|
|
7691
|
+
|
|
7692
|
+
The rule is: **relay, never invent \u2014 and never quote a skill.** Your job is to (a) tell the worker which skills to load, (b) state the objective and acceptance criteria, (c) relay any concrete steps the user or prior context already established. Workers do the looking-up; you do the dispatching.
|
|
7693
|
+
|
|
7694
|
+
Bad goal (don't do this):
|
|
7695
|
+
> "Start a screen recording with \`screencapture -v -V 45 -C /tmp/weather.mov &\`, then open Weather with \`open -a Weather\`, then click the search bar with cliclick, type 'Anchorage'..."
|
|
7696
|
+
|
|
7697
|
+
Good goal (do this):
|
|
7698
|
+
> "Capture a 30\u201360s screen recording of opening the macOS Weather app and viewing the Anchorage, AK forecast. \`load_skill recording\` and \`load_skill computer-use\` first; use the canonical commands from those skills. Verify the Anchorage temperature is visible in a final screenshot before completing. Return the recording path + a one-line summary of the forecast."
|
|
7657
7699
|
`;
|
|
7658
7700
|
}
|
|
7659
7701
|
function createSummaryPrompt(conversationHistory) {
|
|
@@ -10570,11 +10612,11 @@ ${p.text}` : p.text;
|
|
|
10570
10612
|
const { isRemoteConfigured: isRemoteConfigured2, storageQueries: storageQueries2 } = await Promise.resolve().then(() => (init_remote(), remote_exports));
|
|
10571
10613
|
if (!isRemoteConfigured2()) return [];
|
|
10572
10614
|
const { readFile: readFile12 } = await import("fs/promises");
|
|
10573
|
-
const { join:
|
|
10615
|
+
const { join: join17, basename: basename6 } = await import("path");
|
|
10574
10616
|
const urls = [];
|
|
10575
10617
|
for (const filePath of filePaths) {
|
|
10576
10618
|
try {
|
|
10577
|
-
const fullPath = filePath.startsWith("/") ? filePath :
|
|
10619
|
+
const fullPath = filePath.startsWith("/") ? filePath : join17(this.session.workingDirectory, filePath);
|
|
10578
10620
|
const fileName = basename6(fullPath);
|
|
10579
10621
|
const ext = fileName.split(".").pop()?.toLowerCase() || "";
|
|
10580
10622
|
const mimeMap = {
|
|
@@ -10778,6 +10820,121 @@ var init_session_lock = __esm({
|
|
|
10778
10820
|
}
|
|
10779
10821
|
});
|
|
10780
10822
|
|
|
10823
|
+
// src/orchestrator/webhook-events.ts
|
|
10824
|
+
import { existsSync as existsSync18, readFileSync as readFileSync9, appendFileSync as appendFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync7 } from "fs";
|
|
10825
|
+
import { dirname as dirname6, join as join12 } from "path";
|
|
10826
|
+
import { nanoid as nanoid10 } from "nanoid";
|
|
10827
|
+
function logFilePath() {
|
|
10828
|
+
return join12(getAppDataDirectory(), "webhook-events.jsonl");
|
|
10829
|
+
}
|
|
10830
|
+
function ensureLoaded() {
|
|
10831
|
+
if (cache !== null) return cache;
|
|
10832
|
+
cache = [];
|
|
10833
|
+
try {
|
|
10834
|
+
const p = logFilePath();
|
|
10835
|
+
if (!existsSync18(p)) return cache;
|
|
10836
|
+
const lines = readFileSync9(p, "utf-8").split("\n").filter(Boolean);
|
|
10837
|
+
for (const line of lines) {
|
|
10838
|
+
try {
|
|
10839
|
+
cache.push(JSON.parse(line));
|
|
10840
|
+
} catch {
|
|
10841
|
+
}
|
|
10842
|
+
}
|
|
10843
|
+
if (cache.length > MAX_EVENTS) {
|
|
10844
|
+
cache = cache.slice(-MAX_EVENTS);
|
|
10845
|
+
try {
|
|
10846
|
+
writeFileSync3(p, cache.map((e) => JSON.stringify(e)).join("\n") + "\n");
|
|
10847
|
+
} catch {
|
|
10848
|
+
}
|
|
10849
|
+
}
|
|
10850
|
+
} catch {
|
|
10851
|
+
}
|
|
10852
|
+
return cache;
|
|
10853
|
+
}
|
|
10854
|
+
function appendEvent(ev) {
|
|
10855
|
+
const list = ensureLoaded();
|
|
10856
|
+
list.push(ev);
|
|
10857
|
+
if (list.length > MAX_EVENTS) list.shift();
|
|
10858
|
+
try {
|
|
10859
|
+
const p = logFilePath();
|
|
10860
|
+
mkdirSync7(dirname6(p), { recursive: true });
|
|
10861
|
+
appendFileSync3(p, JSON.stringify(ev) + "\n");
|
|
10862
|
+
} catch {
|
|
10863
|
+
}
|
|
10864
|
+
}
|
|
10865
|
+
function recordEvent(ev) {
|
|
10866
|
+
const full = {
|
|
10867
|
+
id: ev.id ?? nanoid10(),
|
|
10868
|
+
ts: ev.ts ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
10869
|
+
source: ev.source,
|
|
10870
|
+
status: ev.status,
|
|
10871
|
+
subtype: ev.subtype,
|
|
10872
|
+
channel: ev.channel,
|
|
10873
|
+
user: ev.user,
|
|
10874
|
+
textSnippet: ev.textSnippet?.slice(0, 200),
|
|
10875
|
+
dropReason: ev.dropReason,
|
|
10876
|
+
error: ev.error,
|
|
10877
|
+
sessionId: ev.sessionId,
|
|
10878
|
+
durationMs: ev.durationMs,
|
|
10879
|
+
meta: ev.meta
|
|
10880
|
+
};
|
|
10881
|
+
appendEvent(full);
|
|
10882
|
+
return full.id;
|
|
10883
|
+
}
|
|
10884
|
+
function updateEvent(id, patch) {
|
|
10885
|
+
const list = ensureLoaded();
|
|
10886
|
+
const i = list.findIndex((e) => e.id === id);
|
|
10887
|
+
if (i < 0) return;
|
|
10888
|
+
list[i] = { ...list[i], ...patch };
|
|
10889
|
+
try {
|
|
10890
|
+
const p = logFilePath();
|
|
10891
|
+
mkdirSync7(dirname6(p), { recursive: true });
|
|
10892
|
+
writeFileSync3(p, list.map((e) => JSON.stringify(e)).join("\n") + "\n");
|
|
10893
|
+
} catch {
|
|
10894
|
+
}
|
|
10895
|
+
}
|
|
10896
|
+
function listEvents(filter = {}) {
|
|
10897
|
+
const list = ensureLoaded();
|
|
10898
|
+
const q = filter.q?.toLowerCase();
|
|
10899
|
+
const sinceTs = filter.since ? Date.parse(filter.since) : -Infinity;
|
|
10900
|
+
const beforeTs = filter.before ? Date.parse(filter.before) : Infinity;
|
|
10901
|
+
const matched = list.filter((e) => {
|
|
10902
|
+
if (filter.source && e.source !== filter.source) return false;
|
|
10903
|
+
if (filter.status && e.status !== filter.status) return false;
|
|
10904
|
+
const t = Date.parse(e.ts);
|
|
10905
|
+
if (t < sinceTs) return false;
|
|
10906
|
+
if (t >= beforeTs) return false;
|
|
10907
|
+
if (q) {
|
|
10908
|
+
const hay = `${e.channel ?? ""} ${e.user ?? ""} ${e.textSnippet ?? ""} ${e.dropReason ?? ""} ${e.error ?? ""} ${e.subtype ?? ""}`.toLowerCase();
|
|
10909
|
+
if (!hay.includes(q)) return false;
|
|
10910
|
+
}
|
|
10911
|
+
return true;
|
|
10912
|
+
});
|
|
10913
|
+
matched.reverse();
|
|
10914
|
+
const offset = Math.max(0, filter.offset ?? 0);
|
|
10915
|
+
const limit = Math.min(500, Math.max(1, filter.limit ?? 50));
|
|
10916
|
+
return {
|
|
10917
|
+
events: matched.slice(offset, offset + limit),
|
|
10918
|
+
total: matched.length
|
|
10919
|
+
};
|
|
10920
|
+
}
|
|
10921
|
+
function clearAllEvents() {
|
|
10922
|
+
cache = [];
|
|
10923
|
+
try {
|
|
10924
|
+
writeFileSync3(logFilePath(), "");
|
|
10925
|
+
} catch {
|
|
10926
|
+
}
|
|
10927
|
+
}
|
|
10928
|
+
var MAX_EVENTS, cache;
|
|
10929
|
+
var init_webhook_events = __esm({
|
|
10930
|
+
"src/orchestrator/webhook-events.ts"() {
|
|
10931
|
+
"use strict";
|
|
10932
|
+
init_config();
|
|
10933
|
+
MAX_EVENTS = 1e3;
|
|
10934
|
+
cache = null;
|
|
10935
|
+
}
|
|
10936
|
+
});
|
|
10937
|
+
|
|
10781
10938
|
// src/orchestrator/daemon.ts
|
|
10782
10939
|
var daemon_exports = {};
|
|
10783
10940
|
__export(daemon_exports, {
|
|
@@ -10839,6 +10996,17 @@ async function runDaemonTurn(sessionId, events) {
|
|
|
10839
10996
|
});
|
|
10840
10997
|
const finishedAt = /* @__PURE__ */ new Date();
|
|
10841
10998
|
const trimmed = text.trim();
|
|
10999
|
+
recordEvent({
|
|
11000
|
+
source: "daemon",
|
|
11001
|
+
status: error ? "failed" : "completed",
|
|
11002
|
+
channel: events[0]?.ref?.channel ?? void 0,
|
|
11003
|
+
user: events[0]?.ref?.user,
|
|
11004
|
+
textSnippet: trimmed.slice(0, 200),
|
|
11005
|
+
error,
|
|
11006
|
+
sessionId,
|
|
11007
|
+
durationMs: finishedAt.getTime() - startedAt.getTime(),
|
|
11008
|
+
meta: { triggeredBy: events.map((e) => e.content?.slice(0, 80)) }
|
|
11009
|
+
});
|
|
10842
11010
|
broadcast({ sessionId, text: trimmed, triggeredBy: events, startedAt, finishedAt, error });
|
|
10843
11011
|
}
|
|
10844
11012
|
var listeners;
|
|
@@ -10849,6 +11017,7 @@ var init_daemon = __esm({
|
|
|
10849
11017
|
init_session_lock();
|
|
10850
11018
|
init_db();
|
|
10851
11019
|
init_inbox();
|
|
11020
|
+
init_webhook_events();
|
|
10852
11021
|
listeners = /* @__PURE__ */ new Map();
|
|
10853
11022
|
}
|
|
10854
11023
|
});
|
|
@@ -11023,8 +11192,8 @@ import { Hono as Hono9 } from "hono";
|
|
|
11023
11192
|
import { serve } from "@hono/node-server";
|
|
11024
11193
|
import { cors } from "hono/cors";
|
|
11025
11194
|
import { logger } from "hono/logger";
|
|
11026
|
-
import { existsSync as
|
|
11027
|
-
import { resolve as resolve11, dirname as
|
|
11195
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync10, writeFileSync as writeFileSync6 } from "fs";
|
|
11196
|
+
import { resolve as resolve11, dirname as dirname8, join as join16 } from "path";
|
|
11028
11197
|
import { spawn as spawn2 } from "child_process";
|
|
11029
11198
|
import { createServer as createNetServer } from "net";
|
|
11030
11199
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
@@ -11038,10 +11207,10 @@ init_checkpoints();
|
|
|
11038
11207
|
import { Hono } from "hono";
|
|
11039
11208
|
import { zValidator } from "@hono/zod-validator";
|
|
11040
11209
|
import { z as z17 } from "zod";
|
|
11041
|
-
import { existsSync as
|
|
11210
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync8, writeFileSync as writeFileSync4, readdirSync as readdirSync3, statSync as statSync2, unlinkSync as unlinkSync3 } from "fs";
|
|
11042
11211
|
import { readdir as readdir6 } from "fs/promises";
|
|
11043
|
-
import { join as
|
|
11044
|
-
import { nanoid as
|
|
11212
|
+
import { join as join13, basename as basename5, extname as extname8, relative as relative9 } from "path";
|
|
11213
|
+
import { nanoid as nanoid11 } from "nanoid";
|
|
11045
11214
|
|
|
11046
11215
|
// src/tasks/agent-status.ts
|
|
11047
11216
|
init_questions();
|
|
@@ -11682,12 +11851,12 @@ sessions2.get("/:id/diff/:filePath", async (c) => {
|
|
|
11682
11851
|
});
|
|
11683
11852
|
function getAttachmentsDir(sessionId) {
|
|
11684
11853
|
const appDataDir = getAppDataDirectory();
|
|
11685
|
-
return
|
|
11854
|
+
return join13(appDataDir, "attachments", sessionId);
|
|
11686
11855
|
}
|
|
11687
11856
|
function ensureAttachmentsDir(sessionId) {
|
|
11688
11857
|
const dir = getAttachmentsDir(sessionId);
|
|
11689
|
-
if (!
|
|
11690
|
-
|
|
11858
|
+
if (!existsSync19(dir)) {
|
|
11859
|
+
mkdirSync8(dir, { recursive: true });
|
|
11691
11860
|
}
|
|
11692
11861
|
return dir;
|
|
11693
11862
|
}
|
|
@@ -11698,12 +11867,12 @@ sessions2.get("/:id/attachments", async (c) => {
|
|
|
11698
11867
|
return c.json({ error: "Session not found" }, 404);
|
|
11699
11868
|
}
|
|
11700
11869
|
const dir = getAttachmentsDir(sessionId);
|
|
11701
|
-
if (!
|
|
11870
|
+
if (!existsSync19(dir)) {
|
|
11702
11871
|
return c.json({ sessionId, attachments: [], count: 0 });
|
|
11703
11872
|
}
|
|
11704
11873
|
const files = readdirSync3(dir);
|
|
11705
11874
|
const attachments = files.map((filename) => {
|
|
11706
|
-
const filePath =
|
|
11875
|
+
const filePath = join13(dir, filename);
|
|
11707
11876
|
const stats = statSync2(filePath);
|
|
11708
11877
|
return {
|
|
11709
11878
|
id: filename.split("_")[0],
|
|
@@ -11735,12 +11904,12 @@ sessions2.post("/:id/attachments", async (c) => {
|
|
|
11735
11904
|
return c.json({ error: "No file provided" }, 400);
|
|
11736
11905
|
}
|
|
11737
11906
|
const dir = ensureAttachmentsDir(sessionId);
|
|
11738
|
-
const id =
|
|
11907
|
+
const id = nanoid11(10);
|
|
11739
11908
|
const ext = extname8(file.name) || "";
|
|
11740
11909
|
const safeFilename = `${id}_${basename5(file.name).replace(/[^a-zA-Z0-9._-]/g, "_")}`;
|
|
11741
|
-
const filePath =
|
|
11910
|
+
const filePath = join13(dir, safeFilename);
|
|
11742
11911
|
const arrayBuffer = await file.arrayBuffer();
|
|
11743
|
-
|
|
11912
|
+
writeFileSync4(filePath, Buffer.from(arrayBuffer));
|
|
11744
11913
|
return c.json({
|
|
11745
11914
|
id,
|
|
11746
11915
|
filename: file.name,
|
|
@@ -11761,16 +11930,16 @@ sessions2.post("/:id/attachments", async (c) => {
|
|
|
11761
11930
|
return c.json({ error: "Missing filename or data" }, 400);
|
|
11762
11931
|
}
|
|
11763
11932
|
const dir = ensureAttachmentsDir(sessionId);
|
|
11764
|
-
const id =
|
|
11933
|
+
const id = nanoid11(10);
|
|
11765
11934
|
const ext = extname8(body.filename) || "";
|
|
11766
11935
|
const safeFilename = `${id}_${basename5(body.filename).replace(/[^a-zA-Z0-9._-]/g, "_")}`;
|
|
11767
|
-
const filePath =
|
|
11936
|
+
const filePath = join13(dir, safeFilename);
|
|
11768
11937
|
let base64Data = body.data;
|
|
11769
11938
|
if (base64Data.includes(",")) {
|
|
11770
11939
|
base64Data = base64Data.split(",")[1];
|
|
11771
11940
|
}
|
|
11772
11941
|
const buffer = Buffer.from(base64Data, "base64");
|
|
11773
|
-
|
|
11942
|
+
writeFileSync4(filePath, buffer);
|
|
11774
11943
|
return c.json({
|
|
11775
11944
|
id,
|
|
11776
11945
|
filename: body.filename,
|
|
@@ -11793,7 +11962,7 @@ sessions2.delete("/:id/attachments/:attachmentId", async (c) => {
|
|
|
11793
11962
|
return c.json({ error: "Session not found" }, 404);
|
|
11794
11963
|
}
|
|
11795
11964
|
const dir = getAttachmentsDir(sessionId);
|
|
11796
|
-
if (!
|
|
11965
|
+
if (!existsSync19(dir)) {
|
|
11797
11966
|
return c.json({ error: "Attachment not found" }, 404);
|
|
11798
11967
|
}
|
|
11799
11968
|
const files = readdirSync3(dir);
|
|
@@ -11801,7 +11970,7 @@ sessions2.delete("/:id/attachments/:attachmentId", async (c) => {
|
|
|
11801
11970
|
if (!file) {
|
|
11802
11971
|
return c.json({ error: "Attachment not found" }, 404);
|
|
11803
11972
|
}
|
|
11804
|
-
const filePath =
|
|
11973
|
+
const filePath = join13(dir, file);
|
|
11805
11974
|
unlinkSync3(filePath);
|
|
11806
11975
|
return c.json({ success: true, id: attachmentId });
|
|
11807
11976
|
});
|
|
@@ -11884,7 +12053,7 @@ async function listWorkspaceFiles(baseDir, currentDir, query, limit, results = [
|
|
|
11884
12053
|
const entries = await readdir6(currentDir, { withFileTypes: true });
|
|
11885
12054
|
for (const entry2 of entries) {
|
|
11886
12055
|
if (results.length >= limit * 2) break;
|
|
11887
|
-
const fullPath =
|
|
12056
|
+
const fullPath = join13(currentDir, entry2.name);
|
|
11888
12057
|
const relativePath = relative9(baseDir, fullPath);
|
|
11889
12058
|
if (entry2.isDirectory() && IGNORED_DIRECTORIES.has(entry2.name)) {
|
|
11890
12059
|
continue;
|
|
@@ -11932,7 +12101,7 @@ sessions2.get(
|
|
|
11932
12101
|
return c.json({ error: "Session not found" }, 404);
|
|
11933
12102
|
}
|
|
11934
12103
|
const workingDirectory = session.workingDirectory;
|
|
11935
|
-
if (!
|
|
12104
|
+
if (!existsSync19(workingDirectory)) {
|
|
11936
12105
|
return c.json({
|
|
11937
12106
|
sessionId,
|
|
11938
12107
|
workingDirectory,
|
|
@@ -12046,8 +12215,8 @@ init_config();
|
|
|
12046
12215
|
import { Hono as Hono2 } from "hono";
|
|
12047
12216
|
import { zValidator as zValidator2 } from "@hono/zod-validator";
|
|
12048
12217
|
import { z as z18 } from "zod";
|
|
12049
|
-
import { existsSync as
|
|
12050
|
-
import { join as
|
|
12218
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync9, writeFileSync as writeFileSync5 } from "fs";
|
|
12219
|
+
import { join as join14 } from "path";
|
|
12051
12220
|
|
|
12052
12221
|
// src/server/resumable-stream.ts
|
|
12053
12222
|
import { createResumableStreamContext } from "resumable-stream/generic";
|
|
@@ -12134,7 +12303,7 @@ var streamContext = createResumableStreamContext({
|
|
|
12134
12303
|
|
|
12135
12304
|
// src/server/routes/agents.ts
|
|
12136
12305
|
init_checkpoints();
|
|
12137
|
-
import { nanoid as
|
|
12306
|
+
import { nanoid as nanoid12 } from "nanoid";
|
|
12138
12307
|
init_stream_proxy();
|
|
12139
12308
|
init_recorder();
|
|
12140
12309
|
init_remote();
|
|
@@ -12254,12 +12423,12 @@ var rejectSchema = z18.object({
|
|
|
12254
12423
|
var streamAbortControllers = /* @__PURE__ */ new Map();
|
|
12255
12424
|
function getAttachmentsDirectory(sessionId) {
|
|
12256
12425
|
const appDataDir = getAppDataDirectory();
|
|
12257
|
-
return
|
|
12426
|
+
return join14(appDataDir, "attachments", sessionId);
|
|
12258
12427
|
}
|
|
12259
12428
|
async function saveAttachmentToDisk(sessionId, attachment, index) {
|
|
12260
12429
|
const attachmentsDir = getAttachmentsDirectory(sessionId);
|
|
12261
|
-
if (!
|
|
12262
|
-
|
|
12430
|
+
if (!existsSync20(attachmentsDir)) {
|
|
12431
|
+
mkdirSync9(attachmentsDir, { recursive: true });
|
|
12263
12432
|
}
|
|
12264
12433
|
let filename = attachment.filename;
|
|
12265
12434
|
if (!filename) {
|
|
@@ -12277,8 +12446,8 @@ async function saveAttachmentToDisk(sessionId, attachment, index) {
|
|
|
12277
12446
|
attachment.mediaType = resized.mediaType;
|
|
12278
12447
|
attachment.data = buffer.toString("base64");
|
|
12279
12448
|
}
|
|
12280
|
-
const filePath =
|
|
12281
|
-
|
|
12449
|
+
const filePath = join14(attachmentsDir, filename);
|
|
12450
|
+
writeFileSync5(filePath, buffer);
|
|
12282
12451
|
return filePath;
|
|
12283
12452
|
}
|
|
12284
12453
|
function stripDataUrlPrefix2(data) {
|
|
@@ -12714,7 +12883,7 @@ ${prompt}` });
|
|
|
12714
12883
|
});
|
|
12715
12884
|
} catch {
|
|
12716
12885
|
}
|
|
12717
|
-
const streamId = `stream_${id}_${
|
|
12886
|
+
const streamId = `stream_${id}_${nanoid12(10)}`;
|
|
12718
12887
|
console.log(`[STREAM] Creating stream ${streamId} for session ${id}`);
|
|
12719
12888
|
await activeStreamQueries.create(id, streamId);
|
|
12720
12889
|
const stream = await streamContext.resumableStream(
|
|
@@ -12919,7 +13088,7 @@ agents.post(
|
|
|
12919
13088
|
});
|
|
12920
13089
|
const session = agent.getSession();
|
|
12921
13090
|
const enrichedPrompt = enrichPromptWithDevtoolsContext(session.id, body.prompt);
|
|
12922
|
-
const streamId = `stream_${session.id}_${
|
|
13091
|
+
const streamId = `stream_${session.id}_${nanoid12(10)}`;
|
|
12923
13092
|
await createCheckpoint(session.id, session.workingDirectory, 0);
|
|
12924
13093
|
await activeStreamQueries.create(session.id, streamId);
|
|
12925
13094
|
const createQuickStreamProducer = () => {
|
|
@@ -13238,26 +13407,26 @@ init_config();
|
|
|
13238
13407
|
import { Hono as Hono3 } from "hono";
|
|
13239
13408
|
import { zValidator as zValidator3 } from "@hono/zod-validator";
|
|
13240
13409
|
import { z as z19 } from "zod";
|
|
13241
|
-
import { readFileSync as
|
|
13410
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
13242
13411
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
13243
|
-
import { dirname as
|
|
13412
|
+
import { dirname as dirname7, join as join15 } from "path";
|
|
13244
13413
|
var __filename = fileURLToPath3(import.meta.url);
|
|
13245
|
-
var __dirname =
|
|
13414
|
+
var __dirname = dirname7(__filename);
|
|
13246
13415
|
var possiblePaths = [
|
|
13247
|
-
|
|
13416
|
+
join15(__dirname, "../package.json"),
|
|
13248
13417
|
// From dist/server -> dist/../package.json
|
|
13249
|
-
|
|
13418
|
+
join15(__dirname, "../../package.json"),
|
|
13250
13419
|
// From dist/server (if nested differently)
|
|
13251
|
-
|
|
13420
|
+
join15(__dirname, "../../../package.json"),
|
|
13252
13421
|
// From src/server/routes (development)
|
|
13253
|
-
|
|
13422
|
+
join15(process.cwd(), "package.json")
|
|
13254
13423
|
// From current working directory
|
|
13255
13424
|
];
|
|
13256
13425
|
var currentVersion = "0.0.0";
|
|
13257
13426
|
var packageName = "sparkecoder";
|
|
13258
13427
|
for (const packageJsonPath of possiblePaths) {
|
|
13259
13428
|
try {
|
|
13260
|
-
const packageJson = JSON.parse(
|
|
13429
|
+
const packageJson = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
|
|
13261
13430
|
if (packageJson.name === "sparkecoder") {
|
|
13262
13431
|
currentVersion = packageJson.version || "0.0.0";
|
|
13263
13432
|
packageName = packageJson.name || "sparkecoder";
|
|
@@ -13707,7 +13876,7 @@ init_config();
|
|
|
13707
13876
|
import { Hono as Hono5 } from "hono";
|
|
13708
13877
|
import { zValidator as zValidator5 } from "@hono/zod-validator";
|
|
13709
13878
|
import { z as z21 } from "zod";
|
|
13710
|
-
import { nanoid as
|
|
13879
|
+
import { nanoid as nanoid13 } from "nanoid";
|
|
13711
13880
|
init_questions();
|
|
13712
13881
|
var tasks = new Hono5();
|
|
13713
13882
|
var taskAbortControllers = /* @__PURE__ */ new Map();
|
|
@@ -13788,7 +13957,7 @@ tasks.post(
|
|
|
13788
13957
|
const taskId = agent.sessionId;
|
|
13789
13958
|
const abortController = new AbortController();
|
|
13790
13959
|
taskAbortControllers.set(taskId, abortController);
|
|
13791
|
-
const streamId = `stream_${taskId}_${
|
|
13960
|
+
const streamId = `stream_${taskId}_${nanoid13(10)}`;
|
|
13792
13961
|
await activeStreamQueries.create(taskId, streamId);
|
|
13793
13962
|
const taskStreamProducer = () => {
|
|
13794
13963
|
const { readable, writable } = new TransformStream();
|
|
@@ -14014,6 +14183,7 @@ function verifySlackSignature(opts) {
|
|
|
14014
14183
|
// src/server/routes/slack.ts
|
|
14015
14184
|
init_client3();
|
|
14016
14185
|
init_slack();
|
|
14186
|
+
init_webhook_events();
|
|
14017
14187
|
init_inbox();
|
|
14018
14188
|
var recentlyHandled = /* @__PURE__ */ new Map();
|
|
14019
14189
|
var MAX_RECENT = 1e3;
|
|
@@ -14054,7 +14224,17 @@ slack.post("/events", async (c) => {
|
|
|
14054
14224
|
}
|
|
14055
14225
|
if (payload?.type === "event_callback" && payload?.event) {
|
|
14056
14226
|
const ev = payload.event;
|
|
14227
|
+
const auditId = recordEvent({
|
|
14228
|
+
source: "slack",
|
|
14229
|
+
status: "received",
|
|
14230
|
+
subtype: ev.type === "message" ? `message.${ev.channel_type ?? "channels"}` : ev.type,
|
|
14231
|
+
channel: ev.channel,
|
|
14232
|
+
user: ev.user,
|
|
14233
|
+
textSnippet: typeof ev.text === "string" ? ev.text : void 0,
|
|
14234
|
+
meta: { ts: ev.ts, thread_ts: ev.thread_ts, team: ev.team, event_subtype: ev.subtype }
|
|
14235
|
+
});
|
|
14057
14236
|
if (alreadyHandled(ev.channel, ev.ts)) {
|
|
14237
|
+
updateEvent(auditId, { status: "dropped", dropReason: "duplicate_delivery" });
|
|
14058
14238
|
return c.json({ ok: true });
|
|
14059
14239
|
}
|
|
14060
14240
|
const { event: inbound, dropReason } = slackEventToInboundResult(ev);
|
|
@@ -14064,6 +14244,7 @@ slack.post("/events", async (c) => {
|
|
|
14064
14244
|
const ours = isThreadOwned(ev.channel, ev.thread_ts) || await threadBelongsToUs(ev.channel, ev.thread_ts);
|
|
14065
14245
|
if (!ours) {
|
|
14066
14246
|
console.log(`[slack] dropping thread reply in unknown thread: channel=${ev.channel} thread=${ev.thread_ts}`);
|
|
14247
|
+
updateEvent(auditId, { status: "dropped", dropReason: "thread_not_owned" });
|
|
14067
14248
|
return c.json({ ok: true });
|
|
14068
14249
|
}
|
|
14069
14250
|
}
|
|
@@ -14076,8 +14257,12 @@ slack.post("/events", async (c) => {
|
|
|
14076
14257
|
const orchestratorId = await findOrCreateOrchestratorId();
|
|
14077
14258
|
if (orchestratorId) {
|
|
14078
14259
|
pushToInbox(orchestratorId, inbound);
|
|
14260
|
+
updateEvent(auditId, { status: "routed", sessionId: orchestratorId });
|
|
14261
|
+
} else {
|
|
14262
|
+
updateEvent(auditId, { status: "error", error: "no orchestrator session available" });
|
|
14079
14263
|
}
|
|
14080
14264
|
} else if (dropReason) {
|
|
14265
|
+
updateEvent(auditId, { status: "dropped", dropReason });
|
|
14081
14266
|
const userFacingDrops = ["user_not_allowed", "channel_not_allowed", "dm_blocked"];
|
|
14082
14267
|
if (userFacingDrops.includes(dropReason)) {
|
|
14083
14268
|
console.log(`[slack] dropped event from user=${payload.event.user} channel=${payload.event.channel}: ${dropReason}`);
|
|
@@ -14140,13 +14325,30 @@ async function sendDeniedReply(event) {
|
|
|
14140
14325
|
init_webhooks_store();
|
|
14141
14326
|
init_webhook();
|
|
14142
14327
|
init_inbox();
|
|
14328
|
+
init_webhook_events();
|
|
14143
14329
|
import { Hono as Hono7 } from "hono";
|
|
14144
14330
|
var inbox = new Hono7();
|
|
14145
14331
|
inbox.post("/:token", async (c) => {
|
|
14146
14332
|
const token = c.req.param("token");
|
|
14147
|
-
if (!token || token.length < 16)
|
|
14333
|
+
if (!token || token.length < 16) {
|
|
14334
|
+
recordEvent({
|
|
14335
|
+
source: "inbox",
|
|
14336
|
+
status: "dropped",
|
|
14337
|
+
dropReason: "invalid_token_format",
|
|
14338
|
+
meta: { tokenLen: token?.length ?? 0 }
|
|
14339
|
+
});
|
|
14340
|
+
return c.json({ error: "invalid token" }, 401);
|
|
14341
|
+
}
|
|
14148
14342
|
const lookup = await findByToken(token);
|
|
14149
|
-
if (!lookup)
|
|
14343
|
+
if (!lookup) {
|
|
14344
|
+
recordEvent({
|
|
14345
|
+
source: "inbox",
|
|
14346
|
+
status: "dropped",
|
|
14347
|
+
dropReason: "unknown_token",
|
|
14348
|
+
meta: { tokenPrefix: token.slice(0, 8) + "\u2026" }
|
|
14349
|
+
});
|
|
14350
|
+
return c.json({ error: "unknown token" }, 404);
|
|
14351
|
+
}
|
|
14150
14352
|
let body;
|
|
14151
14353
|
const contentType = c.req.header("content-type") || "";
|
|
14152
14354
|
try {
|
|
@@ -14168,6 +14370,14 @@ inbox.post("/:token", async (c) => {
|
|
|
14168
14370
|
pushToInbox(lookup.orchestratorSessionId, event);
|
|
14169
14371
|
void recordHit(lookup.orchestratorSessionId, lookup.webhook.id).catch(() => {
|
|
14170
14372
|
});
|
|
14373
|
+
recordEvent({
|
|
14374
|
+
source: "inbox",
|
|
14375
|
+
status: "routed",
|
|
14376
|
+
channel: lookup.webhook.name,
|
|
14377
|
+
textSnippet: typeof body === "string" ? body : JSON.stringify(body).slice(0, 200),
|
|
14378
|
+
sessionId: lookup.orchestratorSessionId,
|
|
14379
|
+
meta: { wake: lookup.webhook.wake, webhookId: lookup.webhook.id }
|
|
14380
|
+
});
|
|
14171
14381
|
return c.json({ ok: true, queued: true, wake: lookup.webhook.wake });
|
|
14172
14382
|
});
|
|
14173
14383
|
|
|
@@ -14179,6 +14389,7 @@ init_webhooks_store();
|
|
|
14179
14389
|
init_messenger();
|
|
14180
14390
|
init_store();
|
|
14181
14391
|
init_pool();
|
|
14392
|
+
init_webhook_events();
|
|
14182
14393
|
import { Hono as Hono8 } from "hono";
|
|
14183
14394
|
import { zValidator as zValidator6 } from "@hono/zod-validator";
|
|
14184
14395
|
import { z as z22 } from "zod";
|
|
@@ -14237,6 +14448,24 @@ function webhookPrefix() {
|
|
|
14237
14448
|
const token = cfg?.webhooks?.token;
|
|
14238
14449
|
return token ? `/w/${token}` : "/api";
|
|
14239
14450
|
}
|
|
14451
|
+
integrations.get("/events", async (c) => {
|
|
14452
|
+
const q = c.req.query();
|
|
14453
|
+
const filter = {
|
|
14454
|
+
source: q.source,
|
|
14455
|
+
status: q.status,
|
|
14456
|
+
q: q.q,
|
|
14457
|
+
since: q.since,
|
|
14458
|
+
before: q.before,
|
|
14459
|
+
limit: q.limit ? Math.min(500, Math.max(1, parseInt(q.limit, 10))) : 50,
|
|
14460
|
+
offset: q.offset ? Math.max(0, parseInt(q.offset, 10)) : 0
|
|
14461
|
+
};
|
|
14462
|
+
const { events, total } = listEvents(filter);
|
|
14463
|
+
return c.json({ events, total, limit: filter.limit, offset: filter.offset });
|
|
14464
|
+
});
|
|
14465
|
+
integrations.delete("/events", async (c) => {
|
|
14466
|
+
clearAllEvents();
|
|
14467
|
+
return c.json({ ok: true });
|
|
14468
|
+
});
|
|
14240
14469
|
integrations.get("/", async (c) => {
|
|
14241
14470
|
const cfg = getConfig();
|
|
14242
14471
|
return c.json({
|
|
@@ -14599,13 +14828,13 @@ var DEFAULT_WEB_PORT = 6969;
|
|
|
14599
14828
|
var WEB_PORT_SEQUENCE = [6969, 6970, 6971, 6972, 6973, 6974, 6975, 6976, 6977, 6978];
|
|
14600
14829
|
function getWebDirectory() {
|
|
14601
14830
|
try {
|
|
14602
|
-
const currentDir =
|
|
14831
|
+
const currentDir = dirname8(fileURLToPath4(import.meta.url));
|
|
14603
14832
|
const webDir = resolve11(currentDir, "..", "web");
|
|
14604
|
-
if (
|
|
14833
|
+
if (existsSync21(webDir) && existsSync21(join16(webDir, "package.json"))) {
|
|
14605
14834
|
return webDir;
|
|
14606
14835
|
}
|
|
14607
14836
|
const altWebDir = resolve11(currentDir, "..", "..", "web");
|
|
14608
|
-
if (
|
|
14837
|
+
if (existsSync21(altWebDir) && existsSync21(join16(altWebDir, "package.json"))) {
|
|
14609
14838
|
return altWebDir;
|
|
14610
14839
|
}
|
|
14611
14840
|
return null;
|
|
@@ -14663,23 +14892,23 @@ async function findWebPort(preferredPort) {
|
|
|
14663
14892
|
return { port: preferredPort, alreadyRunning: false };
|
|
14664
14893
|
}
|
|
14665
14894
|
function hasProductionBuild(webDir) {
|
|
14666
|
-
const buildIdPath =
|
|
14667
|
-
return
|
|
14895
|
+
const buildIdPath = join16(webDir, ".next", "BUILD_ID");
|
|
14896
|
+
return existsSync21(buildIdPath);
|
|
14668
14897
|
}
|
|
14669
14898
|
function hasSourceFiles(webDir) {
|
|
14670
|
-
const appDir =
|
|
14671
|
-
const pagesDir =
|
|
14672
|
-
const rootAppDir =
|
|
14673
|
-
const rootPagesDir =
|
|
14674
|
-
return
|
|
14899
|
+
const appDir = join16(webDir, "src", "app");
|
|
14900
|
+
const pagesDir = join16(webDir, "src", "pages");
|
|
14901
|
+
const rootAppDir = join16(webDir, "app");
|
|
14902
|
+
const rootPagesDir = join16(webDir, "pages");
|
|
14903
|
+
return existsSync21(appDir) || existsSync21(pagesDir) || existsSync21(rootAppDir) || existsSync21(rootPagesDir);
|
|
14675
14904
|
}
|
|
14676
14905
|
function getStandaloneServerPath(webDir) {
|
|
14677
14906
|
const possiblePaths2 = [
|
|
14678
|
-
|
|
14679
|
-
|
|
14907
|
+
join16(webDir, ".next", "standalone", "server.js"),
|
|
14908
|
+
join16(webDir, ".next", "standalone", "web", "server.js")
|
|
14680
14909
|
];
|
|
14681
14910
|
for (const serverPath of possiblePaths2) {
|
|
14682
|
-
if (
|
|
14911
|
+
if (existsSync21(serverPath)) {
|
|
14683
14912
|
return serverPath;
|
|
14684
14913
|
}
|
|
14685
14914
|
}
|
|
@@ -14719,15 +14948,15 @@ async function startWebUI(apiPort, webPort = DEFAULT_WEB_PORT, quiet = false, pu
|
|
|
14719
14948
|
if (!quiet) console.log(` \u2713 Web UI already running at http://localhost:${actualPort}`);
|
|
14720
14949
|
return { process: null, port: actualPort };
|
|
14721
14950
|
}
|
|
14722
|
-
const usePnpm =
|
|
14723
|
-
const useNpm = !usePnpm &&
|
|
14951
|
+
const usePnpm = existsSync21(join16(webDir, "pnpm-lock.yaml"));
|
|
14952
|
+
const useNpm = !usePnpm && existsSync21(join16(webDir, "package-lock.json"));
|
|
14724
14953
|
const pkgManager = usePnpm ? "pnpm" : useNpm ? "npm" : "npx";
|
|
14725
14954
|
const { NODE_OPTIONS, TSX_TSCONFIG_PATH, ...cleanEnv } = process.env;
|
|
14726
14955
|
const apiUrl = publicUrl || `http://127.0.0.1:${apiPort}`;
|
|
14727
14956
|
const runtimeConfig = { apiBaseUrl: apiUrl };
|
|
14728
|
-
const runtimeConfigPath =
|
|
14957
|
+
const runtimeConfigPath = join16(webDir, "runtime-config.json");
|
|
14729
14958
|
try {
|
|
14730
|
-
|
|
14959
|
+
writeFileSync6(runtimeConfigPath, JSON.stringify(runtimeConfig, null, 2));
|
|
14731
14960
|
if (!quiet) console.log(` \u{1F4DD} Runtime config written to ${runtimeConfigPath}`);
|
|
14732
14961
|
} catch (err) {
|
|
14733
14962
|
if (!quiet) console.warn(` \u26A0 Could not write runtime config: ${err}`);
|
|
@@ -14747,7 +14976,7 @@ async function startWebUI(apiPort, webPort = DEFAULT_WEB_PORT, quiet = false, pu
|
|
|
14747
14976
|
if (standaloneServerPath) {
|
|
14748
14977
|
command = "node";
|
|
14749
14978
|
args = ["server.js"];
|
|
14750
|
-
cwd =
|
|
14979
|
+
cwd = dirname8(standaloneServerPath);
|
|
14751
14980
|
webEnv.PORT = String(actualPort);
|
|
14752
14981
|
webEnv.HOSTNAME = "0.0.0.0";
|
|
14753
14982
|
if (!quiet) console.log(" \u{1F4E6} Starting Web UI from standalone build...");
|
|
@@ -14940,8 +15169,8 @@ async function startServer(options = {}) {
|
|
|
14940
15169
|
if (options.workingDirectory) {
|
|
14941
15170
|
config.resolvedWorkingDirectory = options.workingDirectory;
|
|
14942
15171
|
}
|
|
14943
|
-
if (!
|
|
14944
|
-
|
|
15172
|
+
if (!existsSync21(config.resolvedWorkingDirectory)) {
|
|
15173
|
+
mkdirSync10(config.resolvedWorkingDirectory, { recursive: true });
|
|
14945
15174
|
if (!options.quiet) console.log(`\u{1F4C1} Created agent workspace: ${config.resolvedWorkingDirectory}`);
|
|
14946
15175
|
}
|
|
14947
15176
|
if (!config.resolvedRemoteServer.url) {
|