feat(web): add auto-spawn session from URL params#437
feat(web): add auto-spawn session from URL params#437woodgear wants to merge 1 commit intotiann:mainfrom
Conversation
Support spawning a session via URL parameters (?spawn=true&machine=xxx&dir=/path&boot=message). The spawn params are captured at module load time before URL cleanup, then the hook calls spawnSession API and navigates to the new session automatically. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
5027400 to
a574aff
Compare
|
这样我们就能直接把某个文件夹下的agent直接通过url分享出去了。 |
There was a problem hiding this comment.
Findings
- [Major]
bootcan be dropped on newly spawned sessions because the hook sends it immediately afterspawnSession()returns, while the messages route still requires the session to be active. Evidence:web/src/hooks/useAutoSpawn.ts:27,hub/src/web/routes/messages.ts:46,hub/src/sync/sessionCache.ts:183. - [Major] Auto-spawn bypasses the existing missing-directory confirmation and can create folders from a URL alone. Evidence:
web/src/hooks/useAutoSpawn.ts:25,web/src/components/NewSession/index.tsx:235,web/src/components/SpawnSession.tsx:78,cli/src/runner/run.ts:197.
Summary
Review mode: initial
The new URL auto-spawn path introduces two behavior regressions: the optional boot prompt is racy against session activation, and the deep-link flow skips the normal directory existence/confirmation guard before spawning.
Testing
- Not run (automation):
bun typecheckcould not run in this runner becausebunis unavailable (/bin/bash: bun: command not found). - Coverage gap:
AGENTS.mdsays there are currently no web tests, and this PR adds no automated coverage for auto-spawn, boot delivery, or URL cleanup ordering.
HAPI Bot
| if (result.type === 'success') { | ||
| if (SPAWN_PARAMS.boot) { | ||
| try { | ||
| await api.sendMessage(result.sessionId, SPAWN_PARAMS.boot) |
There was a problem hiding this comment.
[Major] boot can be lost here. spawnSession() only returns the new session id; POST /api/sessions/:id/messages still rejects sends until requireActive passes, and sessions are only marked active later from alive updates. In the failure case the link still navigates, but the user’s first prompt disappears into a logged error.
Suggested fix:
const waitForActive = async (sessionId: string) => {
for (let i = 0; i < 30; i += 1) {
const { session } = await api.getSession(sessionId)
if (session.active) return true
await new Promise((resolve) => setTimeout(resolve, 500))
}
return false
}
if (SPAWN_PARAMS.boot && await waitForActive(result.sessionId)) {
await api.sendMessage(result.sessionId, SPAWN_PARAMS.boot)
}|
|
||
| attemptedRef.current = true | ||
|
|
||
| api.spawnSession(SPAWN_PARAMS.machine, SPAWN_PARAMS.dir).then(async (result) => { |
There was a problem hiding this comment.
[Major] This direct spawnSession() call skips the same missing-directory guard used by the manual spawn flows. Those paths first call checkPathsExists() and stop until the user confirms creation, but the runner defaults approvedNewDirectoryCreation = true and will create the directory automatically. A typo or stale deep link can therefore create folders on disk just by opening the URL.
Suggested fix:
const exists = await api.checkMachinePathsExists(SPAWN_PARAMS.machine, [SPAWN_PARAMS.dir])
if (exists.exists[SPAWN_PARAMS.dir] === false) {
console.error('Auto-spawn blocked: missing directory requires explicit confirmation')
return
}
const result = await api.spawnSession(SPAWN_PARAMS.machine, SPAWN_PARAMS.dir)|
@tiann 咋样。这个特性如何觉得可以的话我就在修修review的意见。 |
我觉得挺不错的 |
hqhq1025
left a comment
There was a problem hiding this comment.
The spawn-from-URL idea is useful, but the `boot` parameter introduces a significant security concern:
HAPI users are typically permanently authenticated in their browser. A malicious link like `?spawn=true&machine=xxx&dir=/tmp&boot=` clicked by a logged-in user would silently spawn a session and send an arbitrary prompt to the AI agent — no confirmation, no origin check. This is essentially a CSRF vector, and since HAPI agents have file system access, the impact is real.
On top of that, the bot already flagged that `boot` is racy — `sendMessage` fires before the session is actually active, so it silently fails in practice.
Suggestion: ship v1 without `boot`. The spawn + navigate flow alone is already valuable — the user lands on the session page and can type their own first message. `boot` can be added later behind a confirmation dialog or a signed token mechanism.
One smaller thing: the module-level `SPAWN_PARAMS` capture works but is fragile with HMR. A `useState` initializer would be more idiomatic:
```ts
const [params] = useState(() => {
const q = new URLSearchParams(window.location.search)
return { spawn: q.get('spawn') === 'true', ... }
})
```
Summary
useAutoSpawnhook that reads spawn params (spawn,machine,dir,boot) from URL query stringapi.spawnSessionand navigates to the new sessionbootparam is provided, sends it as the first message to the spawned sessionTest plan
?spawn=true&machine=<name>&dir=<path>and verify a new session is spawned and navigated to&boot=<message>and verify the boot message is sent to the session🤖 Generated with Claude Code