- routes-live: check .running marker before keeping SSE open;
if thread is not running, emit existing records and close
- thread-detail: only show Live badge when connected AND not completed
小橘 <xiaoju@shazhou.work>
When .running marker exists but no __end__ in CAS chain,
check if the worker process is actually alive. Dead PID
means the worker crashed without cleanup → status 'failed'.
Fixes#170
小橘 <xiaoju@shazhou.work>
- resolveThreadListStatus() checks CAS chain for __end__ node
- Stale .running markers no longer cause false 'running' status
- Distinguish 'failed' (returnCode != 0) from 'completed'
- Worker signal handlers (SIGINT/SIGTERM) clean up .running files
- listRunningThreads filters out terminated threads with stale markers
Fixes#170
小橘 <xiaoju@shazhou.work>
- serve generates random UUID on startup
- registration sends agentToken to gateway, stored in KV
- gateway injects X-Agent-Token header when proxying to agent
- serve rejects /api/* requests without valid token
- healthz remains unauthenticated
- tunnel URL is now protected — direct access returns 401
小橘 <xiaoju@shazhou.work>
Both REST and SSE endpoints now return workflow-result with standard
fields (role, content, timestamp) instead of non-standard (summary).
Fixes 'Invalid Date' and empty content in dashboard.
小橘 <xiaoju@shazhou.work>
Gateway proxies /api/neko/healthz → /api/healthz on the agent,
but healthz was only on /healthz. Dashboard status bar showed
permanent Offline.
小橘 🍊(NEKO Team)
Phase C of #164:
- Dashboard fetches agents from gateway /endpoints
- Sidebar shows agent selector with online/offline status
- All API calls routed through gateway /api/:agent/*
- Hash routing: #agent/threads/id format
- SSE live streaming via gateway proxy
- VITE_GATEWAY_URL env var for gateway configuration
- Deployed to CF Pages: workflow-dashboard-54r.pages.dev
- Custom domain: workflow.shazhou.work (pending SSL)
Ref: #164, closes#167
小橘 🍊(NEKO Team)
Phase B of #164:
- serve --name <agent> starts cloudflared quick tunnel automatically
- Registers with CF Worker gateway, heartbeat every 60s
- Graceful unregister on SIGINT/SIGTERM
- --no-tunnel flag for local dev
- Default name from hostname
Ref: #164, closes#166
小橘 🍊(NEKO Team)
- Align REST API contracts for Dashboard (threads list, detail, SSE)
- Add content resolution from CAS in thread show + API responses
- Rename dataWatcher → threadsJsonWatcher in SSE routes
- Update docs (CLAUDE.md, architecture.md, skill.ts) to reflect CAS storage
- Zero .data.jsonl code paths in production code
- All 166 tests pass, bun run check clean
Refs #155, closes#160
小橘 <xiaoju@shazhou.work>
- Update root tsconfig.json references: replace packages/workflow with 6 new packages
- Update cli-workflow tsconfig references to new packages
- Add tsconfig references to workflow-util, workflow-runtime, workflow-execute
- Fix workflow-agent-llm, workflow-agent-cursor, workflow-agent-hermes, workflow-util-agent
tsconfig references (../workflow -> ../workflow-runtime)
- Remove stale @uncaged/workflow deps from agent package.json files
- Change template packages to import buildDescriptor from @uncaged/workflow-register
- Normalize package.json exports field across all new packages
- Delete old packages/workflow/ directory
Phase 7: Engine + extract + workflow-as-agent merged into execute package.
All CLI imports migrated from @uncaged/workflow to specific packages.
105 CLI tests pass, 0 failures.
Changes:
- New @uncaged/workflow-execute package (engine/, extract/, workflow-as-agent)
- CLI src/ and __tests__/ rewritten to import from split packages
- bundle-validator updated to allow @uncaged/workflow-cas imports
- ensure-uncaged-workflow-symlink creates symlinks for all new packages
Ref: #143, closes#150
Merges bundle/ + registry/ + config/ modules. The config↔registry
circular dependency is resolved: ProviderConfig and WorkflowConfig
now come from @uncaged/workflow-protocol.
Ref: #143, closes#149
Phase 4: CAS module extracted with Merkle types, hash functions,
and fs-backed store. Imports CasStore type from protocol.
Phase 5: Reactor (ReAct loop) extracted as independent package.
Only depends on protocol — no cas or engine dependency.
Ref: #143, closes#147, closes#148
All type definitions now originate from @uncaged/workflow-protocol.
Runtime re-exports them for backward compatibility. Local AdvanceOutcome
duplicate in create-workflow.ts removed (now imported from protocol).
Ref: #143, closes#146
Extract all cross-package type definitions and constructor functions
into a dedicated protocol layer. This is the foundation for the
seven-package split (RFC #143).
Contains:
- Result<T,E>, ok(), err()
- START, END constants
- CasStore, WorkflowFn, RoleOutput, WorkflowCompletion
- WorkflowDescriptor, WorkflowRoleDescriptor
- ProviderConfig, WorkflowConfig, ResolvedModel (fixes config↔registry cycle)
- RoleDefinition, Moderator, WorkflowDefinition
- AgentFn, ExtractFn, and all thread context types
Ref: #143, closes#144
- Rewrite supervisor to use createThreadReactor + createLlmFn
- No direct fetch/HTTP calls in supervisor
- All 266 tests passing
Refs #139, relates #141
Collapse bundle/cas/extract/util stubs into types.ts; move createWorkflow and Result helpers to src root.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Hash-based URL routing (#threads, #threads/{id}, #workflows)
for bookmarkable/shareable thread links
- Health check polls every 10s with reconnecting state
- useHashRoute hook for clean route management
Closes#128
Use Bun.file().slice() to read only new bytes from the last known
offset instead of re-reading the entire JSONL file on every fs watch.
- readNewBytes() helper with byte-offset tracking
- Handles file truncation (resets offset)
- Early return when no new data
Closes#130
- Global error handler (app.onError → 500 JSON)
- JSON parse validation on POST routes (400)
- CORS restricted to localhost origins
- 1MB body size limit on POST (413)
- CAS store created once per route group, not per-request
- 6 new tests covering all changes
Closes#120
Add useSSE hook that connects to /api/threads/:id/live via EventSource.
Thread detail page now shows records in real-time with auto-scroll.
- useSSE hook: EventSource connection, record accumulation, auto-reconnect
with exponential backoff, cleanup on unmount
- Thread detail: Live badge, SSE-first with fetch fallback, smooth scroll
- Records clear on reconnect (server replays full file)
Closes#131, testing verified per #133
Refs: #118