sparkecoder 0.1.114 → 0.1.115
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/cli.js +156 -1
- 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/{schema-ecQSnCMz.d.ts → schema-CYSKJZ3m.d.ts} +3 -3
- package/dist/{search-DOzC4ojH.d.ts → search-CVVfuBPZ.d.ts} +4 -4
- package/dist/skills/default/computer-use.md +20 -13
- package/dist/skills/default/recording.md +66 -42
- package/dist/tools/index.d.ts +3 -3
- package/package.json +1 -1
- package/src/skills/default/computer-use.md +20 -13
- package/src/skills/default/recording.md +66 -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/_global-error.html +2 -2
- package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.html +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p/agents/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p/agents.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.html +1 -1
- package/web/.next/standalone/web/.next/server/app/index.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.html +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
- package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
- /package/web/.next/standalone/web/.next/static/{N09EiHl0JwEgsGMdCtwpB → pSGgtxBjN5_o0YHZgQzXm}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{N09EiHl0JwEgsGMdCtwpB → pSGgtxBjN5_o0YHZgQzXm}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/{N09EiHl0JwEgsGMdCtwpB → pSGgtxBjN5_o0YHZgQzXm}/_ssgManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{N09EiHl0JwEgsGMdCtwpB → pSGgtxBjN5_o0YHZgQzXm}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{N09EiHl0JwEgsGMdCtwpB → pSGgtxBjN5_o0YHZgQzXm}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/static/{N09EiHl0JwEgsGMdCtwpB → pSGgtxBjN5_o0YHZgQzXm}/_ssgManifest.js +0 -0
- /package/web/.next/static/{N09EiHl0JwEgsGMdCtwpB → pSGgtxBjN5_o0YHZgQzXm}/_buildManifest.js +0 -0
- /package/web/.next/static/{N09EiHl0JwEgsGMdCtwpB → pSGgtxBjN5_o0YHZgQzXm}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{N09EiHl0JwEgsGMdCtwpB → pSGgtxBjN5_o0YHZgQzXm}/_ssgManifest.js +0 -0
|
@@ -22,6 +22,42 @@ Skip recording when:
|
|
|
22
22
|
- The task is purely textual (reading/writing files, code analysis). The chat transcript already has everything.
|
|
23
23
|
- Recording would capture sensitive content (passwords on screen, private DMs, customer data). Ask first.
|
|
24
24
|
|
|
25
|
+
## Screen recording — use `sparkecoder record` (preferred)
|
|
26
|
+
|
|
27
|
+
The built-in helper handles start/stop reliably so the recording covers the WHOLE task, not a fixed time window. It tracks PIDs in state, works on macOS + Linux with the same interface, and returns JSON you can parse.
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Start: returns {id, path, pid}
|
|
31
|
+
REC=$(sparkecoder record start --name "calculator-demo")
|
|
32
|
+
REC_ID=$(echo "$REC" | jq -r .id)
|
|
33
|
+
REC_PATH=$(echo "$REC" | jq -r .path)
|
|
34
|
+
|
|
35
|
+
# ... do work ...
|
|
36
|
+
|
|
37
|
+
# Stop: returns {id, path, durationSec, sizeMb, ok}
|
|
38
|
+
sparkecoder record stop "$REC_ID"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Other operations:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
sparkecoder record list # list active recordings (auto-prunes dead pids)
|
|
45
|
+
sparkecoder record stop-all # stop everything (cleanup)
|
|
46
|
+
sparkecoder record start --dir /custom/path --name my-task
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Storage: defaults to `~/recordings/`. Files are named `rec-<id>[-<name>].<mov|mp4>`.
|
|
50
|
+
|
|
51
|
+
### Why not `screencapture -V N` or raw `ffmpeg` backgrounded?
|
|
52
|
+
|
|
53
|
+
You can — but you have to:
|
|
54
|
+
- guess the right `-V` timeout (too short = partial, too long = wasted disk),
|
|
55
|
+
- track the PID yourself for `kill -INT`,
|
|
56
|
+
- pick the right tool per OS,
|
|
57
|
+
- and clean up zombie processes if you crash mid-task.
|
|
58
|
+
|
|
59
|
+
`sparkecoder record` does all of that. Reach for raw `screencapture` / `ffmpeg` only if you need specific flags the helper doesn't expose (custom display, rectangle crop, audio mux).
|
|
60
|
+
|
|
25
61
|
## Terminal recording — asciinema
|
|
26
62
|
|
|
27
63
|
`asciinema` records the **content of a terminal session** as a tiny `.cast` text file. It's a fraction of the size of video, plays in any browser via [asciinema-player](https://github.com/asciinema/asciinema-player), and the output is also greppable.
|
|
@@ -85,49 +121,33 @@ curl -fsS -X POST "${SPARKECODER_REMOTE_URL}/storage/upload" \
|
|
|
85
121
|
-F "file=@${RECORDING}" | jq .url
|
|
86
122
|
```
|
|
87
123
|
|
|
88
|
-
##
|
|
124
|
+
## Advanced: raw `screencapture` / `ffmpeg` (use only when the helper isn't enough)
|
|
89
125
|
|
|
90
|
-
|
|
126
|
+
Prefer `sparkecoder record` (above) for almost everything. Reach for raw tools only when you need flags the helper doesn't expose: rectangle crop, specific display, audio mux, custom frame rate.
|
|
91
127
|
|
|
92
128
|
### Requirements
|
|
93
129
|
|
|
94
|
-
- **Screen Recording permission** for the agent's parent process
|
|
95
|
-
-
|
|
130
|
+
- macOS: **Screen Recording permission** for the agent's parent process. `sparkecoder check-permissions` verifies; `sparkecoder request-permissions` opens the right System Settings pane.
|
|
131
|
+
- Linux: `ffmpeg` installed (`sudo apt-get install -y ffmpeg`), and a running X server with the right `DISPLAY` env var.
|
|
96
132
|
|
|
97
|
-
###
|
|
133
|
+
### macOS `screencapture` flags
|
|
98
134
|
|
|
99
135
|
```bash
|
|
100
|
-
#
|
|
101
|
-
screencapture -v ~/recordings/
|
|
102
|
-
REC_PID=$!
|
|
136
|
+
# Crop to a rectangle (x,y,w,h):
|
|
137
|
+
screencapture -v -R 100,100,800,600 -C ~/recordings/clip.mov
|
|
103
138
|
|
|
104
|
-
#
|
|
139
|
+
# Pick a specific display (run `system_profiler SPDisplaysDataType` to list ids):
|
|
140
|
+
screencapture -v -G <displayID> -C ~/recordings/clip.mov
|
|
105
141
|
|
|
106
|
-
#
|
|
107
|
-
|
|
108
|
-
|
|
142
|
+
# Auto-stop after N seconds (avoid this for task-bounded recordings; use the
|
|
143
|
+
# helper instead so the recording covers the whole task):
|
|
144
|
+
screencapture -v -V 30 -C ~/recordings/clip.mov
|
|
109
145
|
```
|
|
110
146
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
- `-V <seconds>` — stop automatically after this many seconds (no need for kill).
|
|
114
|
-
- `-R x,y,w,h` — record just a rectangle.
|
|
115
|
-
- `-C` — also capture mouse cursor (off by default).
|
|
116
|
-
- `-G <displayID>` — pick a specific display (run `system_profiler SPDisplaysDataType` to list).
|
|
117
|
-
- `-T <seconds>` — pre-roll countdown before starting.
|
|
118
|
-
|
|
119
|
-
Example: 30-second auto-stop, full screen, with cursor:
|
|
147
|
+
### Linux `ffmpeg` x11grab
|
|
120
148
|
|
|
121
149
|
```bash
|
|
122
|
-
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
## Screen recording — Linux (`ffmpeg`)
|
|
126
|
-
|
|
127
|
-
```bash
|
|
128
|
-
sudo apt-get install -y ffmpeg
|
|
129
|
-
|
|
130
|
-
# Record the X display. Adjust :0.0 / resolution for your setup.
|
|
150
|
+
# Capture the X display (size matches the screen):
|
|
131
151
|
ffmpeg -y -f x11grab -framerate 25 -video_size 1920x1080 -i :0.0 \
|
|
132
152
|
-c:v libx264 -preset veryfast -pix_fmt yuv420p \
|
|
133
153
|
~/recordings/screen-$(date +%s).mp4
|
|
@@ -141,32 +161,36 @@ On a headless server with no X, screen recording isn't meaningful — record the
|
|
|
141
161
|
|
|
142
162
|
| You want to … | Use |
|
|
143
163
|
|---|---|
|
|
164
|
+
| Show what a computer-use task did on the desktop | `sparkecoder record start` → work → `record stop <id>` |
|
|
144
165
|
| Capture a CLI demo, share a link | `asciinema rec → upload` |
|
|
145
|
-
| Show what a computer-use task did on the desktop | `screencapture -v -V <seconds>` (macOS) |
|
|
146
|
-
| Debug a flaky GUI test on Linux CI | `ffmpeg -f x11grab` around the test run |
|
|
147
166
|
| Capture a single command's output verbatim | `asciinema rec --command "cmd" out.cast` |
|
|
148
|
-
|
|
|
167
|
+
| Debug a flaky GUI test (any OS) | `sparkecoder record start` around the test run |
|
|
168
|
+
| Both terminal AND screen at once | `sparkecoder record start` + `asciinema rec` in parallel |
|
|
149
169
|
|
|
150
170
|
## Best practices
|
|
151
171
|
|
|
152
172
|
1. **Always announce.** Before starting a recording, post a short message to the user: "Starting screen recording for the Calculator demo." So they can intervene if it'd capture something sensitive.
|
|
153
|
-
2. **
|
|
154
|
-
3. **
|
|
155
|
-
4. **
|
|
173
|
+
2. **Use `sparkecoder record` for screen video.** It removes every footgun the raw tools have (no fixed timeout that cuts the task off mid-way, no PID juggling, no per-OS branching). Reach for raw `screencapture` / `ffmpeg` only when you need flags the helper doesn't expose (region crop, custom display, audio).
|
|
174
|
+
3. **Bracket the WHOLE task.** `record start` *before* your first work command; `record stop <id>` *after* the very last one. Don't bracket each step individually — you'll lose context between clips.
|
|
175
|
+
4. **Stop on exit, success OR failure.** Always run `record stop <id>` at the end of your task, even on errors. Otherwise the recorder keeps writing until `record stop-all` (or a reboot) catches it. The duration / size returned by `stop` is also useful in your final summary.
|
|
156
176
|
5. **Don't record secrets.** Refuse to record if the screen contains visible passwords, 1Password vaults, customer PII, etc. Ask the user to close those windows first.
|
|
157
|
-
6. **
|
|
158
|
-
7. **
|
|
177
|
+
6. **Clean up after yourself.** If a recording is no longer needed, `rm` it — videos are big.
|
|
178
|
+
7. **Always mention the file in your final message.** "Recording saved to `<path>`" or, better, upload via `/storage/upload` and post the `/f/<id>` URL so Slack/etc. unfurls it inline.
|
|
159
179
|
|
|
160
180
|
## Returning the recording in your final task summary
|
|
161
181
|
|
|
162
|
-
For a **task worker** that captured a recording, include the
|
|
182
|
+
For a **task worker** that captured a recording, include the structured fields below in your `result` so the orchestrator can route it back to the user:
|
|
163
183
|
|
|
164
184
|
```ts
|
|
165
185
|
{
|
|
166
186
|
"summary": "Opened Calculator, typed 2+2, hit Return. Got 4.",
|
|
167
|
-
"
|
|
168
|
-
|
|
187
|
+
"recording": {
|
|
188
|
+
"path": "/Users/me/recordings/rec-abc123-calculator-demo.mov",
|
|
189
|
+
"durationSec": 42,
|
|
190
|
+
"sizeMb": 18.4,
|
|
191
|
+
"description": "Full screen recording of the Calculator interaction"
|
|
192
|
+
}
|
|
169
193
|
}
|
|
170
194
|
```
|
|
171
195
|
|
|
172
|
-
The orchestrator can then
|
|
196
|
+
The orchestrator can then upload that path via `/storage/upload` and post the `/f/<id>` URL into Slack (or whatever channel the original request came in on) — Slack unfurls it inline as a video preview.
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as ai from 'ai';
|
|
2
2
|
import { ToolSet } from 'ai';
|
|
3
|
-
import { B as BashToolProgress, W as WriteFileProgress, S as SearchToolProgress } from '../search-
|
|
4
|
-
export { b as BashToolOptions, d as SearchToolOptions, e as WriteFileToolOptions, c as createBashTool, f as createSearchTool, a as createWriteFileTool } from '../search-
|
|
3
|
+
import { B as BashToolProgress, W as WriteFileProgress, S as SearchToolProgress } from '../search-CVVfuBPZ.js';
|
|
4
|
+
export { b as BashToolOptions, d as SearchToolOptions, e as WriteFileToolOptions, c as createBashTool, f as createSearchTool, a as createWriteFileTool } from '../search-CVVfuBPZ.js';
|
|
5
5
|
|
|
6
6
|
interface TaskCompletionSignal {
|
|
7
7
|
status: 'completed' | 'failed';
|
|
@@ -110,7 +110,7 @@ interface TodoToolOptions {
|
|
|
110
110
|
workingDirectory: string;
|
|
111
111
|
}
|
|
112
112
|
declare function createTodoTool(options: TodoToolOptions): ai.Tool<{
|
|
113
|
-
action: "
|
|
113
|
+
action: "clear" | "add" | "list" | "mark" | "save_plan" | "list_plans" | "get_plan" | "delete_plan";
|
|
114
114
|
status?: "completed" | "pending" | "in_progress" | "cancelled" | undefined;
|
|
115
115
|
items?: {
|
|
116
116
|
content: string;
|
package/package.json
CHANGED
|
@@ -154,23 +154,30 @@ Coordinates are in the **logical points** of the primary display — same coordi
|
|
|
154
154
|
|
|
155
155
|
## Record what you're doing (default ON)
|
|
156
156
|
|
|
157
|
-
Computer-use sessions are *visual* — the user can't see the screen you're driving, only your text summary. **Record almost every computer-use task** so the user can replay it.
|
|
157
|
+
Computer-use sessions are *visual* — the user can't see the screen you're driving, only your text summary. **Record almost every computer-use task** so the user can replay it. Use the built-in `sparkecoder record` helper which manages start/stop properly so the recording covers the **entire task**, not just a fixed-time window:
|
|
158
158
|
|
|
159
159
|
```bash
|
|
160
|
-
# At the
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
160
|
+
# 1. At the START of the task, BEFORE your first `computer` action:
|
|
161
|
+
REC=$(sparkecoder record start --name "calculator-demo")
|
|
162
|
+
# REC is JSON: {"id":"rec-abc123","path":"~/recordings/rec-abc123-calculator-demo.mov","pid":12345}
|
|
163
|
+
REC_ID=$(echo "$REC" | jq -r .id)
|
|
164
|
+
REC_PATH=$(echo "$REC" | jq -r .path)
|
|
165
|
+
echo "Recording started: $REC_PATH (id=$REC_ID)"
|
|
166
|
+
|
|
167
|
+
# 2. ... do all your computer-use actions (open apps, click, type, etc.) ...
|
|
168
|
+
|
|
169
|
+
# 3. At the END (success OR failure), stop the recording:
|
|
170
|
+
sparkecoder record stop "$REC_ID"
|
|
171
|
+
# → JSON: {"id":"...","path":"...","durationSec":42,"sizeMb":18.4,"ok":true}
|
|
172
172
|
```
|
|
173
173
|
|
|
174
|
+
Why use `sparkecoder record` instead of `screencapture -V 60` directly:
|
|
175
|
+
|
|
176
|
+
- `-V <seconds>` is a fixed timeout — if your task takes longer than the guess, the recording ends mid-task and you get a partial. The helper has no timeout; it records until you explicitly stop it.
|
|
177
|
+
- The helper tracks PIDs in state so `sparkecoder record stop-all` can clean up if something crashes.
|
|
178
|
+
- Works on both macOS (screencapture) and Linux (ffmpeg x11grab) with the same command.
|
|
179
|
+
- Returns the file path as JSON, so you can include it in your final result without guessing.
|
|
180
|
+
|
|
174
181
|
Default behavior:
|
|
175
182
|
|
|
176
183
|
- **Always record** short / visually interesting tasks (open an app, click around, drag/drop, fill a form, demos, "show me X working").
|
|
@@ -22,6 +22,42 @@ Skip recording when:
|
|
|
22
22
|
- The task is purely textual (reading/writing files, code analysis). The chat transcript already has everything.
|
|
23
23
|
- Recording would capture sensitive content (passwords on screen, private DMs, customer data). Ask first.
|
|
24
24
|
|
|
25
|
+
## Screen recording — use `sparkecoder record` (preferred)
|
|
26
|
+
|
|
27
|
+
The built-in helper handles start/stop reliably so the recording covers the WHOLE task, not a fixed time window. It tracks PIDs in state, works on macOS + Linux with the same interface, and returns JSON you can parse.
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Start: returns {id, path, pid}
|
|
31
|
+
REC=$(sparkecoder record start --name "calculator-demo")
|
|
32
|
+
REC_ID=$(echo "$REC" | jq -r .id)
|
|
33
|
+
REC_PATH=$(echo "$REC" | jq -r .path)
|
|
34
|
+
|
|
35
|
+
# ... do work ...
|
|
36
|
+
|
|
37
|
+
# Stop: returns {id, path, durationSec, sizeMb, ok}
|
|
38
|
+
sparkecoder record stop "$REC_ID"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Other operations:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
sparkecoder record list # list active recordings (auto-prunes dead pids)
|
|
45
|
+
sparkecoder record stop-all # stop everything (cleanup)
|
|
46
|
+
sparkecoder record start --dir /custom/path --name my-task
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Storage: defaults to `~/recordings/`. Files are named `rec-<id>[-<name>].<mov|mp4>`.
|
|
50
|
+
|
|
51
|
+
### Why not `screencapture -V N` or raw `ffmpeg` backgrounded?
|
|
52
|
+
|
|
53
|
+
You can — but you have to:
|
|
54
|
+
- guess the right `-V` timeout (too short = partial, too long = wasted disk),
|
|
55
|
+
- track the PID yourself for `kill -INT`,
|
|
56
|
+
- pick the right tool per OS,
|
|
57
|
+
- and clean up zombie processes if you crash mid-task.
|
|
58
|
+
|
|
59
|
+
`sparkecoder record` does all of that. Reach for raw `screencapture` / `ffmpeg` only if you need specific flags the helper doesn't expose (custom display, rectangle crop, audio mux).
|
|
60
|
+
|
|
25
61
|
## Terminal recording — asciinema
|
|
26
62
|
|
|
27
63
|
`asciinema` records the **content of a terminal session** as a tiny `.cast` text file. It's a fraction of the size of video, plays in any browser via [asciinema-player](https://github.com/asciinema/asciinema-player), and the output is also greppable.
|
|
@@ -85,49 +121,33 @@ curl -fsS -X POST "${SPARKECODER_REMOTE_URL}/storage/upload" \
|
|
|
85
121
|
-F "file=@${RECORDING}" | jq .url
|
|
86
122
|
```
|
|
87
123
|
|
|
88
|
-
##
|
|
124
|
+
## Advanced: raw `screencapture` / `ffmpeg` (use only when the helper isn't enough)
|
|
89
125
|
|
|
90
|
-
|
|
126
|
+
Prefer `sparkecoder record` (above) for almost everything. Reach for raw tools only when you need flags the helper doesn't expose: rectangle crop, specific display, audio mux, custom frame rate.
|
|
91
127
|
|
|
92
128
|
### Requirements
|
|
93
129
|
|
|
94
|
-
- **Screen Recording permission** for the agent's parent process
|
|
95
|
-
-
|
|
130
|
+
- macOS: **Screen Recording permission** for the agent's parent process. `sparkecoder check-permissions` verifies; `sparkecoder request-permissions` opens the right System Settings pane.
|
|
131
|
+
- Linux: `ffmpeg` installed (`sudo apt-get install -y ffmpeg`), and a running X server with the right `DISPLAY` env var.
|
|
96
132
|
|
|
97
|
-
###
|
|
133
|
+
### macOS `screencapture` flags
|
|
98
134
|
|
|
99
135
|
```bash
|
|
100
|
-
#
|
|
101
|
-
screencapture -v ~/recordings/
|
|
102
|
-
REC_PID=$!
|
|
136
|
+
# Crop to a rectangle (x,y,w,h):
|
|
137
|
+
screencapture -v -R 100,100,800,600 -C ~/recordings/clip.mov
|
|
103
138
|
|
|
104
|
-
#
|
|
139
|
+
# Pick a specific display (run `system_profiler SPDisplaysDataType` to list ids):
|
|
140
|
+
screencapture -v -G <displayID> -C ~/recordings/clip.mov
|
|
105
141
|
|
|
106
|
-
#
|
|
107
|
-
|
|
108
|
-
|
|
142
|
+
# Auto-stop after N seconds (avoid this for task-bounded recordings; use the
|
|
143
|
+
# helper instead so the recording covers the whole task):
|
|
144
|
+
screencapture -v -V 30 -C ~/recordings/clip.mov
|
|
109
145
|
```
|
|
110
146
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
- `-V <seconds>` — stop automatically after this many seconds (no need for kill).
|
|
114
|
-
- `-R x,y,w,h` — record just a rectangle.
|
|
115
|
-
- `-C` — also capture mouse cursor (off by default).
|
|
116
|
-
- `-G <displayID>` — pick a specific display (run `system_profiler SPDisplaysDataType` to list).
|
|
117
|
-
- `-T <seconds>` — pre-roll countdown before starting.
|
|
118
|
-
|
|
119
|
-
Example: 30-second auto-stop, full screen, with cursor:
|
|
147
|
+
### Linux `ffmpeg` x11grab
|
|
120
148
|
|
|
121
149
|
```bash
|
|
122
|
-
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
## Screen recording — Linux (`ffmpeg`)
|
|
126
|
-
|
|
127
|
-
```bash
|
|
128
|
-
sudo apt-get install -y ffmpeg
|
|
129
|
-
|
|
130
|
-
# Record the X display. Adjust :0.0 / resolution for your setup.
|
|
150
|
+
# Capture the X display (size matches the screen):
|
|
131
151
|
ffmpeg -y -f x11grab -framerate 25 -video_size 1920x1080 -i :0.0 \
|
|
132
152
|
-c:v libx264 -preset veryfast -pix_fmt yuv420p \
|
|
133
153
|
~/recordings/screen-$(date +%s).mp4
|
|
@@ -141,32 +161,36 @@ On a headless server with no X, screen recording isn't meaningful — record the
|
|
|
141
161
|
|
|
142
162
|
| You want to … | Use |
|
|
143
163
|
|---|---|
|
|
164
|
+
| Show what a computer-use task did on the desktop | `sparkecoder record start` → work → `record stop <id>` |
|
|
144
165
|
| Capture a CLI demo, share a link | `asciinema rec → upload` |
|
|
145
|
-
| Show what a computer-use task did on the desktop | `screencapture -v -V <seconds>` (macOS) |
|
|
146
|
-
| Debug a flaky GUI test on Linux CI | `ffmpeg -f x11grab` around the test run |
|
|
147
166
|
| Capture a single command's output verbatim | `asciinema rec --command "cmd" out.cast` |
|
|
148
|
-
|
|
|
167
|
+
| Debug a flaky GUI test (any OS) | `sparkecoder record start` around the test run |
|
|
168
|
+
| Both terminal AND screen at once | `sparkecoder record start` + `asciinema rec` in parallel |
|
|
149
169
|
|
|
150
170
|
## Best practices
|
|
151
171
|
|
|
152
172
|
1. **Always announce.** Before starting a recording, post a short message to the user: "Starting screen recording for the Calculator demo." So they can intervene if it'd capture something sensitive.
|
|
153
|
-
2. **
|
|
154
|
-
3. **
|
|
155
|
-
4. **
|
|
173
|
+
2. **Use `sparkecoder record` for screen video.** It removes every footgun the raw tools have (no fixed timeout that cuts the task off mid-way, no PID juggling, no per-OS branching). Reach for raw `screencapture` / `ffmpeg` only when you need flags the helper doesn't expose (region crop, custom display, audio).
|
|
174
|
+
3. **Bracket the WHOLE task.** `record start` *before* your first work command; `record stop <id>` *after* the very last one. Don't bracket each step individually — you'll lose context between clips.
|
|
175
|
+
4. **Stop on exit, success OR failure.** Always run `record stop <id>` at the end of your task, even on errors. Otherwise the recorder keeps writing until `record stop-all` (or a reboot) catches it. The duration / size returned by `stop` is also useful in your final summary.
|
|
156
176
|
5. **Don't record secrets.** Refuse to record if the screen contains visible passwords, 1Password vaults, customer PII, etc. Ask the user to close those windows first.
|
|
157
|
-
6. **
|
|
158
|
-
7. **
|
|
177
|
+
6. **Clean up after yourself.** If a recording is no longer needed, `rm` it — videos are big.
|
|
178
|
+
7. **Always mention the file in your final message.** "Recording saved to `<path>`" or, better, upload via `/storage/upload` and post the `/f/<id>` URL so Slack/etc. unfurls it inline.
|
|
159
179
|
|
|
160
180
|
## Returning the recording in your final task summary
|
|
161
181
|
|
|
162
|
-
For a **task worker** that captured a recording, include the
|
|
182
|
+
For a **task worker** that captured a recording, include the structured fields below in your `result` so the orchestrator can route it back to the user:
|
|
163
183
|
|
|
164
184
|
```ts
|
|
165
185
|
{
|
|
166
186
|
"summary": "Opened Calculator, typed 2+2, hit Return. Got 4.",
|
|
167
|
-
"
|
|
168
|
-
|
|
187
|
+
"recording": {
|
|
188
|
+
"path": "/Users/me/recordings/rec-abc123-calculator-demo.mov",
|
|
189
|
+
"durationSec": 42,
|
|
190
|
+
"sizeMb": 18.4,
|
|
191
|
+
"description": "Full screen recording of the Calculator interaction"
|
|
192
|
+
}
|
|
169
193
|
}
|
|
170
194
|
```
|
|
171
195
|
|
|
172
|
-
The orchestrator can then
|
|
196
|
+
The orchestrator can then upload that path via `/storage/upload` and post the `/f/<id>` URL into Slack (or whatever channel the original request came in on) — Slack unfurls it inline as a video preview.
|
package/web/.next/BUILD_ID
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
pSGgtxBjN5_o0YHZgQzXm
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
pSGgtxBjN5_o0YHZgQzXm
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
"static/chunks/a6dad97d9634a72d.js"
|
|
8
8
|
],
|
|
9
9
|
"lowPriorityFiles": [
|
|
10
|
-
"static/
|
|
11
|
-
"static/
|
|
10
|
+
"static/pSGgtxBjN5_o0YHZgQzXm/_ssgManifest.js",
|
|
11
|
+
"static/pSGgtxBjN5_o0YHZgQzXm/_buildManifest.js"
|
|
12
12
|
],
|
|
13
13
|
"rootMainFiles": [
|
|
14
14
|
"static/chunks/651e187cc15d66de.js",
|
|
@@ -367,8 +367,8 @@
|
|
|
367
367
|
"dynamicRoutes": {},
|
|
368
368
|
"notFoundRoutes": [],
|
|
369
369
|
"preview": {
|
|
370
|
-
"previewModeId": "
|
|
371
|
-
"previewModeSigningKey": "
|
|
372
|
-
"previewModeEncryptionKey": "
|
|
370
|
+
"previewModeId": "4d4df0b08ac51f255c1fba959eff551a",
|
|
371
|
+
"previewModeSigningKey": "61a87433a4783d0b199c61d12ecf05a6503595b50fb2863e5e86ea9db1544061",
|
|
372
|
+
"previewModeEncryptionKey": "b4d0ec3479d75253ad48871374201d5a399ead8edb8cc23a194a5b2375eddfa9"
|
|
373
373
|
}
|
|
374
374
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
<!DOCTYPE html><!--
|
|
2
|
-
@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top">500</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">Internal Server Error.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/651e187cc15d66de.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[488287,[\"/_next/static/chunks/9b5512fb633ef95d.js\",\"/_next/static/chunks/0f1cf11540868e42.js\"],\"default\"]\n3:I[174895,[\"/_next/static/chunks/9b5512fb633ef95d.js\",\"/_next/static/chunks/0f1cf11540868e42.js\"],\"default\"]\n4:I[151858,[\"/_next/static/chunks/9b5512fb633ef95d.js\",\"/_next/static/chunks/0f1cf11540868e42.js\"],\"OutletBoundary\"]\n5:\"$Sreact.suspense\"\n7:I[151858,[\"/_next/static/chunks/9b5512fb633ef95d.js\",\"/_next/static/chunks/0f1cf11540868e42.js\"],\"ViewportBoundary\"]\n9:I[151858,[\"/_next/static/chunks/9b5512fb633ef95d.js\",\"/_next/static/chunks/0f1cf11540868e42.js\"],\"MetadataBoundary\"]\nb:I[552576,[\"/_next/static/chunks/9b5512fb633ef95d.js\",\"/_next/static/chunks/0f1cf11540868e42.js\"],\"default\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"
|
|
1
|
+
<!DOCTYPE html><!--pSGgtxBjN5_o0YHZgQzXm--><html id="__next_error__"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/651e187cc15d66de.js"/><script src="/_next/static/chunks/735a2408c315b2f0.js" async=""></script><script src="/_next/static/chunks/186e0c1b3ff43c9c.js" async=""></script><script src="/_next/static/chunks/a14243261b055626.js" async=""></script><script src="/_next/static/chunks/862ced58ce21a270.js" async=""></script><script src="/_next/static/chunks/turbopack-2c0905c7bbebae3f.js" async=""></script><script src="/_next/static/chunks/9b5512fb633ef95d.js" async=""></script><script src="/_next/static/chunks/0f1cf11540868e42.js" async=""></script><meta name="next-size-adjust" content=""/><title>500: Internal Server Error.</title><link rel="icon" href="/favicon.ico?favicon.e3cbed1b.ico" sizes="256x256" type="image/x-icon"/><script src="/_next/static/chunks/a6dad97d9634a72d.js" noModule=""></script></head><body><div hidden=""><!--$--><!--/$--></div><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div style="line-height:48px"><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}
|
|
2
|
+
@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top">500</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">Internal Server Error.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/651e187cc15d66de.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[488287,[\"/_next/static/chunks/9b5512fb633ef95d.js\",\"/_next/static/chunks/0f1cf11540868e42.js\"],\"default\"]\n3:I[174895,[\"/_next/static/chunks/9b5512fb633ef95d.js\",\"/_next/static/chunks/0f1cf11540868e42.js\"],\"default\"]\n4:I[151858,[\"/_next/static/chunks/9b5512fb633ef95d.js\",\"/_next/static/chunks/0f1cf11540868e42.js\"],\"OutletBoundary\"]\n5:\"$Sreact.suspense\"\n7:I[151858,[\"/_next/static/chunks/9b5512fb633ef95d.js\",\"/_next/static/chunks/0f1cf11540868e42.js\"],\"ViewportBoundary\"]\n9:I[151858,[\"/_next/static/chunks/9b5512fb633ef95d.js\",\"/_next/static/chunks/0f1cf11540868e42.js\"],\"MetadataBoundary\"]\nb:I[552576,[\"/_next/static/chunks/9b5512fb633ef95d.js\",\"/_next/static/chunks/0f1cf11540868e42.js\"],\"default\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"pSGgtxBjN5_o0YHZgQzXm\",\"c\":[\"\",\"_global-error\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"__PAGE__\",{}]}],[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"html\",null,{\"id\":\"__next_error__\",\"children\":[[\"$\",\"head\",null,{\"children\":[\"$\",\"title\",null,{\"children\":\"500: Internal Server Error.\"}]}],[\"$\",\"body\",null,{\"children\":[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"style\":{\"lineHeight\":\"48px\"},\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}\\n@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"paddingRight\":23,\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\"},\"children\":\"500\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"28px\"},\"children\":\"Internal Server Error.\"}]}]]}]}]}]]}],null,[\"$\",\"$L4\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@6\"}]}]]}],{},null,false,false]},null,false,false],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$L7\",null,{\"children\":\"$L8\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$L9\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.Metadata\",\"children\":\"$La\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$b\",\"$undefined\"],\"S\":true}\n"])</script><script>self.__next_f.push([1,"8:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"c:I[349310,[\"/_next/static/chunks/9b5512fb633ef95d.js\",\"/_next/static/chunks/0f1cf11540868e42.js\"],\"IconMark\"]\n6:null\na:[[\"$\",\"link\",\"0\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.e3cbed1b.ico\",\"sizes\":\"256x256\",\"type\":\"image/x-icon\"}],[\"$\",\"$Lc\",\"1\",{}]]\n"])</script></body></html>
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
7:I[151858,["/_next/static/chunks/9b5512fb633ef95d.js","/_next/static/chunks/0f1cf11540868e42.js"],"ViewportBoundary"]
|
|
7
7
|
9:I[151858,["/_next/static/chunks/9b5512fb633ef95d.js","/_next/static/chunks/0f1cf11540868e42.js"],"MetadataBoundary"]
|
|
8
8
|
b:I[552576,["/_next/static/chunks/9b5512fb633ef95d.js","/_next/static/chunks/0f1cf11540868e42.js"],"default"]
|
|
9
|
-
0:{"P":null,"b":"
|
|
9
|
+
0:{"P":null,"b":"pSGgtxBjN5_o0YHZgQzXm","c":["","_global-error"],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]}],[["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[["$","html",null,{"id":"__next_error__","children":[["$","head",null,{"children":["$","title",null,{"children":"500: Internal Server Error."}]}],["$","body",null,{"children":["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"style":{"lineHeight":"48px"},"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}\n@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","paddingRight":23,"fontSize":24,"fontWeight":500,"verticalAlign":"top"},"children":"500"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"28px"},"children":"Internal Server Error."}]}]]}]}]}]]}],null,["$","$L4",null,{"children":["$","$5",null,{"name":"Next.MetadataOutlet","children":"$@6"}]}]]}],{},null,false,false]},null,false,false],["$","$1","h",{"children":[null,["$","$L7",null,{"children":"$L8"}],["$","div",null,{"hidden":true,"children":["$","$L9",null,{"children":["$","$5",null,{"name":"Next.Metadata","children":"$La"}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],false]],"m":"$undefined","G":["$b","$undefined"],"S":true}
|
|
10
10
|
8:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
|
|
11
11
|
c:I[349310,["/_next/static/chunks/9b5512fb633ef95d.js","/_next/static/chunks/0f1cf11540868e42.js"],"IconMark"]
|
|
12
12
|
6:null
|
package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
1:"$Sreact.fragment"
|
|
2
2
|
2:I[151858,["/_next/static/chunks/9b5512fb633ef95d.js","/_next/static/chunks/0f1cf11540868e42.js"],"OutletBoundary"]
|
|
3
3
|
3:"$Sreact.suspense"
|
|
4
|
-
0:{"buildId":"
|
|
4
|
+
0:{"buildId":"pSGgtxBjN5_o0YHZgQzXm","rsc":["$","$1","c",{"children":[["$","html",null,{"id":"__next_error__","children":[["$","head",null,{"children":["$","title",null,{"children":"500: Internal Server Error."}]}],["$","body",null,{"children":["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"style":{"lineHeight":"48px"},"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}\n@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","paddingRight":23,"fontSize":24,"fontWeight":500,"verticalAlign":"top"},"children":"500"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"28px"},"children":"Internal Server Error."}]}]]}]}]}]]}],null,["$","$L2",null,{"children":["$","$3",null,{"name":"Next.MetadataOutlet","children":"$@4"}]}]]}],"loading":null,"isPartial":false}
|
|
5
5
|
4:null
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
7:I[151858,["/_next/static/chunks/9b5512fb633ef95d.js","/_next/static/chunks/0f1cf11540868e42.js"],"ViewportBoundary"]
|
|
7
7
|
9:I[151858,["/_next/static/chunks/9b5512fb633ef95d.js","/_next/static/chunks/0f1cf11540868e42.js"],"MetadataBoundary"]
|
|
8
8
|
b:I[552576,["/_next/static/chunks/9b5512fb633ef95d.js","/_next/static/chunks/0f1cf11540868e42.js"],"default"]
|
|
9
|
-
0:{"P":null,"b":"
|
|
9
|
+
0:{"P":null,"b":"pSGgtxBjN5_o0YHZgQzXm","c":["","_global-error"],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]}],[["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[["$","html",null,{"id":"__next_error__","children":[["$","head",null,{"children":["$","title",null,{"children":"500: Internal Server Error."}]}],["$","body",null,{"children":["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"style":{"lineHeight":"48px"},"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}\n@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","paddingRight":23,"fontSize":24,"fontWeight":500,"verticalAlign":"top"},"children":"500"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"28px"},"children":"Internal Server Error."}]}]]}]}]}]]}],null,["$","$L4",null,{"children":["$","$5",null,{"name":"Next.MetadataOutlet","children":"$@6"}]}]]}],{},null,false,false]},null,false,false],["$","$1","h",{"children":[null,["$","$L7",null,{"children":"$L8"}],["$","div",null,{"hidden":true,"children":["$","$L9",null,{"children":["$","$5",null,{"name":"Next.Metadata","children":"$La"}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],false]],"m":"$undefined","G":["$b","$undefined"],"S":true}
|
|
10
10
|
8:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
|
|
11
11
|
c:I[349310,["/_next/static/chunks/9b5512fb633ef95d.js","/_next/static/chunks/0f1cf11540868e42.js"],"IconMark"]
|
|
12
12
|
6:null
|
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
3:I[151858,["/_next/static/chunks/9b5512fb633ef95d.js","/_next/static/chunks/0f1cf11540868e42.js"],"MetadataBoundary"]
|
|
4
4
|
4:"$Sreact.suspense"
|
|
5
5
|
5:I[349310,["/_next/static/chunks/9b5512fb633ef95d.js","/_next/static/chunks/0f1cf11540868e42.js"],"IconMark"]
|
|
6
|
-
0:{"buildId":"
|
|
6
|
+
0:{"buildId":"pSGgtxBjN5_o0YHZgQzXm","rsc":["$","$1","h",{"children":[null,["$","$L2",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]}],["$","div",null,{"hidden":true,"children":["$","$L3",null,{"children":["$","$4",null,{"name":"Next.Metadata","children":[["$","link","0",{"rel":"icon","href":"/favicon.ico?favicon.e3cbed1b.ico","sizes":"256x256","type":"image/x-icon"}],["$","$L5","1",{}]]}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],"loading":null,"isPartial":false}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
1:"$Sreact.fragment"
|
|
2
2
|
2:I[488287,["/_next/static/chunks/9b5512fb633ef95d.js","/_next/static/chunks/0f1cf11540868e42.js"],"default"]
|
|
3
3
|
3:I[174895,["/_next/static/chunks/9b5512fb633ef95d.js","/_next/static/chunks/0f1cf11540868e42.js"],"default"]
|
|
4
|
-
0:{"buildId":"
|
|
4
|
+
0:{"buildId":"pSGgtxBjN5_o0YHZgQzXm","rsc":["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","template":["$","$L3",null,{}]}]]}],"loading":null,"isPartial":false}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
0:{"buildId":"
|
|
1
|
+
0:{"buildId":"pSGgtxBjN5_o0YHZgQzXm","tree":{"name":"","paramType":null,"paramKey":"","hasRuntimePrefetch":false,"slots":{"children":{"name":"__PAGE__","paramType":null,"paramKey":"__PAGE__","hasRuntimePrefetch":false,"slots":null,"isRootLayout":false}},"isRootLayout":false},"staleTime":300}
|