sparkecoder 0.1.115 → 0.1.117
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 +62 -0
- package/dist/agent/index.js.map +1 -1
- package/dist/cli.js +387 -108
- package/dist/cli.js.map +1 -1
- package/dist/db/index.d.ts +2 -2
- package/dist/{index-Biy5JTop.d.ts → index-Bi8Ek02A.d.ts} +104 -104
- package/dist/index.d.ts +5 -5
- package/dist/index.js +313 -64
- package/dist/index.js.map +1 -1
- package/dist/{schema-CYSKJZ3m.d.ts → schema-ecQSnCMz.d.ts} +3 -3
- package/dist/{search-CVVfuBPZ.d.ts → search-DOzC4ojH.d.ts} +4 -4
- package/dist/server/index.js +313 -64
- package/dist/server/index.js.map +1 -1
- package/dist/skills/default/computer-use.md +7 -0
- package/dist/skills/default/recording.md +5 -0
- package/dist/tools/index.d.ts +3 -3
- package/package.json +1 -1
- package/src/skills/default/computer-use.md +7 -0
- package/src/skills/default/recording.md +5 -0
- 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/{pSGgtxBjN5_o0YHZgQzXm → static/vLqK4jK7EKdLCpQ-D6-qL}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{pSGgtxBjN5_o0YHZgQzXm → static/vLqK4jK7EKdLCpQ-D6-qL}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/{pSGgtxBjN5_o0YHZgQzXm → static/vLqK4jK7EKdLCpQ-D6-qL}/_ssgManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{static/pSGgtxBjN5_o0YHZgQzXm → vLqK4jK7EKdLCpQ-D6-qL}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{static/pSGgtxBjN5_o0YHZgQzXm → vLqK4jK7EKdLCpQ-D6-qL}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/{static/pSGgtxBjN5_o0YHZgQzXm → vLqK4jK7EKdLCpQ-D6-qL}/_ssgManifest.js +0 -0
- /package/web/.next/static/{pSGgtxBjN5_o0YHZgQzXm → vLqK4jK7EKdLCpQ-D6-qL}/_buildManifest.js +0 -0
- /package/web/.next/static/{pSGgtxBjN5_o0YHZgQzXm → vLqK4jK7EKdLCpQ-D6-qL}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{pSGgtxBjN5_o0YHZgQzXm → vLqK4jK7EKdLCpQ-D6-qL}/_ssgManifest.js +0 -0
package/dist/index.js
CHANGED
|
@@ -7671,6 +7671,68 @@ 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 TALK to the user (versus how you reason internally)
|
|
7676
|
+
|
|
7677
|
+
All of the rules below \u2014 decomposition, parallel spawning, "don't invent commands", load-the-skill, etc. \u2014 are **your internal operating procedure**. They are how you decide what to do. They are NOT something to recite back to the user.
|
|
7678
|
+
|
|
7679
|
+
When replying to the user (Slack, web, or any channel), be a normal helpful assistant:
|
|
7680
|
+
|
|
7681
|
+
- Tell them *what you're doing*, not *how you're doing it internally*.
|
|
7682
|
+
- Don't quote your own prompt language ("just the goal", "read the skill", "no step-by-step from me", "decomposing into parallel workers"). The user doesn't care about your delegation pattern.
|
|
7683
|
+
- Don't narrate "handing off to a worker now" unless it's actually relevant (e.g. they asked how you work, or the work is going to take a noticeably long time).
|
|
7684
|
+
- Skip ceremony. A short acknowledgement + a brief description of the actual task + (optionally) a heads-up if there's anything they need to do or avoid is plenty.
|
|
7685
|
+
|
|
7686
|
+
| What you might be tempted to say | What you should say instead |
|
|
7687
|
+
|---|---|
|
|
7688
|
+
| *"Got it \u2014 handing it off with just the goal + 'read the skills and figure it out.' No step-by-step from me."* | *"On it. Recording a screen capture of the Weather app showing Anchorage. Don't touch the keyboard while it's running \u2014 I'll post the video when it's done."* |
|
|
7689
|
+
| *"Decomposing into two parallel workers: one headless, one desktop."* | *"Running the tests and pulling the diff at the same time. Back in ~30s."* |
|
|
7690
|
+
| *"Spawning worker \`screenshot-calc\` with goal: \u2026"* | *"Taking a screenshot of Calculator now."* |
|
|
7691
|
+
| *"I'll relay the user's instructions to the worker verbatim."* | *(say nothing \u2014 just do it)* |
|
|
7692
|
+
|
|
7693
|
+
If the user explicitly asks how you work, *then* you can explain the orchestrator/worker split. Otherwise: less is more.
|
|
7694
|
+
|
|
7695
|
+
### How to write a worker goal (and what NOT to put in it)
|
|
7696
|
+
|
|
7697
|
+
You delegate; the worker executes. Stay at the **what** level, not the **how**.
|
|
7698
|
+
|
|
7699
|
+
**DO** put in the goal:
|
|
7700
|
+
|
|
7701
|
+
- The end objective ("open the macOS Weather app and capture the forecast for Anchorage as a screen recording").
|
|
7702
|
+
- Which skills the worker should load up-front (\`load_skill recording\`, \`load_skill computer-use\`).
|
|
7703
|
+
- Acceptance criteria ("verify the city name is visible in the screenshot before reporting done").
|
|
7704
|
+
- Routing back ("post the recording URL to Slack channel C0123 thread 1700.001").
|
|
7705
|
+
|
|
7706
|
+
**DO NOT** put in the goal (when you're inventing commands from memory):
|
|
7707
|
+
|
|
7708
|
+
- Literal shell commands (\`screencapture -v -V 45 -C /tmp/...\`, \`osascript -e ...\`, \`cliclick kp:cmd+f\`).
|
|
7709
|
+
- Pre-written step-by-step bash that you're drafting from training-data recall.
|
|
7710
|
+
- The names of tools you can't see in your current toolset.
|
|
7711
|
+
|
|
7712
|
+
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.
|
|
7713
|
+
|
|
7714
|
+
**Exceptions \u2014 concrete steps ARE appropriate ONLY when relayed verbatim:**
|
|
7715
|
+
|
|
7716
|
+
You CAN include literal step-by-step commands when one of these is true:
|
|
7717
|
+
|
|
7718
|
+
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.
|
|
7719
|
+
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.
|
|
7720
|
+
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.
|
|
7721
|
+
|
|
7722
|
+
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\`"*.
|
|
7723
|
+
|
|
7724
|
+
What you do NOT do:
|
|
7725
|
+
|
|
7726
|
+
- **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.
|
|
7727
|
+
- **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.
|
|
7728
|
+
|
|
7729
|
+
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.
|
|
7730
|
+
|
|
7731
|
+
Bad goal (don't do this):
|
|
7732
|
+
> "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'..."
|
|
7733
|
+
|
|
7734
|
+
Good goal (do this):
|
|
7735
|
+
> "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
7736
|
`;
|
|
7675
7737
|
}
|
|
7676
7738
|
function createSummaryPrompt(conversationHistory) {
|
|
@@ -10587,11 +10649,11 @@ ${p.text}` : p.text;
|
|
|
10587
10649
|
const { isRemoteConfigured: isRemoteConfigured2, storageQueries: storageQueries2 } = await Promise.resolve().then(() => (init_remote(), remote_exports));
|
|
10588
10650
|
if (!isRemoteConfigured2()) return [];
|
|
10589
10651
|
const { readFile: readFile12 } = await import("fs/promises");
|
|
10590
|
-
const { join:
|
|
10652
|
+
const { join: join17, basename: basename6 } = await import("path");
|
|
10591
10653
|
const urls = [];
|
|
10592
10654
|
for (const filePath of filePaths) {
|
|
10593
10655
|
try {
|
|
10594
|
-
const fullPath = filePath.startsWith("/") ? filePath :
|
|
10656
|
+
const fullPath = filePath.startsWith("/") ? filePath : join17(this.session.workingDirectory, filePath);
|
|
10595
10657
|
const fileName = basename6(fullPath);
|
|
10596
10658
|
const ext = fileName.split(".").pop()?.toLowerCase() || "";
|
|
10597
10659
|
const mimeMap = {
|
|
@@ -10795,6 +10857,121 @@ var init_session_lock = __esm({
|
|
|
10795
10857
|
}
|
|
10796
10858
|
});
|
|
10797
10859
|
|
|
10860
|
+
// src/orchestrator/webhook-events.ts
|
|
10861
|
+
import { existsSync as existsSync18, readFileSync as readFileSync9, appendFileSync as appendFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync7 } from "fs";
|
|
10862
|
+
import { dirname as dirname6, join as join12 } from "path";
|
|
10863
|
+
import { nanoid as nanoid10 } from "nanoid";
|
|
10864
|
+
function logFilePath() {
|
|
10865
|
+
return join12(getAppDataDirectory(), "webhook-events.jsonl");
|
|
10866
|
+
}
|
|
10867
|
+
function ensureLoaded() {
|
|
10868
|
+
if (cache !== null) return cache;
|
|
10869
|
+
cache = [];
|
|
10870
|
+
try {
|
|
10871
|
+
const p = logFilePath();
|
|
10872
|
+
if (!existsSync18(p)) return cache;
|
|
10873
|
+
const lines = readFileSync9(p, "utf-8").split("\n").filter(Boolean);
|
|
10874
|
+
for (const line of lines) {
|
|
10875
|
+
try {
|
|
10876
|
+
cache.push(JSON.parse(line));
|
|
10877
|
+
} catch {
|
|
10878
|
+
}
|
|
10879
|
+
}
|
|
10880
|
+
if (cache.length > MAX_EVENTS) {
|
|
10881
|
+
cache = cache.slice(-MAX_EVENTS);
|
|
10882
|
+
try {
|
|
10883
|
+
writeFileSync3(p, cache.map((e) => JSON.stringify(e)).join("\n") + "\n");
|
|
10884
|
+
} catch {
|
|
10885
|
+
}
|
|
10886
|
+
}
|
|
10887
|
+
} catch {
|
|
10888
|
+
}
|
|
10889
|
+
return cache;
|
|
10890
|
+
}
|
|
10891
|
+
function appendEvent(ev) {
|
|
10892
|
+
const list = ensureLoaded();
|
|
10893
|
+
list.push(ev);
|
|
10894
|
+
if (list.length > MAX_EVENTS) list.shift();
|
|
10895
|
+
try {
|
|
10896
|
+
const p = logFilePath();
|
|
10897
|
+
mkdirSync7(dirname6(p), { recursive: true });
|
|
10898
|
+
appendFileSync3(p, JSON.stringify(ev) + "\n");
|
|
10899
|
+
} catch {
|
|
10900
|
+
}
|
|
10901
|
+
}
|
|
10902
|
+
function recordEvent(ev) {
|
|
10903
|
+
const full = {
|
|
10904
|
+
id: ev.id ?? nanoid10(),
|
|
10905
|
+
ts: ev.ts ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
10906
|
+
source: ev.source,
|
|
10907
|
+
status: ev.status,
|
|
10908
|
+
subtype: ev.subtype,
|
|
10909
|
+
channel: ev.channel,
|
|
10910
|
+
user: ev.user,
|
|
10911
|
+
textSnippet: ev.textSnippet?.slice(0, 200),
|
|
10912
|
+
dropReason: ev.dropReason,
|
|
10913
|
+
error: ev.error,
|
|
10914
|
+
sessionId: ev.sessionId,
|
|
10915
|
+
durationMs: ev.durationMs,
|
|
10916
|
+
meta: ev.meta
|
|
10917
|
+
};
|
|
10918
|
+
appendEvent(full);
|
|
10919
|
+
return full.id;
|
|
10920
|
+
}
|
|
10921
|
+
function updateEvent(id, patch) {
|
|
10922
|
+
const list = ensureLoaded();
|
|
10923
|
+
const i = list.findIndex((e) => e.id === id);
|
|
10924
|
+
if (i < 0) return;
|
|
10925
|
+
list[i] = { ...list[i], ...patch };
|
|
10926
|
+
try {
|
|
10927
|
+
const p = logFilePath();
|
|
10928
|
+
mkdirSync7(dirname6(p), { recursive: true });
|
|
10929
|
+
writeFileSync3(p, list.map((e) => JSON.stringify(e)).join("\n") + "\n");
|
|
10930
|
+
} catch {
|
|
10931
|
+
}
|
|
10932
|
+
}
|
|
10933
|
+
function listEvents(filter = {}) {
|
|
10934
|
+
const list = ensureLoaded();
|
|
10935
|
+
const q = filter.q?.toLowerCase();
|
|
10936
|
+
const sinceTs = filter.since ? Date.parse(filter.since) : -Infinity;
|
|
10937
|
+
const beforeTs = filter.before ? Date.parse(filter.before) : Infinity;
|
|
10938
|
+
const matched = list.filter((e) => {
|
|
10939
|
+
if (filter.source && e.source !== filter.source) return false;
|
|
10940
|
+
if (filter.status && e.status !== filter.status) return false;
|
|
10941
|
+
const t = Date.parse(e.ts);
|
|
10942
|
+
if (t < sinceTs) return false;
|
|
10943
|
+
if (t >= beforeTs) return false;
|
|
10944
|
+
if (q) {
|
|
10945
|
+
const hay = `${e.channel ?? ""} ${e.user ?? ""} ${e.textSnippet ?? ""} ${e.dropReason ?? ""} ${e.error ?? ""} ${e.subtype ?? ""}`.toLowerCase();
|
|
10946
|
+
if (!hay.includes(q)) return false;
|
|
10947
|
+
}
|
|
10948
|
+
return true;
|
|
10949
|
+
});
|
|
10950
|
+
matched.reverse();
|
|
10951
|
+
const offset = Math.max(0, filter.offset ?? 0);
|
|
10952
|
+
const limit = Math.min(500, Math.max(1, filter.limit ?? 50));
|
|
10953
|
+
return {
|
|
10954
|
+
events: matched.slice(offset, offset + limit),
|
|
10955
|
+
total: matched.length
|
|
10956
|
+
};
|
|
10957
|
+
}
|
|
10958
|
+
function clearAllEvents() {
|
|
10959
|
+
cache = [];
|
|
10960
|
+
try {
|
|
10961
|
+
writeFileSync3(logFilePath(), "");
|
|
10962
|
+
} catch {
|
|
10963
|
+
}
|
|
10964
|
+
}
|
|
10965
|
+
var MAX_EVENTS, cache;
|
|
10966
|
+
var init_webhook_events = __esm({
|
|
10967
|
+
"src/orchestrator/webhook-events.ts"() {
|
|
10968
|
+
"use strict";
|
|
10969
|
+
init_config();
|
|
10970
|
+
MAX_EVENTS = 1e3;
|
|
10971
|
+
cache = null;
|
|
10972
|
+
}
|
|
10973
|
+
});
|
|
10974
|
+
|
|
10798
10975
|
// src/orchestrator/daemon.ts
|
|
10799
10976
|
var daemon_exports = {};
|
|
10800
10977
|
__export(daemon_exports, {
|
|
@@ -10856,6 +11033,17 @@ async function runDaemonTurn(sessionId, events) {
|
|
|
10856
11033
|
});
|
|
10857
11034
|
const finishedAt = /* @__PURE__ */ new Date();
|
|
10858
11035
|
const trimmed = text.trim();
|
|
11036
|
+
recordEvent({
|
|
11037
|
+
source: "daemon",
|
|
11038
|
+
status: error ? "failed" : "completed",
|
|
11039
|
+
channel: events[0]?.ref?.channel ?? void 0,
|
|
11040
|
+
user: events[0]?.ref?.user,
|
|
11041
|
+
textSnippet: trimmed.slice(0, 200),
|
|
11042
|
+
error,
|
|
11043
|
+
sessionId,
|
|
11044
|
+
durationMs: finishedAt.getTime() - startedAt.getTime(),
|
|
11045
|
+
meta: { triggeredBy: events.map((e) => e.content?.slice(0, 80)) }
|
|
11046
|
+
});
|
|
10859
11047
|
broadcast({ sessionId, text: trimmed, triggeredBy: events, startedAt, finishedAt, error });
|
|
10860
11048
|
}
|
|
10861
11049
|
var listeners;
|
|
@@ -10866,6 +11054,7 @@ var init_daemon = __esm({
|
|
|
10866
11054
|
init_session_lock();
|
|
10867
11055
|
init_db();
|
|
10868
11056
|
init_inbox();
|
|
11057
|
+
init_webhook_events();
|
|
10869
11058
|
listeners = /* @__PURE__ */ new Map();
|
|
10870
11059
|
}
|
|
10871
11060
|
});
|
|
@@ -11043,8 +11232,8 @@ import { Hono as Hono9 } from "hono";
|
|
|
11043
11232
|
import { serve } from "@hono/node-server";
|
|
11044
11233
|
import { cors } from "hono/cors";
|
|
11045
11234
|
import { logger } from "hono/logger";
|
|
11046
|
-
import { existsSync as
|
|
11047
|
-
import { resolve as resolve11, dirname as
|
|
11235
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync10, writeFileSync as writeFileSync6 } from "fs";
|
|
11236
|
+
import { resolve as resolve11, dirname as dirname8, join as join16 } from "path";
|
|
11048
11237
|
import { spawn as spawn2 } from "child_process";
|
|
11049
11238
|
import { createServer as createNetServer } from "net";
|
|
11050
11239
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
@@ -11058,10 +11247,10 @@ init_checkpoints();
|
|
|
11058
11247
|
import { Hono } from "hono";
|
|
11059
11248
|
import { zValidator } from "@hono/zod-validator";
|
|
11060
11249
|
import { z as z17 } from "zod";
|
|
11061
|
-
import { existsSync as
|
|
11250
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync8, writeFileSync as writeFileSync4, readdirSync as readdirSync3, statSync as statSync2, unlinkSync as unlinkSync3 } from "fs";
|
|
11062
11251
|
import { readdir as readdir6 } from "fs/promises";
|
|
11063
|
-
import { join as
|
|
11064
|
-
import { nanoid as
|
|
11252
|
+
import { join as join13, basename as basename5, extname as extname8, relative as relative9 } from "path";
|
|
11253
|
+
import { nanoid as nanoid11 } from "nanoid";
|
|
11065
11254
|
|
|
11066
11255
|
// src/tasks/agent-status.ts
|
|
11067
11256
|
init_questions();
|
|
@@ -11702,12 +11891,12 @@ sessions2.get("/:id/diff/:filePath", async (c) => {
|
|
|
11702
11891
|
});
|
|
11703
11892
|
function getAttachmentsDir(sessionId) {
|
|
11704
11893
|
const appDataDir = getAppDataDirectory();
|
|
11705
|
-
return
|
|
11894
|
+
return join13(appDataDir, "attachments", sessionId);
|
|
11706
11895
|
}
|
|
11707
11896
|
function ensureAttachmentsDir(sessionId) {
|
|
11708
11897
|
const dir = getAttachmentsDir(sessionId);
|
|
11709
|
-
if (!
|
|
11710
|
-
|
|
11898
|
+
if (!existsSync19(dir)) {
|
|
11899
|
+
mkdirSync8(dir, { recursive: true });
|
|
11711
11900
|
}
|
|
11712
11901
|
return dir;
|
|
11713
11902
|
}
|
|
@@ -11718,12 +11907,12 @@ sessions2.get("/:id/attachments", async (c) => {
|
|
|
11718
11907
|
return c.json({ error: "Session not found" }, 404);
|
|
11719
11908
|
}
|
|
11720
11909
|
const dir = getAttachmentsDir(sessionId);
|
|
11721
|
-
if (!
|
|
11910
|
+
if (!existsSync19(dir)) {
|
|
11722
11911
|
return c.json({ sessionId, attachments: [], count: 0 });
|
|
11723
11912
|
}
|
|
11724
11913
|
const files = readdirSync3(dir);
|
|
11725
11914
|
const attachments = files.map((filename) => {
|
|
11726
|
-
const filePath =
|
|
11915
|
+
const filePath = join13(dir, filename);
|
|
11727
11916
|
const stats = statSync2(filePath);
|
|
11728
11917
|
return {
|
|
11729
11918
|
id: filename.split("_")[0],
|
|
@@ -11755,12 +11944,12 @@ sessions2.post("/:id/attachments", async (c) => {
|
|
|
11755
11944
|
return c.json({ error: "No file provided" }, 400);
|
|
11756
11945
|
}
|
|
11757
11946
|
const dir = ensureAttachmentsDir(sessionId);
|
|
11758
|
-
const id =
|
|
11947
|
+
const id = nanoid11(10);
|
|
11759
11948
|
const ext = extname8(file.name) || "";
|
|
11760
11949
|
const safeFilename = `${id}_${basename5(file.name).replace(/[^a-zA-Z0-9._-]/g, "_")}`;
|
|
11761
|
-
const filePath =
|
|
11950
|
+
const filePath = join13(dir, safeFilename);
|
|
11762
11951
|
const arrayBuffer = await file.arrayBuffer();
|
|
11763
|
-
|
|
11952
|
+
writeFileSync4(filePath, Buffer.from(arrayBuffer));
|
|
11764
11953
|
return c.json({
|
|
11765
11954
|
id,
|
|
11766
11955
|
filename: file.name,
|
|
@@ -11781,16 +11970,16 @@ sessions2.post("/:id/attachments", async (c) => {
|
|
|
11781
11970
|
return c.json({ error: "Missing filename or data" }, 400);
|
|
11782
11971
|
}
|
|
11783
11972
|
const dir = ensureAttachmentsDir(sessionId);
|
|
11784
|
-
const id =
|
|
11973
|
+
const id = nanoid11(10);
|
|
11785
11974
|
const ext = extname8(body.filename) || "";
|
|
11786
11975
|
const safeFilename = `${id}_${basename5(body.filename).replace(/[^a-zA-Z0-9._-]/g, "_")}`;
|
|
11787
|
-
const filePath =
|
|
11976
|
+
const filePath = join13(dir, safeFilename);
|
|
11788
11977
|
let base64Data = body.data;
|
|
11789
11978
|
if (base64Data.includes(",")) {
|
|
11790
11979
|
base64Data = base64Data.split(",")[1];
|
|
11791
11980
|
}
|
|
11792
11981
|
const buffer = Buffer.from(base64Data, "base64");
|
|
11793
|
-
|
|
11982
|
+
writeFileSync4(filePath, buffer);
|
|
11794
11983
|
return c.json({
|
|
11795
11984
|
id,
|
|
11796
11985
|
filename: body.filename,
|
|
@@ -11813,7 +12002,7 @@ sessions2.delete("/:id/attachments/:attachmentId", async (c) => {
|
|
|
11813
12002
|
return c.json({ error: "Session not found" }, 404);
|
|
11814
12003
|
}
|
|
11815
12004
|
const dir = getAttachmentsDir(sessionId);
|
|
11816
|
-
if (!
|
|
12005
|
+
if (!existsSync19(dir)) {
|
|
11817
12006
|
return c.json({ error: "Attachment not found" }, 404);
|
|
11818
12007
|
}
|
|
11819
12008
|
const files = readdirSync3(dir);
|
|
@@ -11821,7 +12010,7 @@ sessions2.delete("/:id/attachments/:attachmentId", async (c) => {
|
|
|
11821
12010
|
if (!file) {
|
|
11822
12011
|
return c.json({ error: "Attachment not found" }, 404);
|
|
11823
12012
|
}
|
|
11824
|
-
const filePath =
|
|
12013
|
+
const filePath = join13(dir, file);
|
|
11825
12014
|
unlinkSync3(filePath);
|
|
11826
12015
|
return c.json({ success: true, id: attachmentId });
|
|
11827
12016
|
});
|
|
@@ -11904,7 +12093,7 @@ async function listWorkspaceFiles(baseDir, currentDir, query, limit, results = [
|
|
|
11904
12093
|
const entries = await readdir6(currentDir, { withFileTypes: true });
|
|
11905
12094
|
for (const entry2 of entries) {
|
|
11906
12095
|
if (results.length >= limit * 2) break;
|
|
11907
|
-
const fullPath =
|
|
12096
|
+
const fullPath = join13(currentDir, entry2.name);
|
|
11908
12097
|
const relativePath = relative9(baseDir, fullPath);
|
|
11909
12098
|
if (entry2.isDirectory() && IGNORED_DIRECTORIES.has(entry2.name)) {
|
|
11910
12099
|
continue;
|
|
@@ -11952,7 +12141,7 @@ sessions2.get(
|
|
|
11952
12141
|
return c.json({ error: "Session not found" }, 404);
|
|
11953
12142
|
}
|
|
11954
12143
|
const workingDirectory = session.workingDirectory;
|
|
11955
|
-
if (!
|
|
12144
|
+
if (!existsSync19(workingDirectory)) {
|
|
11956
12145
|
return c.json({
|
|
11957
12146
|
sessionId,
|
|
11958
12147
|
workingDirectory,
|
|
@@ -12066,8 +12255,8 @@ init_config();
|
|
|
12066
12255
|
import { Hono as Hono2 } from "hono";
|
|
12067
12256
|
import { zValidator as zValidator2 } from "@hono/zod-validator";
|
|
12068
12257
|
import { z as z18 } from "zod";
|
|
12069
|
-
import { existsSync as
|
|
12070
|
-
import { join as
|
|
12258
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync9, writeFileSync as writeFileSync5 } from "fs";
|
|
12259
|
+
import { join as join14 } from "path";
|
|
12071
12260
|
|
|
12072
12261
|
// src/server/resumable-stream.ts
|
|
12073
12262
|
import { createResumableStreamContext } from "resumable-stream/generic";
|
|
@@ -12154,7 +12343,7 @@ var streamContext = createResumableStreamContext({
|
|
|
12154
12343
|
|
|
12155
12344
|
// src/server/routes/agents.ts
|
|
12156
12345
|
init_checkpoints();
|
|
12157
|
-
import { nanoid as
|
|
12346
|
+
import { nanoid as nanoid12 } from "nanoid";
|
|
12158
12347
|
init_stream_proxy();
|
|
12159
12348
|
init_recorder();
|
|
12160
12349
|
init_remote();
|
|
@@ -12274,12 +12463,12 @@ var rejectSchema = z18.object({
|
|
|
12274
12463
|
var streamAbortControllers = /* @__PURE__ */ new Map();
|
|
12275
12464
|
function getAttachmentsDirectory(sessionId) {
|
|
12276
12465
|
const appDataDir = getAppDataDirectory();
|
|
12277
|
-
return
|
|
12466
|
+
return join14(appDataDir, "attachments", sessionId);
|
|
12278
12467
|
}
|
|
12279
12468
|
async function saveAttachmentToDisk(sessionId, attachment, index) {
|
|
12280
12469
|
const attachmentsDir = getAttachmentsDirectory(sessionId);
|
|
12281
|
-
if (!
|
|
12282
|
-
|
|
12470
|
+
if (!existsSync20(attachmentsDir)) {
|
|
12471
|
+
mkdirSync9(attachmentsDir, { recursive: true });
|
|
12283
12472
|
}
|
|
12284
12473
|
let filename = attachment.filename;
|
|
12285
12474
|
if (!filename) {
|
|
@@ -12297,8 +12486,8 @@ async function saveAttachmentToDisk(sessionId, attachment, index) {
|
|
|
12297
12486
|
attachment.mediaType = resized.mediaType;
|
|
12298
12487
|
attachment.data = buffer.toString("base64");
|
|
12299
12488
|
}
|
|
12300
|
-
const filePath =
|
|
12301
|
-
|
|
12489
|
+
const filePath = join14(attachmentsDir, filename);
|
|
12490
|
+
writeFileSync5(filePath, buffer);
|
|
12302
12491
|
return filePath;
|
|
12303
12492
|
}
|
|
12304
12493
|
function stripDataUrlPrefix2(data) {
|
|
@@ -12734,7 +12923,7 @@ ${prompt}` });
|
|
|
12734
12923
|
});
|
|
12735
12924
|
} catch {
|
|
12736
12925
|
}
|
|
12737
|
-
const streamId = `stream_${id}_${
|
|
12926
|
+
const streamId = `stream_${id}_${nanoid12(10)}`;
|
|
12738
12927
|
console.log(`[STREAM] Creating stream ${streamId} for session ${id}`);
|
|
12739
12928
|
await activeStreamQueries.create(id, streamId);
|
|
12740
12929
|
const stream = await streamContext.resumableStream(
|
|
@@ -12939,7 +13128,7 @@ agents.post(
|
|
|
12939
13128
|
});
|
|
12940
13129
|
const session = agent.getSession();
|
|
12941
13130
|
const enrichedPrompt = enrichPromptWithDevtoolsContext(session.id, body.prompt);
|
|
12942
|
-
const streamId = `stream_${session.id}_${
|
|
13131
|
+
const streamId = `stream_${session.id}_${nanoid12(10)}`;
|
|
12943
13132
|
await createCheckpoint(session.id, session.workingDirectory, 0);
|
|
12944
13133
|
await activeStreamQueries.create(session.id, streamId);
|
|
12945
13134
|
const createQuickStreamProducer = () => {
|
|
@@ -13258,26 +13447,26 @@ init_config();
|
|
|
13258
13447
|
import { Hono as Hono3 } from "hono";
|
|
13259
13448
|
import { zValidator as zValidator3 } from "@hono/zod-validator";
|
|
13260
13449
|
import { z as z19 } from "zod";
|
|
13261
|
-
import { readFileSync as
|
|
13450
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
13262
13451
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
13263
|
-
import { dirname as
|
|
13452
|
+
import { dirname as dirname7, join as join15 } from "path";
|
|
13264
13453
|
var __filename = fileURLToPath3(import.meta.url);
|
|
13265
|
-
var __dirname =
|
|
13454
|
+
var __dirname = dirname7(__filename);
|
|
13266
13455
|
var possiblePaths = [
|
|
13267
|
-
|
|
13456
|
+
join15(__dirname, "../package.json"),
|
|
13268
13457
|
// From dist/server -> dist/../package.json
|
|
13269
|
-
|
|
13458
|
+
join15(__dirname, "../../package.json"),
|
|
13270
13459
|
// From dist/server (if nested differently)
|
|
13271
|
-
|
|
13460
|
+
join15(__dirname, "../../../package.json"),
|
|
13272
13461
|
// From src/server/routes (development)
|
|
13273
|
-
|
|
13462
|
+
join15(process.cwd(), "package.json")
|
|
13274
13463
|
// From current working directory
|
|
13275
13464
|
];
|
|
13276
13465
|
var currentVersion = "0.0.0";
|
|
13277
13466
|
var packageName = "sparkecoder";
|
|
13278
13467
|
for (const packageJsonPath of possiblePaths) {
|
|
13279
13468
|
try {
|
|
13280
|
-
const packageJson = JSON.parse(
|
|
13469
|
+
const packageJson = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
|
|
13281
13470
|
if (packageJson.name === "sparkecoder") {
|
|
13282
13471
|
currentVersion = packageJson.version || "0.0.0";
|
|
13283
13472
|
packageName = packageJson.name || "sparkecoder";
|
|
@@ -13727,7 +13916,7 @@ init_config();
|
|
|
13727
13916
|
import { Hono as Hono5 } from "hono";
|
|
13728
13917
|
import { zValidator as zValidator5 } from "@hono/zod-validator";
|
|
13729
13918
|
import { z as z21 } from "zod";
|
|
13730
|
-
import { nanoid as
|
|
13919
|
+
import { nanoid as nanoid13 } from "nanoid";
|
|
13731
13920
|
init_questions();
|
|
13732
13921
|
var tasks = new Hono5();
|
|
13733
13922
|
var taskAbortControllers = /* @__PURE__ */ new Map();
|
|
@@ -13808,7 +13997,7 @@ tasks.post(
|
|
|
13808
13997
|
const taskId = agent.sessionId;
|
|
13809
13998
|
const abortController = new AbortController();
|
|
13810
13999
|
taskAbortControllers.set(taskId, abortController);
|
|
13811
|
-
const streamId = `stream_${taskId}_${
|
|
14000
|
+
const streamId = `stream_${taskId}_${nanoid13(10)}`;
|
|
13812
14001
|
await activeStreamQueries.create(taskId, streamId);
|
|
13813
14002
|
const taskStreamProducer = () => {
|
|
13814
14003
|
const { readable, writable } = new TransformStream();
|
|
@@ -14034,6 +14223,7 @@ function verifySlackSignature(opts) {
|
|
|
14034
14223
|
// src/server/routes/slack.ts
|
|
14035
14224
|
init_client3();
|
|
14036
14225
|
init_slack();
|
|
14226
|
+
init_webhook_events();
|
|
14037
14227
|
init_inbox();
|
|
14038
14228
|
var recentlyHandled = /* @__PURE__ */ new Map();
|
|
14039
14229
|
var MAX_RECENT = 1e3;
|
|
@@ -14074,7 +14264,17 @@ slack.post("/events", async (c) => {
|
|
|
14074
14264
|
}
|
|
14075
14265
|
if (payload?.type === "event_callback" && payload?.event) {
|
|
14076
14266
|
const ev = payload.event;
|
|
14267
|
+
const auditId = recordEvent({
|
|
14268
|
+
source: "slack",
|
|
14269
|
+
status: "received",
|
|
14270
|
+
subtype: ev.type === "message" ? `message.${ev.channel_type ?? "channels"}` : ev.type,
|
|
14271
|
+
channel: ev.channel,
|
|
14272
|
+
user: ev.user,
|
|
14273
|
+
textSnippet: typeof ev.text === "string" ? ev.text : void 0,
|
|
14274
|
+
meta: { ts: ev.ts, thread_ts: ev.thread_ts, team: ev.team, event_subtype: ev.subtype }
|
|
14275
|
+
});
|
|
14077
14276
|
if (alreadyHandled(ev.channel, ev.ts)) {
|
|
14277
|
+
updateEvent(auditId, { status: "dropped", dropReason: "duplicate_delivery" });
|
|
14078
14278
|
return c.json({ ok: true });
|
|
14079
14279
|
}
|
|
14080
14280
|
const { event: inbound, dropReason } = slackEventToInboundResult(ev);
|
|
@@ -14084,6 +14284,7 @@ slack.post("/events", async (c) => {
|
|
|
14084
14284
|
const ours = isThreadOwned(ev.channel, ev.thread_ts) || await threadBelongsToUs(ev.channel, ev.thread_ts);
|
|
14085
14285
|
if (!ours) {
|
|
14086
14286
|
console.log(`[slack] dropping thread reply in unknown thread: channel=${ev.channel} thread=${ev.thread_ts}`);
|
|
14287
|
+
updateEvent(auditId, { status: "dropped", dropReason: "thread_not_owned" });
|
|
14087
14288
|
return c.json({ ok: true });
|
|
14088
14289
|
}
|
|
14089
14290
|
}
|
|
@@ -14096,8 +14297,12 @@ slack.post("/events", async (c) => {
|
|
|
14096
14297
|
const orchestratorId = await findOrCreateOrchestratorId();
|
|
14097
14298
|
if (orchestratorId) {
|
|
14098
14299
|
pushToInbox(orchestratorId, inbound);
|
|
14300
|
+
updateEvent(auditId, { status: "routed", sessionId: orchestratorId });
|
|
14301
|
+
} else {
|
|
14302
|
+
updateEvent(auditId, { status: "error", error: "no orchestrator session available" });
|
|
14099
14303
|
}
|
|
14100
14304
|
} else if (dropReason) {
|
|
14305
|
+
updateEvent(auditId, { status: "dropped", dropReason });
|
|
14101
14306
|
const userFacingDrops = ["user_not_allowed", "channel_not_allowed", "dm_blocked"];
|
|
14102
14307
|
if (userFacingDrops.includes(dropReason)) {
|
|
14103
14308
|
console.log(`[slack] dropped event from user=${payload.event.user} channel=${payload.event.channel}: ${dropReason}`);
|
|
@@ -14160,13 +14365,30 @@ async function sendDeniedReply(event) {
|
|
|
14160
14365
|
init_webhooks_store();
|
|
14161
14366
|
init_webhook();
|
|
14162
14367
|
init_inbox();
|
|
14368
|
+
init_webhook_events();
|
|
14163
14369
|
import { Hono as Hono7 } from "hono";
|
|
14164
14370
|
var inbox = new Hono7();
|
|
14165
14371
|
inbox.post("/:token", async (c) => {
|
|
14166
14372
|
const token = c.req.param("token");
|
|
14167
|
-
if (!token || token.length < 16)
|
|
14373
|
+
if (!token || token.length < 16) {
|
|
14374
|
+
recordEvent({
|
|
14375
|
+
source: "inbox",
|
|
14376
|
+
status: "dropped",
|
|
14377
|
+
dropReason: "invalid_token_format",
|
|
14378
|
+
meta: { tokenLen: token?.length ?? 0 }
|
|
14379
|
+
});
|
|
14380
|
+
return c.json({ error: "invalid token" }, 401);
|
|
14381
|
+
}
|
|
14168
14382
|
const lookup = await findByToken(token);
|
|
14169
|
-
if (!lookup)
|
|
14383
|
+
if (!lookup) {
|
|
14384
|
+
recordEvent({
|
|
14385
|
+
source: "inbox",
|
|
14386
|
+
status: "dropped",
|
|
14387
|
+
dropReason: "unknown_token",
|
|
14388
|
+
meta: { tokenPrefix: token.slice(0, 8) + "\u2026" }
|
|
14389
|
+
});
|
|
14390
|
+
return c.json({ error: "unknown token" }, 404);
|
|
14391
|
+
}
|
|
14170
14392
|
let body;
|
|
14171
14393
|
const contentType = c.req.header("content-type") || "";
|
|
14172
14394
|
try {
|
|
@@ -14188,6 +14410,14 @@ inbox.post("/:token", async (c) => {
|
|
|
14188
14410
|
pushToInbox(lookup.orchestratorSessionId, event);
|
|
14189
14411
|
void recordHit(lookup.orchestratorSessionId, lookup.webhook.id).catch(() => {
|
|
14190
14412
|
});
|
|
14413
|
+
recordEvent({
|
|
14414
|
+
source: "inbox",
|
|
14415
|
+
status: "routed",
|
|
14416
|
+
channel: lookup.webhook.name,
|
|
14417
|
+
textSnippet: typeof body === "string" ? body : JSON.stringify(body).slice(0, 200),
|
|
14418
|
+
sessionId: lookup.orchestratorSessionId,
|
|
14419
|
+
meta: { wake: lookup.webhook.wake, webhookId: lookup.webhook.id }
|
|
14420
|
+
});
|
|
14191
14421
|
return c.json({ ok: true, queued: true, wake: lookup.webhook.wake });
|
|
14192
14422
|
});
|
|
14193
14423
|
|
|
@@ -14199,6 +14429,7 @@ init_webhooks_store();
|
|
|
14199
14429
|
init_messenger();
|
|
14200
14430
|
init_store();
|
|
14201
14431
|
init_pool();
|
|
14432
|
+
init_webhook_events();
|
|
14202
14433
|
import { Hono as Hono8 } from "hono";
|
|
14203
14434
|
import { zValidator as zValidator6 } from "@hono/zod-validator";
|
|
14204
14435
|
import { z as z22 } from "zod";
|
|
@@ -14257,6 +14488,24 @@ function webhookPrefix() {
|
|
|
14257
14488
|
const token = cfg?.webhooks?.token;
|
|
14258
14489
|
return token ? `/w/${token}` : "/api";
|
|
14259
14490
|
}
|
|
14491
|
+
integrations.get("/events", async (c) => {
|
|
14492
|
+
const q = c.req.query();
|
|
14493
|
+
const filter = {
|
|
14494
|
+
source: q.source,
|
|
14495
|
+
status: q.status,
|
|
14496
|
+
q: q.q,
|
|
14497
|
+
since: q.since,
|
|
14498
|
+
before: q.before,
|
|
14499
|
+
limit: q.limit ? Math.min(500, Math.max(1, parseInt(q.limit, 10))) : 50,
|
|
14500
|
+
offset: q.offset ? Math.max(0, parseInt(q.offset, 10)) : 0
|
|
14501
|
+
};
|
|
14502
|
+
const { events, total } = listEvents(filter);
|
|
14503
|
+
return c.json({ events, total, limit: filter.limit, offset: filter.offset });
|
|
14504
|
+
});
|
|
14505
|
+
integrations.delete("/events", async (c) => {
|
|
14506
|
+
clearAllEvents();
|
|
14507
|
+
return c.json({ ok: true });
|
|
14508
|
+
});
|
|
14260
14509
|
integrations.get("/", async (c) => {
|
|
14261
14510
|
const cfg = getConfig();
|
|
14262
14511
|
return c.json({
|
|
@@ -14619,13 +14868,13 @@ var DEFAULT_WEB_PORT = 6969;
|
|
|
14619
14868
|
var WEB_PORT_SEQUENCE = [6969, 6970, 6971, 6972, 6973, 6974, 6975, 6976, 6977, 6978];
|
|
14620
14869
|
function getWebDirectory() {
|
|
14621
14870
|
try {
|
|
14622
|
-
const currentDir =
|
|
14871
|
+
const currentDir = dirname8(fileURLToPath4(import.meta.url));
|
|
14623
14872
|
const webDir = resolve11(currentDir, "..", "web");
|
|
14624
|
-
if (
|
|
14873
|
+
if (existsSync21(webDir) && existsSync21(join16(webDir, "package.json"))) {
|
|
14625
14874
|
return webDir;
|
|
14626
14875
|
}
|
|
14627
14876
|
const altWebDir = resolve11(currentDir, "..", "..", "web");
|
|
14628
|
-
if (
|
|
14877
|
+
if (existsSync21(altWebDir) && existsSync21(join16(altWebDir, "package.json"))) {
|
|
14629
14878
|
return altWebDir;
|
|
14630
14879
|
}
|
|
14631
14880
|
return null;
|
|
@@ -14683,23 +14932,23 @@ async function findWebPort(preferredPort) {
|
|
|
14683
14932
|
return { port: preferredPort, alreadyRunning: false };
|
|
14684
14933
|
}
|
|
14685
14934
|
function hasProductionBuild(webDir) {
|
|
14686
|
-
const buildIdPath =
|
|
14687
|
-
return
|
|
14935
|
+
const buildIdPath = join16(webDir, ".next", "BUILD_ID");
|
|
14936
|
+
return existsSync21(buildIdPath);
|
|
14688
14937
|
}
|
|
14689
14938
|
function hasSourceFiles(webDir) {
|
|
14690
|
-
const appDir =
|
|
14691
|
-
const pagesDir =
|
|
14692
|
-
const rootAppDir =
|
|
14693
|
-
const rootPagesDir =
|
|
14694
|
-
return
|
|
14939
|
+
const appDir = join16(webDir, "src", "app");
|
|
14940
|
+
const pagesDir = join16(webDir, "src", "pages");
|
|
14941
|
+
const rootAppDir = join16(webDir, "app");
|
|
14942
|
+
const rootPagesDir = join16(webDir, "pages");
|
|
14943
|
+
return existsSync21(appDir) || existsSync21(pagesDir) || existsSync21(rootAppDir) || existsSync21(rootPagesDir);
|
|
14695
14944
|
}
|
|
14696
14945
|
function getStandaloneServerPath(webDir) {
|
|
14697
14946
|
const possiblePaths2 = [
|
|
14698
|
-
|
|
14699
|
-
|
|
14947
|
+
join16(webDir, ".next", "standalone", "server.js"),
|
|
14948
|
+
join16(webDir, ".next", "standalone", "web", "server.js")
|
|
14700
14949
|
];
|
|
14701
14950
|
for (const serverPath of possiblePaths2) {
|
|
14702
|
-
if (
|
|
14951
|
+
if (existsSync21(serverPath)) {
|
|
14703
14952
|
return serverPath;
|
|
14704
14953
|
}
|
|
14705
14954
|
}
|
|
@@ -14739,15 +14988,15 @@ async function startWebUI(apiPort, webPort = DEFAULT_WEB_PORT, quiet = false, pu
|
|
|
14739
14988
|
if (!quiet) console.log(` \u2713 Web UI already running at http://localhost:${actualPort}`);
|
|
14740
14989
|
return { process: null, port: actualPort };
|
|
14741
14990
|
}
|
|
14742
|
-
const usePnpm =
|
|
14743
|
-
const useNpm = !usePnpm &&
|
|
14991
|
+
const usePnpm = existsSync21(join16(webDir, "pnpm-lock.yaml"));
|
|
14992
|
+
const useNpm = !usePnpm && existsSync21(join16(webDir, "package-lock.json"));
|
|
14744
14993
|
const pkgManager = usePnpm ? "pnpm" : useNpm ? "npm" : "npx";
|
|
14745
14994
|
const { NODE_OPTIONS, TSX_TSCONFIG_PATH, ...cleanEnv } = process.env;
|
|
14746
14995
|
const apiUrl = publicUrl || `http://127.0.0.1:${apiPort}`;
|
|
14747
14996
|
const runtimeConfig = { apiBaseUrl: apiUrl };
|
|
14748
|
-
const runtimeConfigPath =
|
|
14997
|
+
const runtimeConfigPath = join16(webDir, "runtime-config.json");
|
|
14749
14998
|
try {
|
|
14750
|
-
|
|
14999
|
+
writeFileSync6(runtimeConfigPath, JSON.stringify(runtimeConfig, null, 2));
|
|
14751
15000
|
if (!quiet) console.log(` \u{1F4DD} Runtime config written to ${runtimeConfigPath}`);
|
|
14752
15001
|
} catch (err) {
|
|
14753
15002
|
if (!quiet) console.warn(` \u26A0 Could not write runtime config: ${err}`);
|
|
@@ -14767,7 +15016,7 @@ async function startWebUI(apiPort, webPort = DEFAULT_WEB_PORT, quiet = false, pu
|
|
|
14767
15016
|
if (standaloneServerPath) {
|
|
14768
15017
|
command = "node";
|
|
14769
15018
|
args = ["server.js"];
|
|
14770
|
-
cwd =
|
|
15019
|
+
cwd = dirname8(standaloneServerPath);
|
|
14771
15020
|
webEnv.PORT = String(actualPort);
|
|
14772
15021
|
webEnv.HOSTNAME = "0.0.0.0";
|
|
14773
15022
|
if (!quiet) console.log(" \u{1F4E6} Starting Web UI from standalone build...");
|
|
@@ -14960,8 +15209,8 @@ async function startServer(options = {}) {
|
|
|
14960
15209
|
if (options.workingDirectory) {
|
|
14961
15210
|
config.resolvedWorkingDirectory = options.workingDirectory;
|
|
14962
15211
|
}
|
|
14963
|
-
if (!
|
|
14964
|
-
|
|
15212
|
+
if (!existsSync21(config.resolvedWorkingDirectory)) {
|
|
15213
|
+
mkdirSync10(config.resolvedWorkingDirectory, { recursive: true });
|
|
14965
15214
|
if (!options.quiet) console.log(`\u{1F4C1} Created agent workspace: ${config.resolvedWorkingDirectory}`);
|
|
14966
15215
|
}
|
|
14967
15216
|
if (!config.resolvedRemoteServer.url) {
|