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/index.js
CHANGED
|
@@ -7671,6 +7671,48 @@ Headless workers never interfere with desktop workers (they don't touch the scre
|
|
|
7671
7671
|
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.` : ""}
|
|
7672
7672
|
|
|
7673
7673
|
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.
|
|
7674
|
+
|
|
7675
|
+
### How to write a worker goal (and what NOT to put in it)
|
|
7676
|
+
|
|
7677
|
+
You delegate; the worker executes. Stay at the **what** level, not the **how**.
|
|
7678
|
+
|
|
7679
|
+
**DO** put in the goal:
|
|
7680
|
+
|
|
7681
|
+
- The end objective ("open the macOS Weather app and capture the forecast for Anchorage as a screen recording").
|
|
7682
|
+
- Which skills the worker should load up-front (\`load_skill recording\`, \`load_skill computer-use\`).
|
|
7683
|
+
- Acceptance criteria ("verify the city name is visible in the screenshot before reporting done").
|
|
7684
|
+
- Routing back ("post the recording URL to Slack channel C0123 thread 1700.001").
|
|
7685
|
+
|
|
7686
|
+
**DO NOT** put in the goal (when you're inventing commands from memory):
|
|
7687
|
+
|
|
7688
|
+
- Literal shell commands (\`screencapture -v -V 45 -C /tmp/...\`, \`osascript -e ...\`, \`cliclick kp:cmd+f\`).
|
|
7689
|
+
- Pre-written step-by-step bash that you're drafting from training-data recall.
|
|
7690
|
+
- The names of tools you can't see in your current toolset.
|
|
7691
|
+
|
|
7692
|
+
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.
|
|
7693
|
+
|
|
7694
|
+
**Exceptions \u2014 concrete steps ARE appropriate ONLY when relayed verbatim:**
|
|
7695
|
+
|
|
7696
|
+
You CAN include literal step-by-step commands when one of these is true:
|
|
7697
|
+
|
|
7698
|
+
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.
|
|
7699
|
+
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.
|
|
7700
|
+
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.
|
|
7701
|
+
|
|
7702
|
+
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\`"*.
|
|
7703
|
+
|
|
7704
|
+
What you do NOT do:
|
|
7705
|
+
|
|
7706
|
+
- **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.
|
|
7707
|
+
- **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.
|
|
7708
|
+
|
|
7709
|
+
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.
|
|
7710
|
+
|
|
7711
|
+
Bad goal (don't do this):
|
|
7712
|
+
> "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'..."
|
|
7713
|
+
|
|
7714
|
+
Good goal (do this):
|
|
7715
|
+
> "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."
|
|
7674
7716
|
`;
|
|
7675
7717
|
}
|
|
7676
7718
|
function createSummaryPrompt(conversationHistory) {
|
|
@@ -10587,11 +10629,11 @@ ${p.text}` : p.text;
|
|
|
10587
10629
|
const { isRemoteConfigured: isRemoteConfigured2, storageQueries: storageQueries2 } = await Promise.resolve().then(() => (init_remote(), remote_exports));
|
|
10588
10630
|
if (!isRemoteConfigured2()) return [];
|
|
10589
10631
|
const { readFile: readFile12 } = await import("fs/promises");
|
|
10590
|
-
const { join:
|
|
10632
|
+
const { join: join17, basename: basename6 } = await import("path");
|
|
10591
10633
|
const urls = [];
|
|
10592
10634
|
for (const filePath of filePaths) {
|
|
10593
10635
|
try {
|
|
10594
|
-
const fullPath = filePath.startsWith("/") ? filePath :
|
|
10636
|
+
const fullPath = filePath.startsWith("/") ? filePath : join17(this.session.workingDirectory, filePath);
|
|
10595
10637
|
const fileName = basename6(fullPath);
|
|
10596
10638
|
const ext = fileName.split(".").pop()?.toLowerCase() || "";
|
|
10597
10639
|
const mimeMap = {
|
|
@@ -10795,6 +10837,121 @@ var init_session_lock = __esm({
|
|
|
10795
10837
|
}
|
|
10796
10838
|
});
|
|
10797
10839
|
|
|
10840
|
+
// src/orchestrator/webhook-events.ts
|
|
10841
|
+
import { existsSync as existsSync18, readFileSync as readFileSync9, appendFileSync as appendFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync7 } from "fs";
|
|
10842
|
+
import { dirname as dirname6, join as join12 } from "path";
|
|
10843
|
+
import { nanoid as nanoid10 } from "nanoid";
|
|
10844
|
+
function logFilePath() {
|
|
10845
|
+
return join12(getAppDataDirectory(), "webhook-events.jsonl");
|
|
10846
|
+
}
|
|
10847
|
+
function ensureLoaded() {
|
|
10848
|
+
if (cache !== null) return cache;
|
|
10849
|
+
cache = [];
|
|
10850
|
+
try {
|
|
10851
|
+
const p = logFilePath();
|
|
10852
|
+
if (!existsSync18(p)) return cache;
|
|
10853
|
+
const lines = readFileSync9(p, "utf-8").split("\n").filter(Boolean);
|
|
10854
|
+
for (const line of lines) {
|
|
10855
|
+
try {
|
|
10856
|
+
cache.push(JSON.parse(line));
|
|
10857
|
+
} catch {
|
|
10858
|
+
}
|
|
10859
|
+
}
|
|
10860
|
+
if (cache.length > MAX_EVENTS) {
|
|
10861
|
+
cache = cache.slice(-MAX_EVENTS);
|
|
10862
|
+
try {
|
|
10863
|
+
writeFileSync3(p, cache.map((e) => JSON.stringify(e)).join("\n") + "\n");
|
|
10864
|
+
} catch {
|
|
10865
|
+
}
|
|
10866
|
+
}
|
|
10867
|
+
} catch {
|
|
10868
|
+
}
|
|
10869
|
+
return cache;
|
|
10870
|
+
}
|
|
10871
|
+
function appendEvent(ev) {
|
|
10872
|
+
const list = ensureLoaded();
|
|
10873
|
+
list.push(ev);
|
|
10874
|
+
if (list.length > MAX_EVENTS) list.shift();
|
|
10875
|
+
try {
|
|
10876
|
+
const p = logFilePath();
|
|
10877
|
+
mkdirSync7(dirname6(p), { recursive: true });
|
|
10878
|
+
appendFileSync3(p, JSON.stringify(ev) + "\n");
|
|
10879
|
+
} catch {
|
|
10880
|
+
}
|
|
10881
|
+
}
|
|
10882
|
+
function recordEvent(ev) {
|
|
10883
|
+
const full = {
|
|
10884
|
+
id: ev.id ?? nanoid10(),
|
|
10885
|
+
ts: ev.ts ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
10886
|
+
source: ev.source,
|
|
10887
|
+
status: ev.status,
|
|
10888
|
+
subtype: ev.subtype,
|
|
10889
|
+
channel: ev.channel,
|
|
10890
|
+
user: ev.user,
|
|
10891
|
+
textSnippet: ev.textSnippet?.slice(0, 200),
|
|
10892
|
+
dropReason: ev.dropReason,
|
|
10893
|
+
error: ev.error,
|
|
10894
|
+
sessionId: ev.sessionId,
|
|
10895
|
+
durationMs: ev.durationMs,
|
|
10896
|
+
meta: ev.meta
|
|
10897
|
+
};
|
|
10898
|
+
appendEvent(full);
|
|
10899
|
+
return full.id;
|
|
10900
|
+
}
|
|
10901
|
+
function updateEvent(id, patch) {
|
|
10902
|
+
const list = ensureLoaded();
|
|
10903
|
+
const i = list.findIndex((e) => e.id === id);
|
|
10904
|
+
if (i < 0) return;
|
|
10905
|
+
list[i] = { ...list[i], ...patch };
|
|
10906
|
+
try {
|
|
10907
|
+
const p = logFilePath();
|
|
10908
|
+
mkdirSync7(dirname6(p), { recursive: true });
|
|
10909
|
+
writeFileSync3(p, list.map((e) => JSON.stringify(e)).join("\n") + "\n");
|
|
10910
|
+
} catch {
|
|
10911
|
+
}
|
|
10912
|
+
}
|
|
10913
|
+
function listEvents(filter = {}) {
|
|
10914
|
+
const list = ensureLoaded();
|
|
10915
|
+
const q = filter.q?.toLowerCase();
|
|
10916
|
+
const sinceTs = filter.since ? Date.parse(filter.since) : -Infinity;
|
|
10917
|
+
const beforeTs = filter.before ? Date.parse(filter.before) : Infinity;
|
|
10918
|
+
const matched = list.filter((e) => {
|
|
10919
|
+
if (filter.source && e.source !== filter.source) return false;
|
|
10920
|
+
if (filter.status && e.status !== filter.status) return false;
|
|
10921
|
+
const t = Date.parse(e.ts);
|
|
10922
|
+
if (t < sinceTs) return false;
|
|
10923
|
+
if (t >= beforeTs) return false;
|
|
10924
|
+
if (q) {
|
|
10925
|
+
const hay = `${e.channel ?? ""} ${e.user ?? ""} ${e.textSnippet ?? ""} ${e.dropReason ?? ""} ${e.error ?? ""} ${e.subtype ?? ""}`.toLowerCase();
|
|
10926
|
+
if (!hay.includes(q)) return false;
|
|
10927
|
+
}
|
|
10928
|
+
return true;
|
|
10929
|
+
});
|
|
10930
|
+
matched.reverse();
|
|
10931
|
+
const offset = Math.max(0, filter.offset ?? 0);
|
|
10932
|
+
const limit = Math.min(500, Math.max(1, filter.limit ?? 50));
|
|
10933
|
+
return {
|
|
10934
|
+
events: matched.slice(offset, offset + limit),
|
|
10935
|
+
total: matched.length
|
|
10936
|
+
};
|
|
10937
|
+
}
|
|
10938
|
+
function clearAllEvents() {
|
|
10939
|
+
cache = [];
|
|
10940
|
+
try {
|
|
10941
|
+
writeFileSync3(logFilePath(), "");
|
|
10942
|
+
} catch {
|
|
10943
|
+
}
|
|
10944
|
+
}
|
|
10945
|
+
var MAX_EVENTS, cache;
|
|
10946
|
+
var init_webhook_events = __esm({
|
|
10947
|
+
"src/orchestrator/webhook-events.ts"() {
|
|
10948
|
+
"use strict";
|
|
10949
|
+
init_config();
|
|
10950
|
+
MAX_EVENTS = 1e3;
|
|
10951
|
+
cache = null;
|
|
10952
|
+
}
|
|
10953
|
+
});
|
|
10954
|
+
|
|
10798
10955
|
// src/orchestrator/daemon.ts
|
|
10799
10956
|
var daemon_exports = {};
|
|
10800
10957
|
__export(daemon_exports, {
|
|
@@ -10856,6 +11013,17 @@ async function runDaemonTurn(sessionId, events) {
|
|
|
10856
11013
|
});
|
|
10857
11014
|
const finishedAt = /* @__PURE__ */ new Date();
|
|
10858
11015
|
const trimmed = text.trim();
|
|
11016
|
+
recordEvent({
|
|
11017
|
+
source: "daemon",
|
|
11018
|
+
status: error ? "failed" : "completed",
|
|
11019
|
+
channel: events[0]?.ref?.channel ?? void 0,
|
|
11020
|
+
user: events[0]?.ref?.user,
|
|
11021
|
+
textSnippet: trimmed.slice(0, 200),
|
|
11022
|
+
error,
|
|
11023
|
+
sessionId,
|
|
11024
|
+
durationMs: finishedAt.getTime() - startedAt.getTime(),
|
|
11025
|
+
meta: { triggeredBy: events.map((e) => e.content?.slice(0, 80)) }
|
|
11026
|
+
});
|
|
10859
11027
|
broadcast({ sessionId, text: trimmed, triggeredBy: events, startedAt, finishedAt, error });
|
|
10860
11028
|
}
|
|
10861
11029
|
var listeners;
|
|
@@ -10866,6 +11034,7 @@ var init_daemon = __esm({
|
|
|
10866
11034
|
init_session_lock();
|
|
10867
11035
|
init_db();
|
|
10868
11036
|
init_inbox();
|
|
11037
|
+
init_webhook_events();
|
|
10869
11038
|
listeners = /* @__PURE__ */ new Map();
|
|
10870
11039
|
}
|
|
10871
11040
|
});
|
|
@@ -11043,8 +11212,8 @@ import { Hono as Hono9 } from "hono";
|
|
|
11043
11212
|
import { serve } from "@hono/node-server";
|
|
11044
11213
|
import { cors } from "hono/cors";
|
|
11045
11214
|
import { logger } from "hono/logger";
|
|
11046
|
-
import { existsSync as
|
|
11047
|
-
import { resolve as resolve11, dirname as
|
|
11215
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync10, writeFileSync as writeFileSync6 } from "fs";
|
|
11216
|
+
import { resolve as resolve11, dirname as dirname8, join as join16 } from "path";
|
|
11048
11217
|
import { spawn as spawn2 } from "child_process";
|
|
11049
11218
|
import { createServer as createNetServer } from "net";
|
|
11050
11219
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
@@ -11058,10 +11227,10 @@ init_checkpoints();
|
|
|
11058
11227
|
import { Hono } from "hono";
|
|
11059
11228
|
import { zValidator } from "@hono/zod-validator";
|
|
11060
11229
|
import { z as z17 } from "zod";
|
|
11061
|
-
import { existsSync as
|
|
11230
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync8, writeFileSync as writeFileSync4, readdirSync as readdirSync3, statSync as statSync2, unlinkSync as unlinkSync3 } from "fs";
|
|
11062
11231
|
import { readdir as readdir6 } from "fs/promises";
|
|
11063
|
-
import { join as
|
|
11064
|
-
import { nanoid as
|
|
11232
|
+
import { join as join13, basename as basename5, extname as extname8, relative as relative9 } from "path";
|
|
11233
|
+
import { nanoid as nanoid11 } from "nanoid";
|
|
11065
11234
|
|
|
11066
11235
|
// src/tasks/agent-status.ts
|
|
11067
11236
|
init_questions();
|
|
@@ -11702,12 +11871,12 @@ sessions2.get("/:id/diff/:filePath", async (c) => {
|
|
|
11702
11871
|
});
|
|
11703
11872
|
function getAttachmentsDir(sessionId) {
|
|
11704
11873
|
const appDataDir = getAppDataDirectory();
|
|
11705
|
-
return
|
|
11874
|
+
return join13(appDataDir, "attachments", sessionId);
|
|
11706
11875
|
}
|
|
11707
11876
|
function ensureAttachmentsDir(sessionId) {
|
|
11708
11877
|
const dir = getAttachmentsDir(sessionId);
|
|
11709
|
-
if (!
|
|
11710
|
-
|
|
11878
|
+
if (!existsSync19(dir)) {
|
|
11879
|
+
mkdirSync8(dir, { recursive: true });
|
|
11711
11880
|
}
|
|
11712
11881
|
return dir;
|
|
11713
11882
|
}
|
|
@@ -11718,12 +11887,12 @@ sessions2.get("/:id/attachments", async (c) => {
|
|
|
11718
11887
|
return c.json({ error: "Session not found" }, 404);
|
|
11719
11888
|
}
|
|
11720
11889
|
const dir = getAttachmentsDir(sessionId);
|
|
11721
|
-
if (!
|
|
11890
|
+
if (!existsSync19(dir)) {
|
|
11722
11891
|
return c.json({ sessionId, attachments: [], count: 0 });
|
|
11723
11892
|
}
|
|
11724
11893
|
const files = readdirSync3(dir);
|
|
11725
11894
|
const attachments = files.map((filename) => {
|
|
11726
|
-
const filePath =
|
|
11895
|
+
const filePath = join13(dir, filename);
|
|
11727
11896
|
const stats = statSync2(filePath);
|
|
11728
11897
|
return {
|
|
11729
11898
|
id: filename.split("_")[0],
|
|
@@ -11755,12 +11924,12 @@ sessions2.post("/:id/attachments", async (c) => {
|
|
|
11755
11924
|
return c.json({ error: "No file provided" }, 400);
|
|
11756
11925
|
}
|
|
11757
11926
|
const dir = ensureAttachmentsDir(sessionId);
|
|
11758
|
-
const id =
|
|
11927
|
+
const id = nanoid11(10);
|
|
11759
11928
|
const ext = extname8(file.name) || "";
|
|
11760
11929
|
const safeFilename = `${id}_${basename5(file.name).replace(/[^a-zA-Z0-9._-]/g, "_")}`;
|
|
11761
|
-
const filePath =
|
|
11930
|
+
const filePath = join13(dir, safeFilename);
|
|
11762
11931
|
const arrayBuffer = await file.arrayBuffer();
|
|
11763
|
-
|
|
11932
|
+
writeFileSync4(filePath, Buffer.from(arrayBuffer));
|
|
11764
11933
|
return c.json({
|
|
11765
11934
|
id,
|
|
11766
11935
|
filename: file.name,
|
|
@@ -11781,16 +11950,16 @@ sessions2.post("/:id/attachments", async (c) => {
|
|
|
11781
11950
|
return c.json({ error: "Missing filename or data" }, 400);
|
|
11782
11951
|
}
|
|
11783
11952
|
const dir = ensureAttachmentsDir(sessionId);
|
|
11784
|
-
const id =
|
|
11953
|
+
const id = nanoid11(10);
|
|
11785
11954
|
const ext = extname8(body.filename) || "";
|
|
11786
11955
|
const safeFilename = `${id}_${basename5(body.filename).replace(/[^a-zA-Z0-9._-]/g, "_")}`;
|
|
11787
|
-
const filePath =
|
|
11956
|
+
const filePath = join13(dir, safeFilename);
|
|
11788
11957
|
let base64Data = body.data;
|
|
11789
11958
|
if (base64Data.includes(",")) {
|
|
11790
11959
|
base64Data = base64Data.split(",")[1];
|
|
11791
11960
|
}
|
|
11792
11961
|
const buffer = Buffer.from(base64Data, "base64");
|
|
11793
|
-
|
|
11962
|
+
writeFileSync4(filePath, buffer);
|
|
11794
11963
|
return c.json({
|
|
11795
11964
|
id,
|
|
11796
11965
|
filename: body.filename,
|
|
@@ -11813,7 +11982,7 @@ sessions2.delete("/:id/attachments/:attachmentId", async (c) => {
|
|
|
11813
11982
|
return c.json({ error: "Session not found" }, 404);
|
|
11814
11983
|
}
|
|
11815
11984
|
const dir = getAttachmentsDir(sessionId);
|
|
11816
|
-
if (!
|
|
11985
|
+
if (!existsSync19(dir)) {
|
|
11817
11986
|
return c.json({ error: "Attachment not found" }, 404);
|
|
11818
11987
|
}
|
|
11819
11988
|
const files = readdirSync3(dir);
|
|
@@ -11821,7 +11990,7 @@ sessions2.delete("/:id/attachments/:attachmentId", async (c) => {
|
|
|
11821
11990
|
if (!file) {
|
|
11822
11991
|
return c.json({ error: "Attachment not found" }, 404);
|
|
11823
11992
|
}
|
|
11824
|
-
const filePath =
|
|
11993
|
+
const filePath = join13(dir, file);
|
|
11825
11994
|
unlinkSync3(filePath);
|
|
11826
11995
|
return c.json({ success: true, id: attachmentId });
|
|
11827
11996
|
});
|
|
@@ -11904,7 +12073,7 @@ async function listWorkspaceFiles(baseDir, currentDir, query, limit, results = [
|
|
|
11904
12073
|
const entries = await readdir6(currentDir, { withFileTypes: true });
|
|
11905
12074
|
for (const entry2 of entries) {
|
|
11906
12075
|
if (results.length >= limit * 2) break;
|
|
11907
|
-
const fullPath =
|
|
12076
|
+
const fullPath = join13(currentDir, entry2.name);
|
|
11908
12077
|
const relativePath = relative9(baseDir, fullPath);
|
|
11909
12078
|
if (entry2.isDirectory() && IGNORED_DIRECTORIES.has(entry2.name)) {
|
|
11910
12079
|
continue;
|
|
@@ -11952,7 +12121,7 @@ sessions2.get(
|
|
|
11952
12121
|
return c.json({ error: "Session not found" }, 404);
|
|
11953
12122
|
}
|
|
11954
12123
|
const workingDirectory = session.workingDirectory;
|
|
11955
|
-
if (!
|
|
12124
|
+
if (!existsSync19(workingDirectory)) {
|
|
11956
12125
|
return c.json({
|
|
11957
12126
|
sessionId,
|
|
11958
12127
|
workingDirectory,
|
|
@@ -12066,8 +12235,8 @@ init_config();
|
|
|
12066
12235
|
import { Hono as Hono2 } from "hono";
|
|
12067
12236
|
import { zValidator as zValidator2 } from "@hono/zod-validator";
|
|
12068
12237
|
import { z as z18 } from "zod";
|
|
12069
|
-
import { existsSync as
|
|
12070
|
-
import { join as
|
|
12238
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync9, writeFileSync as writeFileSync5 } from "fs";
|
|
12239
|
+
import { join as join14 } from "path";
|
|
12071
12240
|
|
|
12072
12241
|
// src/server/resumable-stream.ts
|
|
12073
12242
|
import { createResumableStreamContext } from "resumable-stream/generic";
|
|
@@ -12154,7 +12323,7 @@ var streamContext = createResumableStreamContext({
|
|
|
12154
12323
|
|
|
12155
12324
|
// src/server/routes/agents.ts
|
|
12156
12325
|
init_checkpoints();
|
|
12157
|
-
import { nanoid as
|
|
12326
|
+
import { nanoid as nanoid12 } from "nanoid";
|
|
12158
12327
|
init_stream_proxy();
|
|
12159
12328
|
init_recorder();
|
|
12160
12329
|
init_remote();
|
|
@@ -12274,12 +12443,12 @@ var rejectSchema = z18.object({
|
|
|
12274
12443
|
var streamAbortControllers = /* @__PURE__ */ new Map();
|
|
12275
12444
|
function getAttachmentsDirectory(sessionId) {
|
|
12276
12445
|
const appDataDir = getAppDataDirectory();
|
|
12277
|
-
return
|
|
12446
|
+
return join14(appDataDir, "attachments", sessionId);
|
|
12278
12447
|
}
|
|
12279
12448
|
async function saveAttachmentToDisk(sessionId, attachment, index) {
|
|
12280
12449
|
const attachmentsDir = getAttachmentsDirectory(sessionId);
|
|
12281
|
-
if (!
|
|
12282
|
-
|
|
12450
|
+
if (!existsSync20(attachmentsDir)) {
|
|
12451
|
+
mkdirSync9(attachmentsDir, { recursive: true });
|
|
12283
12452
|
}
|
|
12284
12453
|
let filename = attachment.filename;
|
|
12285
12454
|
if (!filename) {
|
|
@@ -12297,8 +12466,8 @@ async function saveAttachmentToDisk(sessionId, attachment, index) {
|
|
|
12297
12466
|
attachment.mediaType = resized.mediaType;
|
|
12298
12467
|
attachment.data = buffer.toString("base64");
|
|
12299
12468
|
}
|
|
12300
|
-
const filePath =
|
|
12301
|
-
|
|
12469
|
+
const filePath = join14(attachmentsDir, filename);
|
|
12470
|
+
writeFileSync5(filePath, buffer);
|
|
12302
12471
|
return filePath;
|
|
12303
12472
|
}
|
|
12304
12473
|
function stripDataUrlPrefix2(data) {
|
|
@@ -12734,7 +12903,7 @@ ${prompt}` });
|
|
|
12734
12903
|
});
|
|
12735
12904
|
} catch {
|
|
12736
12905
|
}
|
|
12737
|
-
const streamId = `stream_${id}_${
|
|
12906
|
+
const streamId = `stream_${id}_${nanoid12(10)}`;
|
|
12738
12907
|
console.log(`[STREAM] Creating stream ${streamId} for session ${id}`);
|
|
12739
12908
|
await activeStreamQueries.create(id, streamId);
|
|
12740
12909
|
const stream = await streamContext.resumableStream(
|
|
@@ -12939,7 +13108,7 @@ agents.post(
|
|
|
12939
13108
|
});
|
|
12940
13109
|
const session = agent.getSession();
|
|
12941
13110
|
const enrichedPrompt = enrichPromptWithDevtoolsContext(session.id, body.prompt);
|
|
12942
|
-
const streamId = `stream_${session.id}_${
|
|
13111
|
+
const streamId = `stream_${session.id}_${nanoid12(10)}`;
|
|
12943
13112
|
await createCheckpoint(session.id, session.workingDirectory, 0);
|
|
12944
13113
|
await activeStreamQueries.create(session.id, streamId);
|
|
12945
13114
|
const createQuickStreamProducer = () => {
|
|
@@ -13258,26 +13427,26 @@ init_config();
|
|
|
13258
13427
|
import { Hono as Hono3 } from "hono";
|
|
13259
13428
|
import { zValidator as zValidator3 } from "@hono/zod-validator";
|
|
13260
13429
|
import { z as z19 } from "zod";
|
|
13261
|
-
import { readFileSync as
|
|
13430
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
13262
13431
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
13263
|
-
import { dirname as
|
|
13432
|
+
import { dirname as dirname7, join as join15 } from "path";
|
|
13264
13433
|
var __filename = fileURLToPath3(import.meta.url);
|
|
13265
|
-
var __dirname =
|
|
13434
|
+
var __dirname = dirname7(__filename);
|
|
13266
13435
|
var possiblePaths = [
|
|
13267
|
-
|
|
13436
|
+
join15(__dirname, "../package.json"),
|
|
13268
13437
|
// From dist/server -> dist/../package.json
|
|
13269
|
-
|
|
13438
|
+
join15(__dirname, "../../package.json"),
|
|
13270
13439
|
// From dist/server (if nested differently)
|
|
13271
|
-
|
|
13440
|
+
join15(__dirname, "../../../package.json"),
|
|
13272
13441
|
// From src/server/routes (development)
|
|
13273
|
-
|
|
13442
|
+
join15(process.cwd(), "package.json")
|
|
13274
13443
|
// From current working directory
|
|
13275
13444
|
];
|
|
13276
13445
|
var currentVersion = "0.0.0";
|
|
13277
13446
|
var packageName = "sparkecoder";
|
|
13278
13447
|
for (const packageJsonPath of possiblePaths) {
|
|
13279
13448
|
try {
|
|
13280
|
-
const packageJson = JSON.parse(
|
|
13449
|
+
const packageJson = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
|
|
13281
13450
|
if (packageJson.name === "sparkecoder") {
|
|
13282
13451
|
currentVersion = packageJson.version || "0.0.0";
|
|
13283
13452
|
packageName = packageJson.name || "sparkecoder";
|
|
@@ -13727,7 +13896,7 @@ init_config();
|
|
|
13727
13896
|
import { Hono as Hono5 } from "hono";
|
|
13728
13897
|
import { zValidator as zValidator5 } from "@hono/zod-validator";
|
|
13729
13898
|
import { z as z21 } from "zod";
|
|
13730
|
-
import { nanoid as
|
|
13899
|
+
import { nanoid as nanoid13 } from "nanoid";
|
|
13731
13900
|
init_questions();
|
|
13732
13901
|
var tasks = new Hono5();
|
|
13733
13902
|
var taskAbortControllers = /* @__PURE__ */ new Map();
|
|
@@ -13808,7 +13977,7 @@ tasks.post(
|
|
|
13808
13977
|
const taskId = agent.sessionId;
|
|
13809
13978
|
const abortController = new AbortController();
|
|
13810
13979
|
taskAbortControllers.set(taskId, abortController);
|
|
13811
|
-
const streamId = `stream_${taskId}_${
|
|
13980
|
+
const streamId = `stream_${taskId}_${nanoid13(10)}`;
|
|
13812
13981
|
await activeStreamQueries.create(taskId, streamId);
|
|
13813
13982
|
const taskStreamProducer = () => {
|
|
13814
13983
|
const { readable, writable } = new TransformStream();
|
|
@@ -14034,6 +14203,7 @@ function verifySlackSignature(opts) {
|
|
|
14034
14203
|
// src/server/routes/slack.ts
|
|
14035
14204
|
init_client3();
|
|
14036
14205
|
init_slack();
|
|
14206
|
+
init_webhook_events();
|
|
14037
14207
|
init_inbox();
|
|
14038
14208
|
var recentlyHandled = /* @__PURE__ */ new Map();
|
|
14039
14209
|
var MAX_RECENT = 1e3;
|
|
@@ -14074,7 +14244,17 @@ slack.post("/events", async (c) => {
|
|
|
14074
14244
|
}
|
|
14075
14245
|
if (payload?.type === "event_callback" && payload?.event) {
|
|
14076
14246
|
const ev = payload.event;
|
|
14247
|
+
const auditId = recordEvent({
|
|
14248
|
+
source: "slack",
|
|
14249
|
+
status: "received",
|
|
14250
|
+
subtype: ev.type === "message" ? `message.${ev.channel_type ?? "channels"}` : ev.type,
|
|
14251
|
+
channel: ev.channel,
|
|
14252
|
+
user: ev.user,
|
|
14253
|
+
textSnippet: typeof ev.text === "string" ? ev.text : void 0,
|
|
14254
|
+
meta: { ts: ev.ts, thread_ts: ev.thread_ts, team: ev.team, event_subtype: ev.subtype }
|
|
14255
|
+
});
|
|
14077
14256
|
if (alreadyHandled(ev.channel, ev.ts)) {
|
|
14257
|
+
updateEvent(auditId, { status: "dropped", dropReason: "duplicate_delivery" });
|
|
14078
14258
|
return c.json({ ok: true });
|
|
14079
14259
|
}
|
|
14080
14260
|
const { event: inbound, dropReason } = slackEventToInboundResult(ev);
|
|
@@ -14084,6 +14264,7 @@ slack.post("/events", async (c) => {
|
|
|
14084
14264
|
const ours = isThreadOwned(ev.channel, ev.thread_ts) || await threadBelongsToUs(ev.channel, ev.thread_ts);
|
|
14085
14265
|
if (!ours) {
|
|
14086
14266
|
console.log(`[slack] dropping thread reply in unknown thread: channel=${ev.channel} thread=${ev.thread_ts}`);
|
|
14267
|
+
updateEvent(auditId, { status: "dropped", dropReason: "thread_not_owned" });
|
|
14087
14268
|
return c.json({ ok: true });
|
|
14088
14269
|
}
|
|
14089
14270
|
}
|
|
@@ -14096,8 +14277,12 @@ slack.post("/events", async (c) => {
|
|
|
14096
14277
|
const orchestratorId = await findOrCreateOrchestratorId();
|
|
14097
14278
|
if (orchestratorId) {
|
|
14098
14279
|
pushToInbox(orchestratorId, inbound);
|
|
14280
|
+
updateEvent(auditId, { status: "routed", sessionId: orchestratorId });
|
|
14281
|
+
} else {
|
|
14282
|
+
updateEvent(auditId, { status: "error", error: "no orchestrator session available" });
|
|
14099
14283
|
}
|
|
14100
14284
|
} else if (dropReason) {
|
|
14285
|
+
updateEvent(auditId, { status: "dropped", dropReason });
|
|
14101
14286
|
const userFacingDrops = ["user_not_allowed", "channel_not_allowed", "dm_blocked"];
|
|
14102
14287
|
if (userFacingDrops.includes(dropReason)) {
|
|
14103
14288
|
console.log(`[slack] dropped event from user=${payload.event.user} channel=${payload.event.channel}: ${dropReason}`);
|
|
@@ -14160,13 +14345,30 @@ async function sendDeniedReply(event) {
|
|
|
14160
14345
|
init_webhooks_store();
|
|
14161
14346
|
init_webhook();
|
|
14162
14347
|
init_inbox();
|
|
14348
|
+
init_webhook_events();
|
|
14163
14349
|
import { Hono as Hono7 } from "hono";
|
|
14164
14350
|
var inbox = new Hono7();
|
|
14165
14351
|
inbox.post("/:token", async (c) => {
|
|
14166
14352
|
const token = c.req.param("token");
|
|
14167
|
-
if (!token || token.length < 16)
|
|
14353
|
+
if (!token || token.length < 16) {
|
|
14354
|
+
recordEvent({
|
|
14355
|
+
source: "inbox",
|
|
14356
|
+
status: "dropped",
|
|
14357
|
+
dropReason: "invalid_token_format",
|
|
14358
|
+
meta: { tokenLen: token?.length ?? 0 }
|
|
14359
|
+
});
|
|
14360
|
+
return c.json({ error: "invalid token" }, 401);
|
|
14361
|
+
}
|
|
14168
14362
|
const lookup = await findByToken(token);
|
|
14169
|
-
if (!lookup)
|
|
14363
|
+
if (!lookup) {
|
|
14364
|
+
recordEvent({
|
|
14365
|
+
source: "inbox",
|
|
14366
|
+
status: "dropped",
|
|
14367
|
+
dropReason: "unknown_token",
|
|
14368
|
+
meta: { tokenPrefix: token.slice(0, 8) + "\u2026" }
|
|
14369
|
+
});
|
|
14370
|
+
return c.json({ error: "unknown token" }, 404);
|
|
14371
|
+
}
|
|
14170
14372
|
let body;
|
|
14171
14373
|
const contentType = c.req.header("content-type") || "";
|
|
14172
14374
|
try {
|
|
@@ -14188,6 +14390,14 @@ inbox.post("/:token", async (c) => {
|
|
|
14188
14390
|
pushToInbox(lookup.orchestratorSessionId, event);
|
|
14189
14391
|
void recordHit(lookup.orchestratorSessionId, lookup.webhook.id).catch(() => {
|
|
14190
14392
|
});
|
|
14393
|
+
recordEvent({
|
|
14394
|
+
source: "inbox",
|
|
14395
|
+
status: "routed",
|
|
14396
|
+
channel: lookup.webhook.name,
|
|
14397
|
+
textSnippet: typeof body === "string" ? body : JSON.stringify(body).slice(0, 200),
|
|
14398
|
+
sessionId: lookup.orchestratorSessionId,
|
|
14399
|
+
meta: { wake: lookup.webhook.wake, webhookId: lookup.webhook.id }
|
|
14400
|
+
});
|
|
14191
14401
|
return c.json({ ok: true, queued: true, wake: lookup.webhook.wake });
|
|
14192
14402
|
});
|
|
14193
14403
|
|
|
@@ -14199,6 +14409,7 @@ init_webhooks_store();
|
|
|
14199
14409
|
init_messenger();
|
|
14200
14410
|
init_store();
|
|
14201
14411
|
init_pool();
|
|
14412
|
+
init_webhook_events();
|
|
14202
14413
|
import { Hono as Hono8 } from "hono";
|
|
14203
14414
|
import { zValidator as zValidator6 } from "@hono/zod-validator";
|
|
14204
14415
|
import { z as z22 } from "zod";
|
|
@@ -14257,6 +14468,24 @@ function webhookPrefix() {
|
|
|
14257
14468
|
const token = cfg?.webhooks?.token;
|
|
14258
14469
|
return token ? `/w/${token}` : "/api";
|
|
14259
14470
|
}
|
|
14471
|
+
integrations.get("/events", async (c) => {
|
|
14472
|
+
const q = c.req.query();
|
|
14473
|
+
const filter = {
|
|
14474
|
+
source: q.source,
|
|
14475
|
+
status: q.status,
|
|
14476
|
+
q: q.q,
|
|
14477
|
+
since: q.since,
|
|
14478
|
+
before: q.before,
|
|
14479
|
+
limit: q.limit ? Math.min(500, Math.max(1, parseInt(q.limit, 10))) : 50,
|
|
14480
|
+
offset: q.offset ? Math.max(0, parseInt(q.offset, 10)) : 0
|
|
14481
|
+
};
|
|
14482
|
+
const { events, total } = listEvents(filter);
|
|
14483
|
+
return c.json({ events, total, limit: filter.limit, offset: filter.offset });
|
|
14484
|
+
});
|
|
14485
|
+
integrations.delete("/events", async (c) => {
|
|
14486
|
+
clearAllEvents();
|
|
14487
|
+
return c.json({ ok: true });
|
|
14488
|
+
});
|
|
14260
14489
|
integrations.get("/", async (c) => {
|
|
14261
14490
|
const cfg = getConfig();
|
|
14262
14491
|
return c.json({
|
|
@@ -14619,13 +14848,13 @@ var DEFAULT_WEB_PORT = 6969;
|
|
|
14619
14848
|
var WEB_PORT_SEQUENCE = [6969, 6970, 6971, 6972, 6973, 6974, 6975, 6976, 6977, 6978];
|
|
14620
14849
|
function getWebDirectory() {
|
|
14621
14850
|
try {
|
|
14622
|
-
const currentDir =
|
|
14851
|
+
const currentDir = dirname8(fileURLToPath4(import.meta.url));
|
|
14623
14852
|
const webDir = resolve11(currentDir, "..", "web");
|
|
14624
|
-
if (
|
|
14853
|
+
if (existsSync21(webDir) && existsSync21(join16(webDir, "package.json"))) {
|
|
14625
14854
|
return webDir;
|
|
14626
14855
|
}
|
|
14627
14856
|
const altWebDir = resolve11(currentDir, "..", "..", "web");
|
|
14628
|
-
if (
|
|
14857
|
+
if (existsSync21(altWebDir) && existsSync21(join16(altWebDir, "package.json"))) {
|
|
14629
14858
|
return altWebDir;
|
|
14630
14859
|
}
|
|
14631
14860
|
return null;
|
|
@@ -14683,23 +14912,23 @@ async function findWebPort(preferredPort) {
|
|
|
14683
14912
|
return { port: preferredPort, alreadyRunning: false };
|
|
14684
14913
|
}
|
|
14685
14914
|
function hasProductionBuild(webDir) {
|
|
14686
|
-
const buildIdPath =
|
|
14687
|
-
return
|
|
14915
|
+
const buildIdPath = join16(webDir, ".next", "BUILD_ID");
|
|
14916
|
+
return existsSync21(buildIdPath);
|
|
14688
14917
|
}
|
|
14689
14918
|
function hasSourceFiles(webDir) {
|
|
14690
|
-
const appDir =
|
|
14691
|
-
const pagesDir =
|
|
14692
|
-
const rootAppDir =
|
|
14693
|
-
const rootPagesDir =
|
|
14694
|
-
return
|
|
14919
|
+
const appDir = join16(webDir, "src", "app");
|
|
14920
|
+
const pagesDir = join16(webDir, "src", "pages");
|
|
14921
|
+
const rootAppDir = join16(webDir, "app");
|
|
14922
|
+
const rootPagesDir = join16(webDir, "pages");
|
|
14923
|
+
return existsSync21(appDir) || existsSync21(pagesDir) || existsSync21(rootAppDir) || existsSync21(rootPagesDir);
|
|
14695
14924
|
}
|
|
14696
14925
|
function getStandaloneServerPath(webDir) {
|
|
14697
14926
|
const possiblePaths2 = [
|
|
14698
|
-
|
|
14699
|
-
|
|
14927
|
+
join16(webDir, ".next", "standalone", "server.js"),
|
|
14928
|
+
join16(webDir, ".next", "standalone", "web", "server.js")
|
|
14700
14929
|
];
|
|
14701
14930
|
for (const serverPath of possiblePaths2) {
|
|
14702
|
-
if (
|
|
14931
|
+
if (existsSync21(serverPath)) {
|
|
14703
14932
|
return serverPath;
|
|
14704
14933
|
}
|
|
14705
14934
|
}
|
|
@@ -14739,15 +14968,15 @@ async function startWebUI(apiPort, webPort = DEFAULT_WEB_PORT, quiet = false, pu
|
|
|
14739
14968
|
if (!quiet) console.log(` \u2713 Web UI already running at http://localhost:${actualPort}`);
|
|
14740
14969
|
return { process: null, port: actualPort };
|
|
14741
14970
|
}
|
|
14742
|
-
const usePnpm =
|
|
14743
|
-
const useNpm = !usePnpm &&
|
|
14971
|
+
const usePnpm = existsSync21(join16(webDir, "pnpm-lock.yaml"));
|
|
14972
|
+
const useNpm = !usePnpm && existsSync21(join16(webDir, "package-lock.json"));
|
|
14744
14973
|
const pkgManager = usePnpm ? "pnpm" : useNpm ? "npm" : "npx";
|
|
14745
14974
|
const { NODE_OPTIONS, TSX_TSCONFIG_PATH, ...cleanEnv } = process.env;
|
|
14746
14975
|
const apiUrl = publicUrl || `http://127.0.0.1:${apiPort}`;
|
|
14747
14976
|
const runtimeConfig = { apiBaseUrl: apiUrl };
|
|
14748
|
-
const runtimeConfigPath =
|
|
14977
|
+
const runtimeConfigPath = join16(webDir, "runtime-config.json");
|
|
14749
14978
|
try {
|
|
14750
|
-
|
|
14979
|
+
writeFileSync6(runtimeConfigPath, JSON.stringify(runtimeConfig, null, 2));
|
|
14751
14980
|
if (!quiet) console.log(` \u{1F4DD} Runtime config written to ${runtimeConfigPath}`);
|
|
14752
14981
|
} catch (err) {
|
|
14753
14982
|
if (!quiet) console.warn(` \u26A0 Could not write runtime config: ${err}`);
|
|
@@ -14767,7 +14996,7 @@ async function startWebUI(apiPort, webPort = DEFAULT_WEB_PORT, quiet = false, pu
|
|
|
14767
14996
|
if (standaloneServerPath) {
|
|
14768
14997
|
command = "node";
|
|
14769
14998
|
args = ["server.js"];
|
|
14770
|
-
cwd =
|
|
14999
|
+
cwd = dirname8(standaloneServerPath);
|
|
14771
15000
|
webEnv.PORT = String(actualPort);
|
|
14772
15001
|
webEnv.HOSTNAME = "0.0.0.0";
|
|
14773
15002
|
if (!quiet) console.log(" \u{1F4E6} Starting Web UI from standalone build...");
|
|
@@ -14960,8 +15189,8 @@ async function startServer(options = {}) {
|
|
|
14960
15189
|
if (options.workingDirectory) {
|
|
14961
15190
|
config.resolvedWorkingDirectory = options.workingDirectory;
|
|
14962
15191
|
}
|
|
14963
|
-
if (!
|
|
14964
|
-
|
|
15192
|
+
if (!existsSync21(config.resolvedWorkingDirectory)) {
|
|
15193
|
+
mkdirSync10(config.resolvedWorkingDirectory, { recursive: true });
|
|
14965
15194
|
if (!options.quiet) console.log(`\u{1F4C1} Created agent workspace: ${config.resolvedWorkingDirectory}`);
|
|
14966
15195
|
}
|
|
14967
15196
|
if (!config.resolvedRemoteServer.url) {
|