@schoolai/shipyard 3.3.0 → 3.3.1-nightly.20260427.0
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/README.md +99 -19
- package/dist/{chunk-OHIIVBEZ.js → chunk-5J6ABOPF.js} +6 -6
- package/dist/{chunk-UWBX6UGC.js → chunk-6GPDEZNR.js} +5 -5
- package/dist/chunk-6GPDEZNR.js.map +1 -0
- package/dist/chunk-G5KJXNNK.js +340 -0
- package/dist/chunk-G5KJXNNK.js.map +1 -0
- package/dist/chunk-GQPRMFVC.js +40 -0
- package/dist/chunk-GQPRMFVC.js.map +1 -0
- package/dist/chunk-KYLY4DJF.js +61 -0
- package/dist/chunk-KYLY4DJF.js.map +1 -0
- package/dist/git-repo-I2OABFB7.js +32 -0
- package/dist/index.js +8 -3
- package/dist/index.js.map +1 -1
- package/dist/{login-N43V35KE.js → login-D3OUX3KD.js} +4 -4
- package/dist/login-D3OUX3KD.js.map +1 -0
- package/dist/{serve-QLYUK5XN.js → serve-MBUBBBRA.js} +73144 -66606
- package/dist/{serve-QLYUK5XN.js.map → serve-MBUBBBRA.js.map} +1 -1
- package/dist/shell-JINTQUIR.js +25 -0
- package/dist/shell-JINTQUIR.js.map +1 -0
- package/dist/{start-NVYMND3X.js → start-ZOGQS3QS.js} +5 -5
- package/package.json +6 -2
- package/dist/chunk-UWBX6UGC.js.map +0 -1
- /package/dist/{chunk-OHIIVBEZ.js.map → chunk-5J6ABOPF.js.map} +0 -0
- /package/dist/{login-N43V35KE.js.map → git-repo-I2OABFB7.js.map} +0 -0
- /package/dist/{start-NVYMND3X.js.map → start-ZOGQS3QS.js.map} +0 -0
package/README.md
CHANGED
|
@@ -1,29 +1,104 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
<h1>Shipyard</h1>
|
|
3
|
+
<p><strong>Ship together with AI — locally, visibly, confidently.</strong></p>
|
|
4
|
+
<p>The collaboration workspace where engineering teams build alongside AI coding agents.</p>
|
|
2
5
|
|
|
3
|
-
|
|
6
|
+
<p>
|
|
7
|
+
<a href="https://www.npmjs.com/package/@schoolai/shipyard"><img src="https://img.shields.io/npm/v/@schoolai/shipyard" alt="npm"></a>
|
|
8
|
+
<a href="https://img.shields.io/badge/license-FSL--1.1-blue"><img src="https://img.shields.io/badge/license-FSL--1.1-blue" alt="License"></a>
|
|
9
|
+
</p>
|
|
10
|
+
</div>
|
|
4
11
|
|
|
5
|
-
|
|
12
|
+
<p align="center">
|
|
13
|
+
<img src="https://pub-2a5bcc605c9f466681c9b10bf4d173f4.r2.dev/images/hero.png" alt="Shipyard — task sidebar, agent workspace, and composer" width="100%">
|
|
14
|
+
</p>
|
|
6
15
|
|
|
7
|
-
|
|
16
|
+
---
|
|
8
17
|
|
|
9
|
-
|
|
10
|
-
npm install -g @schoolai/shipyard
|
|
11
|
-
```
|
|
18
|
+
## Quick Start
|
|
12
19
|
|
|
13
|
-
|
|
20
|
+
**Prerequisites:** [Node.js](https://nodejs.org/) >= 22
|
|
14
21
|
|
|
15
22
|
```bash
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
## Quick Start
|
|
23
|
+
# Install the daemon
|
|
24
|
+
npm install -g @schoolai/shipyard
|
|
20
25
|
|
|
21
|
-
```bash
|
|
22
26
|
# Start Shipyard (authenticates on first run, opens browser automatically)
|
|
23
27
|
shipyard start
|
|
24
28
|
```
|
|
25
29
|
|
|
26
|
-
The
|
|
30
|
+
That's it. The daemon handles authentication via GitHub device flow, connects to signaling, and auto-opens the web app.
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
<table>
|
|
35
|
+
<tr>
|
|
36
|
+
<td width="50%" align="center">
|
|
37
|
+
|
|
38
|
+
<img src="https://pub-2a5bcc605c9f466681c9b10bf4d173f4.r2.dev/images/task-graph.png" alt="Structured tasks with dependency graph" width="100%">
|
|
39
|
+
|
|
40
|
+
**Structured Tasks**<br>
|
|
41
|
+
<sub>Dependency graphs, progress tracking, and orchestrated subtasks — not just a flat checklist.</sub>
|
|
42
|
+
|
|
43
|
+
</td>
|
|
44
|
+
<td width="50%" align="center">
|
|
45
|
+
|
|
46
|
+
<img src="https://pub-2a5bcc605c9f466681c9b10bf4d173f4.r2.dev/images/plan-review.png" alt="Plan review with comments and approval" width="100%">
|
|
47
|
+
|
|
48
|
+
**Plan Collaboration**<br>
|
|
49
|
+
<sub>Rich-text plans with inline comments, real-time co-editing, and approval workflows.</sub>
|
|
50
|
+
|
|
51
|
+
</td>
|
|
52
|
+
</tr>
|
|
53
|
+
<tr>
|
|
54
|
+
<td width="50%" align="center">
|
|
55
|
+
|
|
56
|
+
<img src="https://pub-2a5bcc605c9f466681c9b10bf4d173f4.r2.dev/images/diff-review.png" alt="Diff review with inline comments" width="100%">
|
|
57
|
+
|
|
58
|
+
**Diff Review**<br>
|
|
59
|
+
<sub>Review every code change with inline comments that flow back to the agent.</sub>
|
|
60
|
+
|
|
61
|
+
</td>
|
|
62
|
+
<td width="50%" align="center">
|
|
63
|
+
|
|
64
|
+
<img src="https://pub-2a5bcc605c9f466681c9b10bf4d173f4.r2.dev/images/canvas.png" alt="Infinite canvas with diagrams and annotations" width="100%">
|
|
65
|
+
|
|
66
|
+
**Infinite Canvas**<br>
|
|
67
|
+
<sub>Mermaid diagrams, HTML visualizations, drawings, and annotations on a shared workspace.</sub>
|
|
68
|
+
|
|
69
|
+
</td>
|
|
70
|
+
</tr>
|
|
71
|
+
<tr>
|
|
72
|
+
<td width="50%" align="center">
|
|
73
|
+
|
|
74
|
+
<img src="https://pub-2a5bcc605c9f466681c9b10bf4d173f4.r2.dev/images/browser-preview.png" alt="Browser preview with annotation overlay" width="100%">
|
|
75
|
+
|
|
76
|
+
**Browser Preview**<br>
|
|
77
|
+
<sub>Forward local dev servers to the browser. Annotate directly on the live app.</sub>
|
|
78
|
+
|
|
79
|
+
</td>
|
|
80
|
+
<td width="50%" align="center">
|
|
81
|
+
|
|
82
|
+
<img src="https://pub-2a5bcc605c9f466681c9b10bf4d173f4.r2.dev/images/code-terminal.png" alt="Code editor and terminal" width="100%">
|
|
83
|
+
|
|
84
|
+
**Code Editor & Terminal**<br>
|
|
85
|
+
<sub>Monaco editor with file tree, plus a terminal forwarded from your machine via WebRTC.</sub>
|
|
86
|
+
|
|
87
|
+
</td>
|
|
88
|
+
</tr>
|
|
89
|
+
</table>
|
|
90
|
+
|
|
91
|
+
**And more:** real-time multiplayer collaboration (share a URL, review together), threads (branch parallel agent conversations), rewind (checkpoint & restore code + conversation), scheduled runs (automated cron tasks), voice mode, @ file mentions, slash commands, one-click daemon updates.
|
|
92
|
+
|
|
93
|
+
**Agent support:** [Claude Code](https://docs.anthropic.com/en/docs/agents/claude-code) (full integration). Agent-agnostic architecture — bring your own.
|
|
94
|
+
|
|
95
|
+
## How It Works
|
|
96
|
+
|
|
97
|
+
1. **Start a task** — describe what you want built, the agent begins working
|
|
98
|
+
2. **Review in real time** — watch diffs, plans, and reasoning as the agent builds
|
|
99
|
+
3. **Comment & guide** — add inline comments on diffs or plans; the agent sees your feedback and adjusts
|
|
100
|
+
4. **Collaborate** — share a URL, teammates join and review together via P2P sync
|
|
101
|
+
5. **Accept & ship** — approve the work, merge the PR
|
|
27
102
|
|
|
28
103
|
## Commands
|
|
29
104
|
|
|
@@ -56,12 +131,17 @@ The `start` command handles everything: checks for auth, runs the device flow if
|
|
|
56
131
|
| `SHIPYARD_MACHINE_ID` | `os.hostname()` | Machine identifier |
|
|
57
132
|
| `SHIPYARD_MACHINE_NAME` | `os.hostname()` | Human-readable machine name |
|
|
58
133
|
|
|
59
|
-
##
|
|
134
|
+
## Data & Privacy
|
|
135
|
+
|
|
136
|
+
| Data | Where It Lives | Control |
|
|
137
|
+
|------|---------------|---------|
|
|
138
|
+
| Conversations | Daemon (JSONL files on your machine) | You own it |
|
|
139
|
+
| Plans & canvas | CRDT documents synced via WebRTC | You own it |
|
|
140
|
+
| Assets | Daemon storage + WebRTC transfer | Never leaves your network |
|
|
141
|
+
| Browser state | IndexedDB (local) | Stays in your browser |
|
|
60
142
|
|
|
61
|
-
|
|
62
|
-
- [Architecture](https://github.com/SchoolAI/shipyard/blob/main/docs/architecture.md)
|
|
63
|
-
- [Development](https://github.com/SchoolAI/shipyard/blob/main/docs/development.md)
|
|
143
|
+
**Anonymous product analytics via PostHog.** No conversation content, code, or personal data is collected. All task data stays on your machine and syncs peer-to-peer.
|
|
64
144
|
|
|
65
145
|
## License
|
|
66
146
|
|
|
67
|
-
|
|
147
|
+
FSL-1.1-ALv2 (Functional Source License) — Free for all non-competing use, converts to Apache 2.0 in 2 years.
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
print,
|
|
4
|
-
printError
|
|
5
|
-
} from "./chunk-CCW5QAUH.js";
|
|
6
2
|
import {
|
|
7
3
|
DeviceExchangeCodeResponseSchema,
|
|
8
4
|
DevicePollPendingSchema,
|
|
9
5
|
DevicePollResponseSchema,
|
|
10
6
|
DeviceStartResponseSchema,
|
|
11
7
|
ROUTES
|
|
12
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-6GPDEZNR.js";
|
|
9
|
+
import {
|
|
10
|
+
print,
|
|
11
|
+
printError
|
|
12
|
+
} from "./chunk-CCW5QAUH.js";
|
|
13
13
|
import {
|
|
14
14
|
getConfigPath,
|
|
15
15
|
loadAuthToken,
|
|
@@ -217,4 +217,4 @@ export {
|
|
|
217
217
|
ensureAuthenticated,
|
|
218
218
|
loginCommand
|
|
219
219
|
};
|
|
220
|
-
//# sourceMappingURL=chunk-
|
|
220
|
+
//# sourceMappingURL=chunk-5J6ABOPF.js.map
|
|
@@ -158,8 +158,8 @@ var PresignedUrlPayloadSchema = external_exports.object({
|
|
|
158
158
|
generation: external_exports.number().optional()
|
|
159
159
|
});
|
|
160
160
|
var ReasoningCapabilitySchema = external_exports.object({
|
|
161
|
-
efforts: external_exports.array(external_exports.enum(["low", "medium", "high", "xhigh", "max"
|
|
162
|
-
defaultEffort: external_exports.enum(["low", "medium", "high", "xhigh", "max"
|
|
161
|
+
efforts: external_exports.array(external_exports.enum(["none", "low", "medium", "high", "xhigh", "max"])).min(1),
|
|
162
|
+
defaultEffort: external_exports.enum(["none", "low", "medium", "high", "xhigh", "max"])
|
|
163
163
|
}).refine((data) => data.efforts.includes(data.defaultEffort), {
|
|
164
164
|
message: "defaultEffort must be one of the supported efforts"
|
|
165
165
|
});
|
|
@@ -650,7 +650,7 @@ var ROUTE_DESCRIPTIONS = [
|
|
|
650
650
|
];
|
|
651
651
|
|
|
652
652
|
// ../../packages/session/src/claude-code-compat.ts
|
|
653
|
-
var TESTED_CLAUDE_CODE_VERSION = "2.1.
|
|
653
|
+
var TESTED_CLAUDE_CODE_VERSION = "2.1.120";
|
|
654
654
|
function classifyClaudeCodeCompatibility(detected, tested = TESTED_CLAUDE_CODE_VERSION) {
|
|
655
655
|
if (!detected) return { status: "unknown" };
|
|
656
656
|
const detectedParts = detected.split(".");
|
|
@@ -1040,7 +1040,7 @@ var PersonalRoomConnection = class {
|
|
|
1040
1040
|
};
|
|
1041
1041
|
|
|
1042
1042
|
// ../../packages/session/src/protocol-version.ts
|
|
1043
|
-
var PROTOCOL_VERSION =
|
|
1043
|
+
var PROTOCOL_VERSION = 47;
|
|
1044
1044
|
|
|
1045
1045
|
// ../../packages/session/src/publish-constants.ts
|
|
1046
1046
|
var PUBLISHED_PREVIEW_KINDS = [
|
|
@@ -1140,4 +1140,4 @@ export {
|
|
|
1140
1140
|
PublishCreateResponseSchema,
|
|
1141
1141
|
ROUTES
|
|
1142
1142
|
};
|
|
1143
|
-
//# sourceMappingURL=chunk-
|
|
1143
|
+
//# sourceMappingURL=chunk-6GPDEZNR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../packages/session/src/schemas.ts","../../../packages/session/src/routes.ts","../../../packages/session/src/claude-code-compat.ts","../../../packages/session/src/collab-room-connection.ts","../../../packages/session/src/personal-room-connection.ts","../../../packages/session/src/protocol-version.ts","../../../packages/session/src/publish-constants.ts"],"sourcesContent":["/**\n * Zod schemas for all signaling server request/response bodies and WebSocket messages.\n *\n * This module provides:\n * - Validation schemas for all HTTP endpoints\n * - WebSocket message schemas for personal and collab rooms\n * - Inferred TypeScript types for type-safe API usage\n * - Error response schemas for consistent error handling\n *\n * This is the single source of truth for all API schemas.\n * The client directory is designed to be self-contained and hoistable\n * to packages/shared without depending on server code.\n *\n * @module client/schemas\n */\n\nimport { z } from 'zod';\n\n/**\n * Pattern for valid git branch names.\n * Shared between daemon validation and web form validation.\n */\nexport const BRANCH_NAME_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9/_.-]*$/;\n\n/**\n * Pattern for browser/agent machineId query params on personal-room and\n * collab-room WebSocket upgrades. Used by the server to validate before\n * composing participantIds. Clients below MIN_PROTOCOL_VERSION that omit\n * it will be rejected elsewhere, but the server falls back gracefully.\n */\nexport const MACHINE_ID_PATTERN = /^[\\w-]+$/;\nexport const MACHINE_ID_MAX_LENGTH = 128;\n\n/**\n * Standard error response schema used across all endpoints.\n */\nexport const ErrorResponseSchema = z.object({\n error: z.string(),\n message: z.string(),\n});\n\nexport type ErrorResponse = z.infer<typeof ErrorResponseSchema>;\n\n/**\n * Validation error response with field-level details.\n */\nexport const ValidationErrorResponseSchema = ErrorResponseSchema.extend({\n details: z\n .array(\n z.object({\n path: z.array(z.union([z.string(), z.number()])),\n message: z.string(),\n code: z.string().optional(),\n })\n )\n .optional(),\n});\n\nexport type ValidationErrorResponse = z.infer<typeof ValidationErrorResponseSchema>;\n\n/**\n * Not found error response with available endpoints.\n */\nexport const NotFoundResponseSchema = ErrorResponseSchema.extend({\n endpoints: z.array(z.string()),\n});\n\nexport type NotFoundResponse = z.infer<typeof NotFoundResponseSchema>;\n\n/**\n * GET /health response schema.\n *\n * Returns service health status and environment info.\n */\nexport const HealthResponseSchema = z.object({\n status: z.literal('ok'),\n service: z.literal('shipyard-signaling'),\n environment: z.enum(['development', 'production']),\n});\n\nexport type HealthResponse = z.infer<typeof HealthResponseSchema>;\n\n/**\n * POST /auth/github/callback request body schema.\n *\n * Used to exchange a GitHub OAuth code for a Shipyard JWT.\n */\nexport const AuthGitHubCallbackRequestSchema = z.object({\n /** GitHub OAuth authorization code */\n code: z.string().min(1, 'code is required'),\n /** OAuth redirect URI that was used in the authorize request */\n redirect_uri: z.string().url('redirect_uri must be a valid URL'),\n});\n\nexport type AuthGitHubCallbackRequest = z.infer<typeof AuthGitHubCallbackRequestSchema>;\n\n/**\n * User info returned from successful OAuth.\n */\nexport const OAuthUserSchema = z.object({\n /** Shipyard user ID (\"usr_abc123\") */\n id: z.string(),\n /** Display name */\n displayName: z.string(),\n /** GitHub avatar URL */\n avatarUrl: z.string().nullable(),\n /** Linked providers */\n providers: z.array(z.string()),\n});\n\nexport type OAuthUser = z.infer<typeof OAuthUserSchema>;\n\n/**\n * POST /auth/github/callback response schema.\n *\n * Returns a Shipyard JWT and user info on successful OAuth.\n */\nexport const AuthGitHubCallbackResponseSchema = z.object({\n /** Shipyard JWT for authentication */\n token: z.string(),\n /** User info from GitHub */\n user: OAuthUserSchema,\n /** GitHub access token for API calls (~8h expiry for GitHub App tokens) */\n githubAccessToken: z.string().optional(),\n /** GitHub refresh token for obtaining new access tokens (~6 month expiry) */\n githubRefreshToken: z.string().optional(),\n /** Present and true if request came from a mobile device */\n is_mobile: z.boolean().optional(),\n});\n\nexport type AuthGitHubCallbackResponse = z.infer<typeof AuthGitHubCallbackResponseSchema>;\n\n/**\n * POST /auth/github/refresh request body schema.\n *\n * Exchange a GitHub refresh token for a new access token.\n */\nexport const AuthGitHubRefreshRequestSchema = z.object({\n /** GitHub refresh token from the original OAuth flow */\n refreshToken: z.string().min(1, 'refreshToken is required'),\n});\n\nexport type AuthGitHubRefreshRequest = z.infer<typeof AuthGitHubRefreshRequestSchema>;\n\n/**\n * POST /auth/github/refresh response schema.\n */\nexport const AuthGitHubRefreshResponseSchema = z.object({\n /** New GitHub access token */\n githubAccessToken: z.string(),\n /** New GitHub refresh token (GitHub rotates these on each use) */\n githubRefreshToken: z.string(),\n});\n\nexport type AuthGitHubRefreshResponse = z.infer<typeof AuthGitHubRefreshResponseSchema>;\n\n/**\n * GET /auth/verify response schema.\n *\n * Validates a JWT against the database and returns user info or failure reason.\n */\nexport const AuthVerifyResponseSchema = z.discriminatedUnion('valid', [\n z.object({ valid: z.literal(true), user: OAuthUserSchema }),\n z.object({\n valid: z.literal(false),\n reason: z.enum(['invalid_token', 'user_not_found']),\n }),\n]);\n\nexport type AuthVerifyResponse = z.infer<typeof AuthVerifyResponseSchema>;\n\n/**\n * All valid participant roles in a collab room.\n * Owner is the task creator; collaborator roles come from the invite link.\n */\nexport const ParticipantRoleSchema = z.enum([\n 'owner',\n 'collaborator-full',\n 'collaborator-review',\n 'viewer',\n]);\nexport type ParticipantRole = z.infer<typeof ParticipantRoleSchema>;\n\n/**\n * Collaborator-only roles (subset of ParticipantRole, excludes 'owner').\n * Used for invite link creation where the owner role is never assignable.\n */\nexport const CollaboratorRoleSchema = ParticipantRoleSchema.extract([\n 'collaborator-full',\n 'collaborator-review',\n 'viewer',\n]);\nexport type CollaboratorRole = z.infer<typeof CollaboratorRoleSchema>;\n\n/**\n * POST /collab/create request body schema.\n *\n * Used to create a new collaboration room with a pre-signed URL.\n */\nexport const CollabCreateRequestSchema = z.object({\n /** ID of the task to collaborate on */\n taskId: z.string().min(1, 'taskId is required'),\n /** How long the collaboration link should be valid (1-10080 minutes / 7 days max, default 60) */\n expiresInMinutes: z.number().min(1).max(10080).default(60),\n /** Permission level for the invitee (defaults to 'collaborator-full') */\n role: CollaboratorRoleSchema.optional(),\n});\n\nexport type CollabCreateRequest = z.infer<typeof CollabCreateRequestSchema>;\n\n/**\n * POST /collab/create response schema.\n *\n * Returns the pre-signed WebSocket URL for joining the collaboration room.\n */\nexport const CollabCreateResponseSchema = z.object({\n /** Pre-signed WebSocket URL for joining the room */\n url: z.string().url(),\n /** Unique room identifier */\n roomId: z.string(),\n /** Unix timestamp when the collaboration link expires */\n expiresAt: z.number(),\n});\n\nexport type CollabCreateResponse = z.infer<typeof CollabCreateResponseSchema>;\n\n/**\n * GET /personal/:userId error responses.\n *\n * WebSocket messages are defined below.\n *\n * The actual WebSocket is handled by the Durable Object.\n * These are HTTP error responses before upgrade.\n */\nexport const WsPersonalErrorSchema = z.discriminatedUnion('error', [\n ErrorResponseSchema.extend({\n error: z.literal('upgrade_required'),\n }),\n ErrorResponseSchema.extend({\n error: z.literal('missing_token'),\n }),\n ErrorResponseSchema.extend({\n error: z.literal('invalid_token'),\n }),\n ErrorResponseSchema.extend({\n error: z.literal('forbidden'),\n }),\n]);\n\nexport type WsPersonalError = z.infer<typeof WsPersonalErrorSchema>;\n\n/**\n * GET /collab/:roomId error responses.\n *\n * WebSocket messages are defined below.\n *\n * The actual WebSocket is handled by the Durable Object.\n * These are HTTP error responses before upgrade.\n */\nexport const WsCollabErrorSchema = z.discriminatedUnion('error', [\n ErrorResponseSchema.extend({\n error: z.literal('upgrade_required'),\n }),\n ErrorResponseSchema.extend({\n error: z.literal('missing_token'),\n }),\n ErrorResponseSchema.extend({\n error: z.literal('invalid_token'),\n }),\n ErrorResponseSchema.extend({\n error: z.literal('forbidden'),\n }),\n ErrorResponseSchema.extend({\n error: z.literal('expired'),\n }),\n]);\n\nexport type WsCollabError = z.infer<typeof WsCollabErrorSchema>;\n\n/**\n * Shipyard JWT claims schema.\n *\n * This is the payload embedded in the JWT returned by /auth/github/callback.\n */\nexport const ShipyardJWTClaimsSchema = z.object({\n /** Shipyard user ID: \"usr_abc123\" */\n sub: z.string(),\n /** Display name from primary provider */\n displayName: z.string(),\n /** Linked OAuth providers */\n providers: z.array(z.string()),\n iat: z.number(),\n exp: z.number(),\n /** Optional: Scope for agent tokens (e.g., 'task:abc123') */\n scope: z.string().optional(),\n /** Optional: Machine ID for daemon tokens */\n machineId: z.string().optional(),\n});\n\nexport type ShipyardJWTClaims = z.infer<typeof ShipyardJWTClaimsSchema>;\n\n/**\n * Pre-signed URL payload schema.\n *\n * Embedded in the token query parameter for /collab/:roomId.\n */\nexport const PresignedUrlPayloadSchema = z.object({\n /** Room ID this token is valid for */\n roomId: z.string(),\n /** Task ID being collaborated on */\n taskId: z.string(),\n /** User ID of the person who created the invite */\n inviterId: z.string(),\n /** Expiration timestamp (Unix ms) */\n exp: z.number(),\n /** Permission level for the invitee (defaults to 'collaborator-full') */\n role: CollaboratorRoleSchema.optional(),\n /** Generation counter for link revocation — tokens with a generation older than the room's current generation are rejected */\n generation: z.number().optional(),\n});\n\nexport type PresignedUrlPayload = z.infer<typeof PresignedUrlPayloadSchema>;\n\n/**\n * Reasoning capability schema for models that support configurable reasoning effort.\n */\n/*\n * Keep in sync with ReasoningEffortSchema in packages/loro-schema/src/shared-enums.ts.\n * Inlined here because packages/session has no dependency on @shipyard/loro-schema.\n */\nexport const ReasoningCapabilitySchema = z\n .object({\n efforts: z.array(z.enum(['none', 'low', 'medium', 'high', 'xhigh', 'max'])).min(1),\n defaultEffort: z.enum(['none', 'low', 'medium', 'high', 'xhigh', 'max']),\n })\n .refine((data) => data.efforts.includes(data.defaultEffort), {\n message: 'defaultEffort must be one of the supported efforts',\n });\n\nexport type ReasoningCapability = z.infer<typeof ReasoningCapabilitySchema>;\n\n/**\n * Model info schema for machine capabilities.\n */\nexport const ModelInfoSchema = z.object({\n id: z.string(),\n name: z.string(),\n provider: z.string(),\n description: z.string().optional(),\n reasoning: ReasoningCapabilitySchema.optional(),\n supportsFastMode: z.boolean().optional(),\n});\n\nexport type ModelInfo = z.infer<typeof ModelInfoSchema>;\n\n/**\n * Git repo info schema for machine capabilities.\n */\nexport const GitRepoInfoSchema = z.object({\n path: z.string(),\n name: z.string(),\n branch: z.string(),\n remote: z.string().optional(),\n});\n\nexport type GitRepoInfo = z.infer<typeof GitRepoInfoSchema>;\n\n/**\n * Permission mode schema for machine capabilities.\n */\nexport const PermissionModeSchema = z.enum(['default', 'accept-edits', 'plan', 'bypass', 'auto']);\n\nexport type PermissionMode = z.infer<typeof PermissionModeSchema>;\n\n/**\n * Anthropic auth status — detected from env vars, Claude Code OAuth, or cloud providers.\n */\nconst AnthropicAuthMethodEnum = z.enum([\n 'claude-ai',\n 'console',\n 'api-key',\n 'sso',\n 'gateway',\n 'bedrock',\n 'vertex',\n 'foundry',\n 'none',\n]);\n\nexport const AnthropicAuthStatusSchema = z.object({\n status: z.enum(['authenticated', 'unauthenticated', 'unknown']),\n method: AnthropicAuthMethodEnum,\n email: z.string().optional(),\n orgName: z.string().optional(),\n subscriptionType: z.string().nullable().optional(),\n apiProvider: z.string().optional(),\n authMismatch: z\n .object({\n selected: AnthropicAuthMethodEnum,\n envMethod: AnthropicAuthMethodEnum,\n envVar: z.string(),\n })\n .optional(),\n});\n\nexport type AnthropicAuthStatus = z.infer<typeof AnthropicAuthStatusSchema>;\n\nexport const MCPServerAuthStatusSchema = z.enum(['authenticated', 'unauthenticated', 'unknown']);\nexport type MCPServerAuthStatus = z.infer<typeof MCPServerAuthStatusSchema>;\n\nexport const MCPServerSourceSchema = z.enum([\n 'project',\n 'user',\n 'local',\n 'mcp-json',\n 'plugin',\n 'claudeai',\n]);\nexport type MCPServerSource = z.infer<typeof MCPServerSourceSchema>;\n\nconst MCP_SERVER_TYPES = ['stdio', 'http', 'sse'] as const;\nexport const MCPServerTypeSchema = z.enum(MCP_SERVER_TYPES);\nexport type MCPServerType = z.infer<typeof MCPServerTypeSchema>;\n\nexport const MCPOAuthConfigSchema = z.object({\n clientId: z.string().optional(),\n callbackPort: z.number().optional(),\n});\n\nexport const MCPServerInfoSchema = z.object({\n name: z.string(),\n type: MCPServerTypeSchema.default('stdio'),\n command: z.string().optional(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n url: z.string().optional(),\n headers: z.record(z.string(), z.string()).optional(),\n oauth: MCPOAuthConfigSchema.optional(),\n enabled: z.boolean(),\n source: MCPServerSourceSchema,\n authStatus: MCPServerAuthStatusSchema,\n});\nexport type MCPServerInfo = z.infer<typeof MCPServerInfoSchema>;\n\nexport const SkillInfoSchema = z.object({\n name: z.string(),\n description: z.string(),\n});\nexport type SkillInfo = z.infer<typeof SkillInfoSchema>;\n\n/**\n * Machine capabilities schema — advertised by daemons at registration time.\n */\nexport const MarketplacePluginInfoSchema = z.object({\n name: z.string(),\n description: z.string(),\n author: z.string(),\n marketplace: z.string(),\n installCount: z.number().optional(),\n installed: z.boolean(),\n enabled: z.boolean(),\n version: z.string().optional(),\n isExternal: z.boolean(),\n});\nexport type MarketplacePluginInfo = z.infer<typeof MarketplacePluginInfoSchema>;\n\nexport const ClaudeCodeAgentSchema = z.object({\n id: z.literal('claude-code'),\n name: z.literal('Claude Code'),\n version: z.string().optional(),\n});\n\nexport const InstalledAgentSchema = z.discriminatedUnion('id', [ClaudeCodeAgentSchema]);\nexport type InstalledAgent = z.infer<typeof InstalledAgentSchema>;\n\nexport const MachineCapabilitiesSchema = z.object({\n models: z.array(ModelInfoSchema),\n environments: z.array(GitRepoInfoSchema),\n permissionModes: z.array(PermissionModeSchema),\n homeDir: z.string(),\n anthropicAuth: AnthropicAuthStatusSchema.optional(),\n mcpServers: z.array(MCPServerInfoSchema),\n skills: z.array(SkillInfoSchema),\n marketplacePlugins: z.array(MarketplacePluginInfoSchema),\n autoModeEnabled: z.boolean().optional(),\n installedAgents: z.array(InstalledAgentSchema),\n});\n\nexport type MachineCapabilities = z.infer<typeof MachineCapabilitiesSchema>;\n\n/**\n * Register agent message schema for personal room WebSocket.\n * Capabilities are no longer sent via signaling -- they flow through\n * Loro ephemeral on the room document instead.\n */\n/**\n * Local-direct advertisement — when the daemon is running a LocalDirectServer\n * on a loopback port, it advertises that port + connection token so a browser\n * on the same machine can bypass WebRTC/signaling entirely. Additive, optional.\n *\n * Token is carried here because the browser cannot read the daemon's on-disk\n * advertisement file. Signaling is JWT-authenticated, so a token over this\n * channel is safe for a single-user dev box. For multi-user hosts, audit the\n * threat model before shipping phase 2 (default-on).\n */\nexport const LocalDirectAdvertisementSchema = z.object({\n port: z.number().int().min(1).max(65535),\n token: z.string().min(16),\n});\n\nexport type LocalDirectAdvertisement = z.infer<typeof LocalDirectAdvertisementSchema>;\n\nexport const RegisterAgentSchema = z.object({\n type: z.literal('register-agent'),\n agentId: z.string(),\n machineId: z.string(),\n machineName: z.string(),\n agentType: z.string(),\n protocolVersion: z.number().optional(),\n npmVersion: z.string().optional(),\n localDirect: LocalDirectAdvertisementSchema.optional(),\n});\n\n/**\n * Unregister agent message schema for personal room WebSocket.\n */\nexport const UnregisterAgentSchema = z.object({\n type: z.literal('unregister-agent'),\n agentId: z.string(),\n});\n\n/**\n * Agent status update message schema for personal room WebSocket.\n */\nexport const AgentStatusSchema = z.object({\n type: z.literal('agent-status'),\n agentId: z.string(),\n status: z.enum(['idle', 'running', 'error']),\n activeTaskId: z.string().optional(),\n});\n\n/**\n * WebRTC offer message schema for personal room WebSocket.\n *\n * When sent by a client: `targetMachineId` is the intended recipient.\n * When relayed by the server: `fromMachineId` is added to identify the sender.\n *\n * `generationId` is a UUID minted by the offerer when it constructs the\n * RTCPeerConnection. It flows through the answer and every subsequent ICE\n * candidate for that PC so both sides can discard messages belonging to a\n * prior generation after a teardown-and-replace cycle. Without it, stale\n * candidates in flight across the signaling relay silently contaminate the\n * successor PC's ICE state.\n */\nexport const WebRTCOfferSchema = z.object({\n type: z.literal('webrtc-offer'),\n targetMachineId: z.string(),\n fromMachineId: z.string().optional(),\n generationId: z.string(),\n offer: z.unknown(),\n requestId: z.string().optional(),\n});\n\n/**\n * WebRTC answer message schema for personal room WebSocket.\n *\n * When sent by a client: `targetMachineId` is the intended recipient.\n * When relayed by the server: `fromMachineId` is added to identify the sender.\n *\n * `generationId` echoes the offerer's generationId so the offerer can\n * discard answers that don't correspond to its current PC.\n */\nexport const WebRTCAnswerSchema = z.object({\n type: z.literal('webrtc-answer'),\n targetMachineId: z.string(),\n fromMachineId: z.string().optional(),\n generationId: z.string(),\n answer: z.unknown(),\n requestId: z.string().optional(),\n});\n\n/**\n * WebRTC ICE candidate message schema for personal room WebSocket.\n *\n * When sent by a client: `targetMachineId` is the intended recipient.\n * When relayed by the server: `fromMachineId` is added to identify the sender.\n *\n * `generationId` identifies the PC that emitted this candidate. Receivers\n * drop candidates whose generationId doesn't match the PC currently tracked\n * for the sender.\n */\nexport const WebRTCIceSchema = z.object({\n type: z.literal('webrtc-ice'),\n targetMachineId: z.string(),\n fromMachineId: z.string().optional(),\n generationId: z.string(),\n candidate: z.unknown(),\n});\n\n/**\n * ICE server entry schema (matches RTCIceServer).\n */\nexport const IceServerSchema = z.object({\n urls: z.union([z.string(), z.array(z.string())]),\n username: z.string().optional(),\n credential: z.string().optional(),\n});\n\nexport type IceServer = z.infer<typeof IceServerSchema>;\n\n/**\n * Default ICE servers used when the server has not provided TURN credentials.\n * Centralized here so all consumers (browser, daemon, session-server) share\n * one source of truth for the fallback STUN URL.\n */\nexport const DEFAULT_ICE_SERVERS: IceServer[] = [{ urls: 'stun:stun.cloudflare.com:3478' }];\n\n/**\n * Server→client message delivering ICE server configuration (STUN + TURN).\n * Sent after authentication so clients have TURN credentials before any\n * peer connections are created.\n */\nexport const IceServersSchema = z.object({\n type: z.literal('ice-servers'),\n iceServers: z.array(IceServerSchema),\n});\n\n/**\n * Error message schema for WebSocket connections.\n */\nexport const ErrorMessageSchema = z.object({\n type: z.literal('error'),\n code: z.string(),\n message: z.string(),\n requestId: z.string().optional(),\n});\n\n/**\n * User settings schema — stored in CRDT, synced across daemons.\n */\nexport const UserSettingsSchema = z.object({\n worktreeSetupScript: z.string().nullable(),\n});\n\nexport type UserSettings = z.infer<typeof UserSettingsSchema>;\n\n/**\n * Browser requests daemon self-update via signaling relay.\n * Follows the WebRTC relay pattern: browser sends with targetMachineId,\n * server relays to daemon with fromMachineId added.\n */\nexport const RequestDaemonUpdateSchema = z.object({\n type: z.literal('request-daemon-update'),\n targetMachineId: z.string(),\n fromMachineId: z.string().optional(),\n installCommand: z.string(),\n});\n\nexport type RequestDaemonUpdate = z.infer<typeof RequestDaemonUpdateSchema>;\n\n/**\n * Daemon reports self-update progress via signaling relay.\n * Sent by daemon, server broadcasts to all browser connections.\n *\n * Status lifecycle — daemon-as-stager model:\n * downloading → downloaded → handoff → (daemon exits) → installing →\n * verifying → restarting → (new daemon boots) → succeeded|rolled-back|failed\n * The succeeded transition is reported by the NEW daemon on first authenticated\n * browser connection (see readAndClearUpdateStatus).\n */\nexport const DaemonUpdateStatusSchema = z.object({\n type: z.literal('daemon-update-status'),\n fromMachineId: z.string().optional(),\n status: z.enum([\n 'downloading',\n 'downloaded',\n 'handoff',\n 'installing',\n 'verifying',\n 'restarting',\n 'succeeded',\n 'rolled-back',\n 'failed',\n ]),\n error: z.string().optional(),\n targetVersion: z.string().optional(),\n previousVersion: z.string().optional(),\n});\n\nexport type DaemonUpdateStatus = z.infer<typeof DaemonUpdateStatusSchema>;\n\n/**\n * Union of all client-to-server messages for personal room WebSocket.\n */\nexport const PersonalRoomClientMessageSchema = z.discriminatedUnion('type', [\n RegisterAgentSchema,\n UnregisterAgentSchema,\n AgentStatusSchema,\n WebRTCOfferSchema,\n WebRTCAnswerSchema,\n WebRTCIceSchema,\n ErrorMessageSchema,\n RequestDaemonUpdateSchema,\n DaemonUpdateStatusSchema,\n]);\n\nexport type PersonalRoomClientMessage = z.infer<typeof PersonalRoomClientMessageSchema>;\n\n/**\n * Authentication success message schema for personal room WebSocket.\n */\nexport const AuthenticatedSchema = z.object({\n type: z.literal('authenticated'),\n userId: z.string(),\n username: z.string(),\n});\n\n/**\n * Agent info schema for personal room WebSocket.\n * Capabilities are no longer included -- they flow through Loro ephemeral.\n */\nexport const AgentInfoSchema = z.object({\n agentId: z.string(),\n machineId: z.string(),\n machineName: z.string(),\n agentType: z.string(),\n status: z.enum(['idle', 'running', 'error']),\n activeTaskId: z.string().optional(),\n protocolVersion: z.number().optional(),\n npmVersion: z.string().optional(),\n localDirect: LocalDirectAdvertisementSchema.optional(),\n});\n\nexport type AgentInfo = z.infer<typeof AgentInfoSchema>;\n\n/**\n * Agents list message schema for personal room WebSocket.\n */\nexport const AgentsListSchema = z.object({\n type: z.literal('agents-list'),\n agents: z.array(AgentInfoSchema),\n hasDaemonRegistered: z.boolean().optional(),\n});\n\n/**\n * Agent joined notification message schema for personal room WebSocket.\n */\nexport const AgentJoinedSchema = z.object({\n type: z.literal('agent-joined'),\n agent: AgentInfoSchema,\n});\n\n/**\n * Agent left notification message schema for personal room WebSocket.\n */\nexport const AgentLeftSchema = z.object({\n type: z.literal('agent-left'),\n agentId: z.string(),\n});\n\n/**\n * Agent status changed notification message schema for personal room WebSocket.\n */\nexport const AgentStatusChangedSchema = z.object({\n type: z.literal('agent-status-changed'),\n agentId: z.string(),\n status: z.enum(['idle', 'running', 'error']),\n activeTaskId: z.string().optional(),\n /**\n * Mirror the daemon's local-direct advert on status updates so browsers\n * joining mid-session (or recovering from a signaling reconnect) always\n * see the authoritative port/token. The browser's status-merge path\n * preserves prior-frame fields via spread; making this explicit avoids\n * relying on that incidental behavior.\n */\n localDirect: LocalDirectAdvertisementSchema.optional(),\n});\n\n/**\n * Webhook event schema for events ingested from external services (e.g. Linear)\n * and forwarded to connected daemons via the PersonalRoom WebSocket.\n */\nexport const WebhookEventSchema = z.object({\n type: z.literal('webhook-event'),\n source: z.string(),\n event: z.string(),\n payload: z.record(z.string(), z.unknown()),\n timestamp: z.number(),\n});\n\nexport type WebhookEvent = z.infer<typeof WebhookEventSchema>;\n\n/**\n * Union of all server-to-client messages for personal room WebSocket.\n */\nexport const PersonalRoomServerMessageSchema = z.discriminatedUnion('type', [\n AuthenticatedSchema,\n AgentsListSchema,\n AgentJoinedSchema,\n AgentLeftSchema,\n AgentStatusChangedSchema,\n ErrorMessageSchema,\n WebRTCOfferSchema,\n WebRTCAnswerSchema,\n WebRTCIceSchema,\n IceServersSchema,\n WebhookEventSchema,\n RequestDaemonUpdateSchema,\n DaemonUpdateStatusSchema,\n]);\n\nexport type PersonalRoomServerMessage = z.infer<typeof PersonalRoomServerMessageSchema>;\n\n/**\n * WebRTC offer message schema for collab room WebSocket.\n *\n * `generationId` is minted per-PeerConnection by the offerer so both sides\n * can discriminate messages from a prior PC generation after teardown and\n * replacement. Mirrors the personal-room pattern; without it, stale ICE or\n * answers from a pre-reconnect PC silently contaminate the successor PC's\n * state (see PR #2244 and the 2026-04-22 collab-refresh deadlock incident).\n */\nexport const CollabWebRTCOfferSchema = z.object({\n type: z.literal('webrtc-offer'),\n targetUserId: z.string(),\n fromUserId: z.string().optional(),\n generationId: z.string(),\n offer: z.unknown(),\n});\n\n/**\n * WebRTC answer message schema for collab room WebSocket.\n *\n * Echoes the offerer's `generationId` so the offerer can drop answers that\n * don't correspond to its current PC.\n */\nexport const CollabWebRTCAnswerSchema = z.object({\n type: z.literal('webrtc-answer'),\n targetUserId: z.string(),\n fromUserId: z.string().optional(),\n generationId: z.string(),\n answer: z.unknown(),\n});\n\n/**\n * WebRTC ICE candidate message schema for collab room WebSocket.\n *\n * `generationId` identifies the PC that emitted this candidate. Receivers\n * drop candidates whose generationId doesn't match the PC currently tracked\n * for the sender.\n */\nexport const CollabWebRTCIceSchema = z.object({\n type: z.literal('webrtc-ice'),\n targetUserId: z.string(),\n fromUserId: z.string().optional(),\n generationId: z.string(),\n candidate: z.unknown(),\n});\n\n/**\n * Union of all client-to-server messages for collab room WebSocket.\n */\nexport const CollabRoomClientMessageSchema = z.discriminatedUnion('type', [\n CollabWebRTCOfferSchema,\n CollabWebRTCAnswerSchema,\n CollabWebRTCIceSchema,\n]);\n\nexport type CollabRoomClientMessage = z.infer<typeof CollabRoomClientMessageSchema>;\n\n/**\n * Participant info schema for collab room WebSocket.\n *\n * `connectionId` is minted by the CollabRoom DO at each WebSocket accept\n * (per-connection, opaque to clients). Clients track it per-userId so they\n * can discard stale `participant-left` events from a prior session that\n * arrive after the same user has rejoined with a newer connection — the\n * root cause of the 2026-04-22 collab-refresh deadlock. Consumers MUST\n * record the latest connectionId they've seen for each userId and match\n * against incoming leave events before tearing down peer state.\n */\nexport const ParticipantSchema = z.object({\n userId: z.string(),\n username: z.string(),\n avatarUrl: z.string().nullable().optional(),\n role: ParticipantRoleSchema,\n connectionId: z.string(),\n});\n\nexport type Participant = z.infer<typeof ParticipantSchema>;\n\n/**\n * Authentication success message schema for collab room WebSocket.\n */\nexport const CollabAuthenticatedSchema = z.object({\n type: z.literal('authenticated'),\n userId: z.string(),\n username: z.string(),\n taskId: z.string(),\n});\n\n/**\n * Participants list message schema for collab room WebSocket.\n */\nexport const ParticipantsListSchema = z.object({\n type: z.literal('participants-list'),\n participants: z.array(ParticipantSchema),\n});\n\n/**\n * Participant joined notification message schema for collab room WebSocket.\n */\nexport const ParticipantJoinedSchema = z.object({\n type: z.literal('participant-joined'),\n participant: ParticipantSchema,\n});\n\n/**\n * Participant left notification message schema for collab room WebSocket.\n *\n * `connectionId` identifies WHICH connection left. When a user refreshes,\n * the DO's webSocketClose may fire after the refreshed tab has already\n * joined with a new connection — consumers drop a leave whose connectionId\n * doesn't match the latest one tracked for that userId. This is the\n * stale-disconnect discriminator that prevents ghost-teardown of the\n * freshly-established peer.\n */\nexport const ParticipantLeftSchema = z.object({\n type: z.literal('participant-left'),\n userId: z.string(),\n connectionId: z.string(),\n});\n\n/**\n * Union of all server-to-client messages for collab room WebSocket.\n */\nexport const CollabRoomServerMessageSchema = z.discriminatedUnion('type', [\n CollabAuthenticatedSchema,\n ParticipantsListSchema,\n ParticipantJoinedSchema,\n ParticipantLeftSchema,\n ErrorMessageSchema,\n CollabWebRTCOfferSchema,\n CollabWebRTCAnswerSchema,\n CollabWebRTCIceSchema,\n IceServersSchema,\n]);\n\nexport type CollabRoomServerMessage = z.infer<typeof CollabRoomServerMessageSchema>;\n\n/**\n * GitHub issue type for feedback categorization.\n */\nexport const GitHubIssueTypeSchema = z.enum(['bug', 'feature', 'question', 'praise']);\nexport type GitHubIssueType = z.infer<typeof GitHubIssueTypeSchema>;\n\n/**\n * POST /feedback/issue request body schema.\n */\nexport const GitHubIssueCreateRequestSchema = z.object({\n type: GitHubIssueTypeSchema,\n title: z.string().min(1, 'title is required').max(256, 'title must be 256 chars or fewer'),\n description: z.string().max(10000).optional(),\n logs: z.string().max(50000).optional(),\n context: z\n .object({\n url: z.string().optional(),\n taskId: z.string().optional(),\n userAgent: z.string().optional(),\n timestamp: z.string().optional(),\n })\n .optional(),\n});\n\nexport type GitHubIssueCreateRequest = z.infer<typeof GitHubIssueCreateRequestSchema>;\n\n/**\n * POST /feedback/issue response schema.\n */\nexport const GitHubIssueCreateResponseSchema = z.object({\n issueUrl: z.string(),\n issueNumber: z.number(),\n});\n\nexport type GitHubIssueCreateResponse = z.infer<typeof GitHubIssueCreateResponseSchema>;\n\n/**\n * POST /auth/linear/callback request body schema.\n *\n * Used to exchange a Linear OAuth code for Linear access tokens.\n * Requires an authenticated Shipyard JWT.\n */\nexport const AuthLinearCallbackRequestSchema = z.object({\n /** Linear OAuth authorization code */\n code: z.string().min(1, 'code is required'),\n /** OAuth redirect URI that was used in the authorize request */\n redirect_uri: z.string().url('redirect_uri must be a valid URL'),\n});\n\nexport type AuthLinearCallbackRequest = z.infer<typeof AuthLinearCallbackRequestSchema>;\n\n/**\n * POST /auth/linear/callback response schema.\n *\n * Returns Linear OAuth tokens and user info on successful OAuth.\n */\nexport const AuthLinearCallbackResponseSchema = z.object({\n /** Linear access token */\n linearAccessToken: z.string(),\n /** Seconds until the access token expires (from Linear's token response) */\n expiresIn: z.number().optional(),\n /** Linear user info */\n linearUser: z.object({\n id: z.string(),\n name: z.string().nullable(),\n email: z.string().nullable(),\n avatarUrl: z.string().nullable(),\n }),\n});\n\nexport type AuthLinearCallbackResponse = z.infer<typeof AuthLinearCallbackResponseSchema>;\n\n/** POST /auth/device/start — no request body needed */\nexport const DeviceStartResponseSchema = z.object({\n deviceCode: z.string(),\n userCode: z.string(),\n verificationUri: z.string().url(),\n expiresIn: z.number(),\n interval: z.number(),\n});\nexport type DeviceStartResponse = z.infer<typeof DeviceStartResponseSchema>;\n\n/** POST /auth/device/poll request */\nexport const DevicePollRequestSchema = z.object({\n deviceCode: z.string().min(1, 'deviceCode is required'),\n});\nexport type DevicePollRequest = z.infer<typeof DevicePollRequestSchema>;\n\n/** POST /auth/device/poll response (success) */\nexport const DevicePollResponseSchema = z.object({\n token: z.string(),\n user: OAuthUserSchema,\n});\nexport type DevicePollResponse = z.infer<typeof DevicePollResponseSchema>;\n\n/** POST /auth/device/poll response (pending/errors) */\nexport const DevicePollPendingSchema = z.object({\n error: z.enum(['authorization_pending', 'slow_down', 'expired_token']),\n});\nexport type DevicePollPending = z.infer<typeof DevicePollPendingSchema>;\n\n/** POST /auth/device/authorize — browser authorizes a device using its own JWT */\nexport const DeviceAuthorizeRequestSchema = z.object({\n userCode: z.string().min(1, 'userCode is required'),\n});\nexport type DeviceAuthorizeRequest = z.infer<typeof DeviceAuthorizeRequestSchema>;\n\nexport const DeviceAuthorizeResponseSchema = z.object({\n authorized: z.boolean(),\n});\nexport type DeviceAuthorizeResponse = z.infer<typeof DeviceAuthorizeResponseSchema>;\n\n/** POST /auth/device/exchange-code — daemon exchanges userCode for deviceCode */\nexport const DeviceExchangeCodeRequestSchema = z.object({\n userCode: z.string().min(1, 'userCode is required'),\n});\nexport type DeviceExchangeCodeRequest = z.infer<typeof DeviceExchangeCodeRequestSchema>;\n\nexport const DeviceExchangeCodeResponseSchema = z.object({\n deviceCode: z.string(),\n});\nexport type DeviceExchangeCodeResponse = z.infer<typeof DeviceExchangeCodeResponseSchema>;\n\n/** POST /auth/browser-code — daemon requests a one-time code for browser auth */\nexport const BrowserCodeResponseSchema = z.object({\n code: z.string(),\n expiresIn: z.number(),\n});\nexport type BrowserCodeResponse = z.infer<typeof BrowserCodeResponseSchema>;\n\n/** POST /auth/browser-code/exchange — browser exchanges code for JWT */\nexport const BrowserCodeExchangeRequestSchema = z.object({\n code: z.string().min(1, 'code is required'),\n});\nexport type BrowserCodeExchangeRequest = z.infer<typeof BrowserCodeExchangeRequestSchema>;\n\nexport const BrowserCodeExchangeResponseSchema = z.object({\n token: z.string(),\n user: OAuthUserSchema,\n});\nexport type BrowserCodeExchangeResponse = z.infer<typeof BrowserCodeExchangeResponseSchema>;\n\n/** GET /vault/key response */\nexport const VaultKeyGetResponseSchema = z.object({\n encryptedKey: z.string(),\n createdAt: z.number(),\n});\nexport type VaultKeyGetResponse = z.infer<typeof VaultKeyGetResponseSchema>;\n\n/** PUT /vault/key request */\nexport const VaultKeyPutRequestSchema = z.object({\n encryptedKey: z.string().min(1, 'encryptedKey is required').max(4096),\n});\nexport type VaultKeyPutRequest = z.infer<typeof VaultKeyPutRequestSchema>;\n\n/** PUT /vault/key response (created) */\nexport const VaultKeyPutResponseSchema = z.object({\n created: z.boolean(),\n});\nexport type VaultKeyPutResponse = z.infer<typeof VaultKeyPutResponseSchema>;\n\n/** Metrics ingestion */\n\nexport const MetricsEventSchema = z.object({\n eventType: z.string().min(1).max(100),\n taskId: z.string().max(200).optional(),\n payload: z.record(z.unknown()).default({}),\n clientTimestamp: z.number().int().positive(),\n});\nexport type MetricsEvent = z.infer<typeof MetricsEventSchema>;\n\nexport const MetricsIngestRequestSchema = z.object({\n events: z.array(MetricsEventSchema).min(1).max(100),\n});\nexport type MetricsIngestRequest = z.infer<typeof MetricsIngestRequestSchema>;\n\nexport const MetricsIngestResponseSchema = z.object({\n accepted: z.number(),\n});\nexport type MetricsIngestResponse = z.infer<typeof MetricsIngestResponseSchema>;\n","/**\n * Shared route constants for the signaling server.\n *\n * Used by both server (route registration) and client (request URLs).\n * Single source of truth prevents drift between implementations.\n *\n * @module client/routes\n */\nexport const ROUTES = {\n HEALTH: '/health',\n AUTH_GITHUB_CALLBACK: '/auth/github/callback',\n AUTH_GITHUB_REFRESH: '/auth/github/refresh',\n AUTH_DEVICE_START: '/auth/device/start',\n AUTH_DEVICE_VERIFY: '/auth/device/verify',\n AUTH_DEVICE_POLL: '/auth/device/poll',\n AUTH_DEVICE_AUTHORIZE: '/auth/device/authorize',\n AUTH_DEVICE_EXCHANGE_CODE: '/auth/device/exchange-code',\n AUTH_BROWSER_CODE: '/auth/browser-code',\n AUTH_BROWSER_CODE_EXCHANGE: '/auth/browser-code/exchange',\n AUTH_VERIFY: '/auth/verify',\n COLLAB_CREATE: '/collab/create',\n COLLAB_REVOKE: '/collab/:roomId',\n GITHUB_ISSUE_CREATE: '/feedback/issue',\n VAULT_KEY: '/vault/key',\n AUTH_LINEAR: '/auth/linear',\n AUTH_LINEAR_CALLBACK: '/auth/linear/callback',\n WEBHOOK_INGEST: '/webhooks/:userId/:source',\n WS_PERSONAL: '/personal/:userId',\n WS_COLLAB: '/collab/:roomId',\n METRICS_INGEST: '/ingest',\n METRICS_QUERY_EVENTS: '/query/events',\n PUBLISH_UPLOAD: '/publish',\n PUBLISH_ITEM: '/publish/:id',\n PUBLISH_MINE: '/publish/mine',\n} as const;\n\n/**\n * Human-readable endpoint descriptions for documentation and error messages.\n */\nexport const ROUTE_DESCRIPTIONS = [\n `GET ${ROUTES.HEALTH}`,\n `POST ${ROUTES.AUTH_GITHUB_CALLBACK}`,\n `POST ${ROUTES.AUTH_GITHUB_REFRESH}`,\n `POST ${ROUTES.AUTH_DEVICE_START}`,\n `GET ${ROUTES.AUTH_DEVICE_VERIFY}`,\n `POST ${ROUTES.AUTH_DEVICE_POLL}`,\n `POST ${ROUTES.AUTH_DEVICE_AUTHORIZE}`,\n `POST ${ROUTES.AUTH_DEVICE_EXCHANGE_CODE}`,\n `POST ${ROUTES.AUTH_BROWSER_CODE}`,\n `POST ${ROUTES.AUTH_BROWSER_CODE_EXCHANGE}`,\n `GET ${ROUTES.AUTH_VERIFY}`,\n `POST ${ROUTES.COLLAB_CREATE}`,\n `DELETE ${ROUTES.COLLAB_REVOKE}`,\n `POST ${ROUTES.GITHUB_ISSUE_CREATE}`,\n `GET ${ROUTES.VAULT_KEY}`,\n `PUT ${ROUTES.VAULT_KEY}`,\n `GET ${ROUTES.AUTH_LINEAR}`,\n `GET ${ROUTES.AUTH_LINEAR_CALLBACK}`,\n `POST ${ROUTES.WEBHOOK_INGEST}`,\n `WS ${ROUTES.WS_PERSONAL}`,\n `WS ${ROUTES.WS_COLLAB}`,\n `POST ${ROUTES.METRICS_INGEST}`,\n `GET ${ROUTES.METRICS_QUERY_EVENTS}`,\n `POST ${ROUTES.PUBLISH_UPLOAD}`,\n `PUT ${ROUTES.PUBLISH_ITEM}`,\n `DELETE ${ROUTES.PUBLISH_ITEM}`,\n `GET ${ROUTES.PUBLISH_MINE}`,\n] as const;\n","/**\n * Claude Code version compatibility for the Shipyard daemon.\n *\n * The SDK ships a per-platform native `claude` binary via optional\n * dependencies (`@anthropic-ai/claude-agent-sdk-${platform}-${arch}`).\n * The user's global `claude` install is NOT what Shipyard spawns.\n * Pinning the SDK version effectively pins Claude Code. This module\n * provides observability: when the init message reports a runtime\n * version, we compare it against what we tested.\n */\n\n/** The Claude Code version bundled with the currently pinned SDK (0.2.120). */\nexport const TESTED_CLAUDE_CODE_VERSION = '2.1.120';\n\nexport type ClaudeCodeCompatResult =\n | { status: 'compatible' }\n | { status: 'untested'; detected: string; tested: string }\n | { status: 'unknown' };\n\n/**\n * Compare a detected Claude Code runtime version against the tested version.\n *\n * - `compatible`: major.minor matches the tested version\n * - `untested`: version detected but major.minor differs\n * - `unknown`: version could not be determined\n */\nexport function classifyClaudeCodeCompatibility(\n detected: string | undefined,\n tested: string = TESTED_CLAUDE_CODE_VERSION\n): ClaudeCodeCompatResult {\n if (!detected) return { status: 'unknown' };\n\n const detectedParts = detected.split('.');\n const testedParts = tested.split('.');\n\n if (detectedParts[0] === testedParts[0] && detectedParts[1] === testedParts[1]) {\n return { status: 'compatible' };\n }\n\n return { status: 'untested', detected, tested };\n}\n","import type { ConnectionState } from './personal-room-connection';\nimport type { CollabRoomClientMessage, CollabRoomServerMessage } from './schemas';\nimport { CollabRoomServerMessageSchema } from './schemas';\n\ninterface MinimalWebSocket {\n onopen: ((ev: unknown) => void) | null;\n onclose: ((ev: unknown) => void) | null;\n onerror: ((ev: unknown) => void) | null;\n onmessage: ((ev: { data: string }) => void) | null;\n send(data: string): void;\n close(): void;\n}\n\nexport interface CollabRoomConnectionConfig {\n url: string;\n WebSocketImpl?: new (url: string) => MinimalWebSocket;\n maxRetries?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n backoffMultiplier?: number;\n /** Called when the server closes the connection with code 1000 (\"Room expired\"). Do not reconnect. */\n onRoomExpired?: () => void;\n}\n\nexport class CollabRoomConnection {\n private state: ConnectionState = 'disconnected';\n private ws: MinimalWebSocket | null = null;\n private readonly messageHandlers = new Set<(msg: CollabRoomServerMessage) => void>();\n private readonly stateChangeHandlers = new Set<(state: ConnectionState) => void>();\n private readonly config: CollabRoomConnectionConfig;\n private retryCount = 0;\n private retryTimer: ReturnType<typeof setTimeout> | null = null;\n private pingTimer: ReturnType<typeof setTimeout> | null = null;\n private intentionalDisconnect = false;\n\n constructor(config: CollabRoomConnectionConfig) {\n this.config = config;\n }\n\n getState(): ConnectionState {\n return this.state;\n }\n\n connect(): void {\n this.intentionalDisconnect = false;\n\n if (this.retryTimer !== null) {\n clearTimeout(this.retryTimer);\n this.retryTimer = null;\n }\n\n if (this.ws) {\n this.stopPingTimer();\n this.ws.onopen = null;\n this.ws.onclose = null;\n this.ws.onerror = null;\n this.ws.onmessage = null;\n this.ws.close();\n this.ws = null;\n }\n\n const Impl = this.config.WebSocketImpl ?? (WebSocket as never);\n try {\n this.ws = new Impl(this.config.url);\n } catch {\n this.setState('error');\n this.reconnectWithBackoff();\n return;\n }\n this.setState('connecting');\n\n this.ws.onopen = () => {\n this.setState('connected');\n this.startPingTimer();\n };\n\n this.ws.onclose = (ev: unknown) => {\n this.stopPingTimer();\n if (this.state !== 'error' && this.state !== 'reconnecting') {\n this.setState('disconnected');\n }\n const code = extractCloseCode(ev);\n /** NOTE: 1000 = \"Room expired\" — the Durable Object TTL has elapsed. Stop reconnecting and notify the caller. */\n if (code === 1000) {\n this.config.onRoomExpired?.();\n return;\n }\n /** NOTE: 4001 = \"Replaced by new connection\" — a newer WebSocket for the same userId was accepted by the server. Do not reconnect; the replacement is already active. */\n if (!this.intentionalDisconnect && code !== 4001) {\n this.reconnectWithBackoff();\n }\n };\n\n this.ws.onerror = () => {\n this.stopPingTimer();\n this.setState('error');\n if (!this.intentionalDisconnect) {\n this.reconnectWithBackoff();\n }\n };\n\n this.ws.onmessage = (event: { data: string }) => {\n this.startPingTimer();\n\n if (event.data === 'pong') return;\n\n let raw: unknown;\n try {\n raw = JSON.parse(event.data);\n } catch {\n return;\n }\n\n const result = CollabRoomServerMessageSchema.safeParse(raw);\n if (!result.success) {\n // biome-ignore lint/suspicious/noConsole: intentional debug visibility for silent Zod drops that hid a critical share-link bug\n console.warn(\n '[CollabRoom] Dropped unrecognized server message:',\n JSON.stringify(raw),\n result.error.issues\n );\n return;\n }\n\n for (const handler of [...this.messageHandlers]) {\n handler(result.data);\n }\n };\n }\n\n send(msg: CollabRoomClientMessage): void {\n try {\n this.ws?.send(JSON.stringify(msg));\n } catch {\n /** WebSocket may be in CLOSING/CLOSED state */\n }\n }\n\n onMessage(handler: (msg: CollabRoomServerMessage) => void): () => void {\n this.messageHandlers.add(handler);\n return () => {\n this.messageHandlers.delete(handler);\n };\n }\n\n onStateChange(handler: (state: ConnectionState) => void): () => void {\n this.stateChangeHandlers.add(handler);\n return () => {\n this.stateChangeHandlers.delete(handler);\n };\n }\n\n reconnect(): void {\n this.intentionalDisconnect = false;\n if (this.retryTimer !== null) {\n clearTimeout(this.retryTimer);\n this.retryTimer = null;\n }\n this.retryCount = 0;\n this.connect();\n }\n\n disconnect(): void {\n this.intentionalDisconnect = true;\n this.stopPingTimer();\n\n if (this.retryTimer !== null) {\n clearTimeout(this.retryTimer);\n this.retryTimer = null;\n }\n\n this.retryCount = 0;\n\n if (this.ws) {\n this.ws.onopen = null;\n this.ws.onclose = null;\n this.ws.onerror = null;\n this.ws.onmessage = null;\n this.ws.close();\n this.ws = null;\n }\n this.setState('disconnected');\n }\n\n private startPingTimer(): void {\n this.stopPingTimer();\n this.schedulePing();\n }\n\n private stopPingTimer(): void {\n if (this.pingTimer !== null) {\n clearTimeout(this.pingTimer);\n this.pingTimer = null;\n }\n }\n\n private schedulePing(): void {\n const jitter = Math.floor(Math.random() * 25_000);\n const delay = 30_000 + jitter;\n this.pingTimer = setTimeout(() => {\n this.pingTimer = null;\n try {\n this.ws?.send('ping');\n } catch {\n /** WebSocket may be in CLOSING/CLOSED state */\n }\n this.schedulePing();\n }, delay);\n }\n\n private reconnectWithBackoff(): void {\n if (this.retryTimer !== null) return;\n\n const maxRetries = this.config.maxRetries;\n if (maxRetries === undefined || maxRetries === 0) {\n return;\n }\n\n if (maxRetries !== -1 && this.retryCount >= maxRetries) {\n return;\n }\n\n this.setState('reconnecting');\n\n if (this.intentionalDisconnect) return;\n\n const initialDelay = this.config.initialDelayMs ?? 1000;\n const maxDelay = this.config.maxDelayMs ?? 30000;\n const multiplier = this.config.backoffMultiplier ?? 2;\n const delay = Math.min(initialDelay * multiplier ** this.retryCount, maxDelay);\n\n this.retryCount++;\n\n this.retryTimer = setTimeout(() => {\n this.retryTimer = null;\n this.connect();\n }, delay);\n }\n\n private setState(newState: ConnectionState): void {\n this.state = newState;\n if (newState === 'connected') {\n this.retryCount = 0;\n }\n for (const handler of [...this.stateChangeHandlers]) {\n handler(newState);\n }\n }\n}\n\nfunction extractCloseCode(ev: unknown): number | undefined {\n if (typeof ev !== 'object' || ev === null || !('code' in ev)) return undefined;\n const code: unknown = ev.code;\n return typeof code === 'number' ? code : undefined;\n}\n","import type { PersonalRoomClientMessage, PersonalRoomServerMessage } from './schemas';\nimport { PersonalRoomServerMessageSchema } from './schemas';\n\nexport type ConnectionState =\n | 'connecting'\n | 'connected'\n | 'disconnected'\n | 'reconnecting'\n | 'error';\n\ninterface MinimalWebSocket {\n onopen: ((ev: unknown) => void) | null;\n onclose: ((ev: unknown) => void) | null;\n onerror: ((ev: unknown) => void) | null;\n onmessage: ((ev: { data: string }) => void) | null;\n send(data: string): void;\n close(): void;\n}\n\nexport interface PersonalRoomConnectionConfig {\n url: string;\n WebSocketImpl?: new (url: string) => MinimalWebSocket;\n maxRetries?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n backoffMultiplier?: number;\n}\n\nexport class PersonalRoomConnection {\n private state: ConnectionState = 'disconnected';\n private ws: MinimalWebSocket | null = null;\n private readonly messageHandlers = new Set<(msg: PersonalRoomServerMessage) => void>();\n private readonly stateChangeHandlers = new Set<(state: ConnectionState) => void>();\n private readonly config: PersonalRoomConnectionConfig;\n private retryCount = 0;\n private retryTimer: ReturnType<typeof setTimeout> | null = null;\n private pingTimer: ReturnType<typeof setTimeout> | null = null;\n private intentionalDisconnect = false;\n\n constructor(config: PersonalRoomConnectionConfig) {\n this.config = config;\n }\n\n getState(): ConnectionState {\n return this.state;\n }\n\n connect(): void {\n this.intentionalDisconnect = false;\n\n if (this.retryTimer !== null) {\n clearTimeout(this.retryTimer);\n this.retryTimer = null;\n }\n\n if (this.ws) {\n this.stopPingTimer();\n this.ws.onopen = null;\n this.ws.onclose = null;\n this.ws.onerror = null;\n this.ws.onmessage = null;\n this.ws.close();\n this.ws = null;\n }\n\n const Impl = this.config.WebSocketImpl ?? (WebSocket as never);\n try {\n this.ws = new Impl(this.config.url);\n } catch {\n this.setState('error');\n this.reconnectWithBackoff();\n return;\n }\n this.setState('connecting');\n\n this.ws.onopen = () => {\n this.setState('connected');\n this.startPingTimer();\n };\n\n this.ws.onclose = () => {\n this.stopPingTimer();\n if (this.state !== 'error' && this.state !== 'reconnecting') {\n this.setState('disconnected');\n }\n if (!this.intentionalDisconnect) {\n this.reconnectWithBackoff();\n }\n };\n\n this.ws.onerror = () => {\n this.stopPingTimer();\n this.setState('error');\n if (!this.intentionalDisconnect) {\n this.reconnectWithBackoff();\n }\n };\n\n this.ws.onmessage = (event: { data: string }) => {\n this.startPingTimer();\n\n if (event.data === 'pong') return;\n\n let raw: unknown;\n try {\n raw = JSON.parse(event.data);\n } catch {\n return;\n }\n\n const result = PersonalRoomServerMessageSchema.safeParse(raw);\n if (!result.success) {\n if (this.state === 'connected') {\n // biome-ignore lint/suspicious/noConsole: intentional debug visibility for silent Zod drops that hid a critical share-link bug\n console.warn(\n '[PersonalRoom] Dropped unrecognized server message:',\n JSON.stringify(raw),\n result.error.issues\n );\n }\n return;\n }\n\n for (const handler of [...this.messageHandlers]) {\n handler(result.data);\n }\n };\n }\n\n send(msg: PersonalRoomClientMessage): void {\n try {\n this.ws?.send(JSON.stringify(msg));\n } catch {\n /** WebSocket may be in CLOSING/CLOSED state */\n }\n }\n\n onMessage(handler: (msg: PersonalRoomServerMessage) => void): () => void {\n this.messageHandlers.add(handler);\n return () => {\n this.messageHandlers.delete(handler);\n };\n }\n\n onStateChange(handler: (state: ConnectionState) => void): () => void {\n this.stateChangeHandlers.add(handler);\n return () => {\n this.stateChangeHandlers.delete(handler);\n };\n }\n\n reconnect(): void {\n this.intentionalDisconnect = false;\n if (this.retryTimer !== null) {\n clearTimeout(this.retryTimer);\n this.retryTimer = null;\n }\n this.retryCount = 0;\n this.connect();\n }\n\n disconnect(): void {\n this.intentionalDisconnect = true;\n this.stopPingTimer();\n\n if (this.retryTimer !== null) {\n clearTimeout(this.retryTimer);\n this.retryTimer = null;\n }\n\n this.retryCount = 0;\n\n if (this.ws) {\n this.ws.onopen = null;\n this.ws.onclose = null;\n this.ws.onerror = null;\n this.ws.onmessage = null;\n this.ws.close();\n this.ws = null;\n }\n this.setState('disconnected');\n }\n\n private startPingTimer(): void {\n this.stopPingTimer();\n this.schedulePing();\n }\n\n private stopPingTimer(): void {\n if (this.pingTimer !== null) {\n clearTimeout(this.pingTimer);\n this.pingTimer = null;\n }\n }\n\n private schedulePing(): void {\n const jitter = Math.floor(Math.random() * 25_000);\n const delay = 30_000 + jitter;\n this.pingTimer = setTimeout(() => {\n this.pingTimer = null;\n try {\n this.ws?.send('ping');\n } catch {\n /** WebSocket may be in CLOSING/CLOSED state */\n }\n this.schedulePing();\n }, delay);\n }\n\n private reconnectWithBackoff(): void {\n if (this.retryTimer !== null) return;\n\n const maxRetries = this.config.maxRetries;\n if (maxRetries === undefined || maxRetries === 0) {\n return;\n }\n\n if (maxRetries !== -1 && this.retryCount >= maxRetries) {\n return;\n }\n\n this.setState('reconnecting');\n\n if (this.intentionalDisconnect) return;\n\n const initialDelay = this.config.initialDelayMs ?? 1000;\n const maxDelay = this.config.maxDelayMs ?? 30000;\n const multiplier = this.config.backoffMultiplier ?? 2;\n const delay = Math.min(initialDelay * multiplier ** this.retryCount, maxDelay);\n\n this.retryCount++;\n\n this.retryTimer = setTimeout(() => {\n this.retryTimer = null;\n this.connect();\n }, delay);\n }\n\n private setState(newState: ConnectionState): void {\n this.state = newState;\n if (newState === 'connected') {\n this.retryCount = 0;\n }\n for (const handler of [...this.stateChangeHandlers]) {\n handler(newState);\n }\n }\n}\n","/**\n * Monotonic protocol version for daemon↔browser compatibility.\n *\n * Bump ONLY on breaking changes to the communication protocol between\n * the daemon and browser (new/removed message types, changed ephemeral\n * schemas, etc.). Feature releases that don't break the protocol do\n * NOT bump this number.\n *\n * The browser hardcodes a minimum acceptable version. When a daemon\n * connects with a lower version, the browser shows a blocking update\n * modal.\n */\nexport const PROTOCOL_VERSION = 47;\n\n/**\n * Minimum protocol version the browser requires from daemons.\n * Daemons reporting a version below this (or no version at all)\n * trigger the \"update your daemon\" modal.\n *\n * Version history:\n * 32: Canvas publish stability — `projectRoot` / `packageName` on DetectedPort;\n * `canvasElementId` / `projectRoot` on request_publish previewPort target;\n * new `published_artifacts_state` broadcast.\n * 33: Task index pagination — `partial` / `nextCursor` / `nextCursorId` /\n * `totalCount` on `task_index_snapshot` and matching `activeOnly` / `limit` /\n * `sinceLastActivityAt` / `sinceLastId` on `request_task_index`. Bounds the\n * initial startup payload for users with large task stores and lets the\n * browser fetch older pages on demand.\n * 34: Sidebar redesign — task coloring / favorites / projects. New message\n * types: set_task_color, toggle_favorite_task, set_task_project,\n * create_project, rename_project, delete_project, reorder_projects\n * (browser→daemon); projects_snapshot, project_updated, project_deleted\n * (daemon→browser). Adds `projectId` to TaskRecord and `taskColors` /\n * `favoriteTasks` / `collapsedProjects` to UserSettingsRecord.\n * Additive: MIN_PROTOCOL_VERSION stays at 33 — pre-v34 daemons still\n * function, just without the new sidebar features.\n * 35: Browser-initiated cwd persistence — `set_task_cwd` control message\n * (browser → daemon) that writes `TaskRecord.cwd` and invokes the\n * existing `onCwdChanged` hook so worktree auto-switch selections\n * survive page refresh. Hard bumps MIN to 35: pre-v35 daemons don't\n * handle `set_task_cwd`, so the browser's optimistic auto-switch\n * would write UI state but not persist, silently re-introducing the\n * refresh-reset bug.\n * 36: Preview-pointer refactor — canvas `preview` elements become\n * pointer-only in the CRDT (`{ ownerUserId }`). Port / url /\n * projectRoot / proxyPort / initialPath move to a daemon-local\n * `PreviewStateStore` broadcast via a new `preview_elements_state`\n * control message. Hard bumps MIN to 36: pre-v36 daemons still write\n * port/projectRoot into the CRDT, so a v36 browser reading\n * `preview_elements_state` would show \"preview pending\" forever\n * against an older daemon. Graceful downgrade isn't possible.\n * 37: No wire-protocol change. Forces the update-modal for v3.3.0 daemons\n * so users pick up the v3.3.1 hotfix for the node-pty `spawn-helper`\n * permissions bug — node-pty 1.1.0 ships the PTY-spawn intermediate\n * with mode 0644 (no execute bit), so every terminal spawn on\n * macOS/Linux fails with an opaque \"posix_spawnp failed.\" v3.3.1 adds\n * a postinstall chmod to the daemon's package-npm.json. Bumping MIN\n * forces the prompt because graceful downgrade leaves a featured\n * surface (terminal panel) broken with no user-visible clue why.\n * 38: Linear plugin filter/sort/scope persistence — adds `linearViewPreferences`,\n * `linearScope`, `linearSelectedTeamId` to UserSettingsRecord. Additive:\n * MIN_PROTOCOL_VERSION stays at 37 — pre-v38 daemons just ignore the new\n * fields and the browser falls back to local defaults.\n * 39: Worktree state-machine refactor + start_from_linear protocol.\n * Replaces the worktree_progress/worktree_created/worktree_error\n * message triple with a single worktree_phase_changed snapshot\n * carrying full WorktreeState (per Invariant #2). Adds\n * start_from_linear (browser→daemon) and task_starting_from_linear\n * (daemon→browser) for the Linear plugin one-click ergonomics flow.\n * TaskRecord adds startupPhase, awaitingSetup, startedFromLinear\n * with Zod defaults — no imperative migration. MIN bumped because\n * pre-v39 daemons emit removed message types and post-v39 browsers\n * don't know how to handle them (and vice versa).\n * 40: Daemon-owns-templates refactor — new browser→daemon `apply_template_request`\n * message. Removes browser-side template mirroring into TodoEnrichmentStore.\n * Hard bumps MIN to 40: pre-v40 daemons don't handle `apply_template_request`,\n * so applying a template to an existing task would silently no-op.\n * 41: Notification system foundation — adds task-scoped notification\n * control-channel messages (`notification_snapshot`, `notification_added`,\n * `notification_updated`, `notification_resolved` daemon→browser plus\n * `notification_ack` browser→daemon) and a `notifications` field on\n * `TaskRecord`. Hard MIN bump: pre-v41 daemons can't classify the new\n * D→B messages through `collab-outbound-filter`'s exhaustive switch\n * and won't honour browser acks, so the bell badge / sidebar Needs\n * attention bucket would silently desync from daemon state.\n * 42: Unified comment experience — DiffHunkAnnotation extended with\n * provider/external/baseRef/baseLabel/syncStatus, new annotation_updated\n * control message for reanchor broadcasts, PRComment extended with\n * commit_id/threadId/isResolved/isOutdated for richer GitHub mapping,\n * new unresolve_thread PRAction. Pre-v42 daemons can't emit\n * annotation_updated, so a v42 browser waiting for reanchor broadcasts\n * on commit would never receive them. Hard bumps MIN: graceful\n * downgrade leaves the auto-promote-on-commit feature silently broken.\n * 43: On-demand per-task hydration — adds `request_task_state` (browser→daemon).\n * Daemon responds with the existing per-task messages\n * (`published_artifacts_state`, `preview_elements_state`, `annotation_snapshot`,\n * `thread_list`, `permission_request`/`permission_resolved`, `plan_detected`,\n * `turn_stats`) only for the requested taskId. Replaces the daemon's\n * at-attach iterate-all-tasks fan-out (the thundering herd at 552\n * tasks: ~1,656 control sends per attach, self-feeding via SCTP\n * backpressure → channel close → reconnect loop). Pre-v43 daemons\n * don't handle `request_task_state`, so a v43 browser would never\n * hydrate published artifacts / preview elements / pending permissions\n * and the canvas + permissions UI would render empty. Hard MIN bump\n * — graceful downgrade isn't possible.\n * 44: Favorites zombie fix — removes the deprecated browser→daemon\n * `toggle_pin_task` control message and the `pinned` field from\n * TaskRecord (TASK_STORE_VERSION 14→15). Favorites now live exclusively\n * in `UserSettingsRecord.favoriteTasks`. Hard MIN bump: pre-v44\n * browsers still call `togglePinTask` on pin/unpin, which a v44 daemon\n * would reject as an unknown control message — silently breaking the\n * star toggle. The unified favorites surface is on every browser at\n * v34+, so the upgrade modal is the right UX.\n * 45: MCP architecture rebuild — adds browser→daemon `request_mcp_toggle`\n * (coordinator-driven runtime toggle, replaces overloading\n * `update_settings.disabledMcpServers` for the same purpose), renames\n * `mcp_server_status` enum value `pending` → `connecting` (the new\n * per-server FSM in `apps/daemon/src/services/mcp/server-fsm.ts` uses\n * `connecting` and the protocol now mirrors that vocabulary), and\n * routes lifecycle through the new `McpCoordinator` (single source of\n * truth, owns transports, persistence-before-ack, single broadcast\n * per transition). Hard MIN bump for two reasons: (1) pre-v45 daemons\n * emit `pending` which v45 browsers no longer accept, and (2) pre-v45\n * browsers send toggle intent via `update_settings.disabledMcpServers`\n * which v45 daemons no longer act on at the toggle level (Phase 3\n * collapses the path through the coordinator). Graceful downgrade\n * isn't possible on either side without re-introducing the bugs the\n * rebuild closes.\n * 46: ReasoningEffort enum change — removed `'auto'` (meta-value that silently\n * omitted `--effort`), added `'none'` (explicit thinking-off, translated to\n * `applyFlagSettings({alwaysThinkingEnabled:false})`). The\n * `ReasoningCapabilitySchema` in `packages/session` uses `z.enum()`, so a\n * v45 daemon advertising `'auto'` fails Zod parse on a v46 browser and\n * vice versa. Hard bumps MIN to 46.\n * 47: Per-item model+effort carrier — adds `set_task_capabilities`\n * (browser→daemon) for per-structured-task-item capability overrides.\n * Schema additions: `model` / `reasoningEffort` on `StructuredTask` +\n * `TemplateItem`; `capabilitiesOverrides` on `TaskOverlay`. Additive on\n * the wire — pre-v47 daemons don't handle `set_task_capabilities` (the\n * browser badge edit affordance no-ops) but everything else still\n * functions. MIN_PROTOCOL_VERSION stays at 46: a graceful downgrade\n * leaves only the new badge-edit UI inert, no silent corruption.\n */\nexport const MIN_PROTOCOL_VERSION = 46;\n\nexport type CompatResult =\n | { compatible: true }\n | { compatible: false; reason: 'protocol' | 'prerelease-mismatch'; installCommand: string };\n\nfunction isPrerelease(version: string): boolean {\n return /-(nightly|rc)\\./.test(version);\n}\n\nexport function getInstallCommand(version?: string, channel?: 'latest' | 'next'): string {\n if (channel) {\n return `npm install -g @schoolai/shipyard@${channel}`;\n }\n const tag = version && isPrerelease(version) ? '@next' : '@latest';\n return `npm install -g @schoolai/shipyard${tag}`;\n}\n\nexport function classifyDaemonCompatibility(\n daemon: { protocolVersion?: number; npmVersion?: string },\n browser: {\n minProtocolVersion: number;\n expectedDaemonVersion?: string;\n channel?: 'latest' | 'next';\n }\n): CompatResult {\n const installCommand = getInstallCommand(\n browser.expectedDaemonVersion ?? daemon.npmVersion,\n browser.channel\n );\n\n if (\n daemon.npmVersion &&\n browser.expectedDaemonVersion &&\n isPrerelease(daemon.npmVersion) &&\n isPrerelease(browser.expectedDaemonVersion) &&\n daemon.npmVersion !== browser.expectedDaemonVersion\n ) {\n return {\n compatible: false,\n reason: 'prerelease-mismatch',\n installCommand,\n };\n }\n\n if ((daemon.protocolVersion ?? 0) < browser.minProtocolVersion) {\n return {\n compatible: false,\n reason: 'protocol',\n installCommand,\n };\n }\n\n return { compatible: true };\n}\n","/**\n * Shared constants and schemas for the Shipyard publish feature.\n *\n * Lives in `@shipyard/session` (not `@shipyard/loro-schema`) because it must\n * be consumable from Cloudflare Workers (session-server, publish-worker) where\n * loro-crdt's WASM barrel cannot load in vitest-pool-workers. The session\n * package is Worker-safe by construction.\n *\n * `@shipyard/loro-schema` re-exports these for backwards compatibility with\n * daemon/browser imports that expect the schema to own the shape.\n *\n * @module publish-constants\n */\n\nimport { z } from 'zod';\n\n/**\n * The set of supported publish kinds. Mirrors the D1 CHECK constraint on\n * published_previews.kind.\n */\nexport const PUBLISHED_PREVIEW_KINDS = [\n 'html',\n 'mermaid',\n 'svg',\n 'image',\n 'static-site',\n 'dom-snapshot',\n] as const;\n\nexport type PublishedPreviewKind = (typeof PUBLISHED_PREVIEW_KINDS)[number];\n\nexport const PublishedPreviewKindSchema = z.enum(PUBLISHED_PREVIEW_KINDS);\n\n/**\n * TTL choices exposed to users. Mapped to ms via {@link ttlToMilliseconds}.\n */\nexport const PUBLISH_TTL_CHOICES = ['24h', '7d', '30d'] as const;\nexport type PublishTtl = (typeof PUBLISH_TTL_CHOICES)[number];\n\nexport const PublishTtlSchema = z.enum(PUBLISH_TTL_CHOICES).default('24h');\n\n/**\n * Convert a TTL choice to milliseconds.\n */\nexport function ttlToMilliseconds(ttl: PublishTtl): number {\n switch (ttl) {\n case '24h':\n return 24 * 60 * 60 * 1000;\n case '7d':\n return 7 * 24 * 60 * 60 * 1000;\n case '30d':\n return 30 * 24 * 60 * 60 * 1000;\n }\n}\n\n/** Max bytes for a single-file publish (html, mermaid, svg, image, dom-snapshot). */\nexport const MAX_SINGLE_FILE_BYTES = 50 * 1024 * 1024;\n/** Max aggregate bytes across a multi-file build (static-site). */\nexport const MAX_BUILD_TOTAL_BYTES = 200 * 1024 * 1024;\n/** Max bytes for any single file within a build. */\nexport const MAX_BUILD_PER_FILE_BYTES = 10 * 1024 * 1024;\n/** Max number of files in a build. */\nexport const MAX_BUILD_FILE_COUNT = 2000;\n\n/** Per-user publish rate limit (publishes per hour). */\nexport const PUBLISH_RATE_LIMIT_PER_HOUR = 20;\n/** Per-user total active-publish storage quota (bytes). */\nexport const PUBLISH_QUOTA_TOTAL_BYTES = 500 * 1024 * 1024;\n\n/**\n * POST /publish request fields.\n *\n * Note: the endpoint accepts multipart/form-data, not JSON. This schema\n * describes the string fields only; files are transported as `files[]`\n * entries and validated separately against size/count limits.\n */\nexport const PublishCreateRequestSchema = z.object({\n kind: PublishedPreviewKindSchema,\n ttl: PublishTtlSchema,\n entryPath: z.string().min(1).max(512),\n title: z.string().max(200).optional(),\n /** \"1\" to enable SPA fallback (index.html served for unknown paths). */\n spaFallback: z.enum(['0', '1']).default('0'),\n});\nexport type PublishCreateRequest = z.infer<typeof PublishCreateRequestSchema>;\n\n/**\n * POST /publish response body.\n *\n * Discriminated on `ok` so consumers cannot silently read `undefined` from\n * `id`/`url`/`expiresAt` on failure (previously all three were required on a\n * single flat object, which TypeScript happily parsed but which didn't survive\n * the HTTP error paths — e.g. 4xx bodies with `{ error, message }`). The\n * discriminant forces callers to narrow before reading the success fields.\n *\n * Session-server routes emit `ok: true` alongside the data on 2xx and\n * `ok: false` alongside `error` on 4xx — see routes/publish.ts.\n */\nexport const PublishCreateResponseSchema = z.discriminatedUnion('ok', [\n z.object({\n ok: z.literal(true),\n id: z.string().min(1),\n url: z.string().url(),\n expiresAt: z.number().int(),\n }),\n z.object({\n ok: z.literal(false),\n error: z.string(),\n }),\n]);\nexport type PublishCreateResponse = z.infer<typeof PublishCreateResponseSchema>;\n\n/**\n * DELETE /publish/:id response body.\n */\nexport const PublishDeleteResponseSchema = z.object({\n ok: z.literal(true),\n});\nexport type PublishDeleteResponse = z.infer<typeof PublishDeleteResponseSchema>;\n\n/**\n * Row shape for GET /publish/mine.\n */\nexport const PublishListItemSchema = z.object({\n id: z.string().min(1),\n url: z.string().url(),\n kind: z.string(),\n title: z.string().nullable(),\n createdAt: z.number().int(),\n expiresAt: z.number().int(),\n sizeBytes: z.number().int().nonnegative(),\n});\nexport type PublishListItem = z.infer<typeof PublishListItemSchema>;\n\n/**\n * GET /publish/mine response body.\n */\nexport const PublishListResponseSchema = z.object({\n items: z.array(PublishListItemSchema),\n});\nexport type PublishListResponse = z.infer<typeof PublishListResponseSchema>;\n"],"mappings":";;;;;;AAsBO,IAAM,sBAAsB;AAc5B,IAAM,sBAAsB,iBAAE,OAAO;AAAA,EAC1C,OAAO,iBAAE,OAAO;AAAA,EAChB,SAAS,iBAAE,OAAO;AACpB,CAAC;AAOM,IAAM,gCAAgC,oBAAoB,OAAO;AAAA,EACtE,SAAS,iBACN;AAAA,IACC,iBAAE,OAAO;AAAA,MACP,MAAM,iBAAE,MAAM,iBAAE,MAAM,CAAC,iBAAE,OAAO,GAAG,iBAAE,OAAO,CAAC,CAAC,CAAC;AAAA,MAC/C,SAAS,iBAAE,OAAO;AAAA,MAClB,MAAM,iBAAE,OAAO,EAAE,SAAS;AAAA,IAC5B,CAAC;AAAA,EACH,EACC,SAAS;AACd,CAAC;AAOM,IAAM,yBAAyB,oBAAoB,OAAO;AAAA,EAC/D,WAAW,iBAAE,MAAM,iBAAE,OAAO,CAAC;AAC/B,CAAC;AASM,IAAM,uBAAuB,iBAAE,OAAO;AAAA,EAC3C,QAAQ,iBAAE,QAAQ,IAAI;AAAA,EACtB,SAAS,iBAAE,QAAQ,oBAAoB;AAAA,EACvC,aAAa,iBAAE,KAAK,CAAC,eAAe,YAAY,CAAC;AACnD,CAAC;AASM,IAAM,kCAAkC,iBAAE,OAAO;AAAA;AAAA,EAEtD,MAAM,iBAAE,OAAO,EAAE,IAAI,GAAG,kBAAkB;AAAA;AAAA,EAE1C,cAAc,iBAAE,OAAO,EAAE,IAAI,kCAAkC;AACjE,CAAC;AAOM,IAAM,kBAAkB,iBAAE,OAAO;AAAA;AAAA,EAEtC,IAAI,iBAAE,OAAO;AAAA;AAAA,EAEb,aAAa,iBAAE,OAAO;AAAA;AAAA,EAEtB,WAAW,iBAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAE/B,WAAW,iBAAE,MAAM,iBAAE,OAAO,CAAC;AAC/B,CAAC;AASM,IAAM,mCAAmC,iBAAE,OAAO;AAAA;AAAA,EAEvD,OAAO,iBAAE,OAAO;AAAA;AAAA,EAEhB,MAAM;AAAA;AAAA,EAEN,mBAAmB,iBAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAEvC,oBAAoB,iBAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAExC,WAAW,iBAAE,QAAQ,EAAE,SAAS;AAClC,CAAC;AASM,IAAM,iCAAiC,iBAAE,OAAO;AAAA;AAAA,EAErD,cAAc,iBAAE,OAAO,EAAE,IAAI,GAAG,0BAA0B;AAC5D,CAAC;AAOM,IAAM,kCAAkC,iBAAE,OAAO;AAAA;AAAA,EAEtD,mBAAmB,iBAAE,OAAO;AAAA;AAAA,EAE5B,oBAAoB,iBAAE,OAAO;AAC/B,CAAC;AASM,IAAM,2BAA2B,iBAAE,mBAAmB,SAAS;AAAA,EACpE,iBAAE,OAAO,EAAE,OAAO,iBAAE,QAAQ,IAAI,GAAG,MAAM,gBAAgB,CAAC;AAAA,EAC1D,iBAAE,OAAO;AAAA,IACP,OAAO,iBAAE,QAAQ,KAAK;AAAA,IACtB,QAAQ,iBAAE,KAAK,CAAC,iBAAiB,gBAAgB,CAAC;AAAA,EACpD,CAAC;AACH,CAAC;AAQM,IAAM,wBAAwB,iBAAE,KAAK;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAOM,IAAM,yBAAyB,sBAAsB,QAAQ;AAAA,EAClE;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAQM,IAAM,4BAA4B,iBAAE,OAAO;AAAA;AAAA,EAEhD,QAAQ,iBAAE,OAAO,EAAE,IAAI,GAAG,oBAAoB;AAAA;AAAA,EAE9C,kBAAkB,iBAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,KAAK,EAAE,QAAQ,EAAE;AAAA;AAAA,EAEzD,MAAM,uBAAuB,SAAS;AACxC,CAAC;AASM,IAAM,6BAA6B,iBAAE,OAAO;AAAA;AAAA,EAEjD,KAAK,iBAAE,OAAO,EAAE,IAAI;AAAA;AAAA,EAEpB,QAAQ,iBAAE,OAAO;AAAA;AAAA,EAEjB,WAAW,iBAAE,OAAO;AACtB,CAAC;AAYM,IAAM,wBAAwB,iBAAE,mBAAmB,SAAS;AAAA,EACjE,oBAAoB,OAAO;AAAA,IACzB,OAAO,iBAAE,QAAQ,kBAAkB;AAAA,EACrC,CAAC;AAAA,EACD,oBAAoB,OAAO;AAAA,IACzB,OAAO,iBAAE,QAAQ,eAAe;AAAA,EAClC,CAAC;AAAA,EACD,oBAAoB,OAAO;AAAA,IACzB,OAAO,iBAAE,QAAQ,eAAe;AAAA,EAClC,CAAC;AAAA,EACD,oBAAoB,OAAO;AAAA,IACzB,OAAO,iBAAE,QAAQ,WAAW;AAAA,EAC9B,CAAC;AACH,CAAC;AAYM,IAAM,sBAAsB,iBAAE,mBAAmB,SAAS;AAAA,EAC/D,oBAAoB,OAAO;AAAA,IACzB,OAAO,iBAAE,QAAQ,kBAAkB;AAAA,EACrC,CAAC;AAAA,EACD,oBAAoB,OAAO;AAAA,IACzB,OAAO,iBAAE,QAAQ,eAAe;AAAA,EAClC,CAAC;AAAA,EACD,oBAAoB,OAAO;AAAA,IACzB,OAAO,iBAAE,QAAQ,eAAe;AAAA,EAClC,CAAC;AAAA,EACD,oBAAoB,OAAO;AAAA,IACzB,OAAO,iBAAE,QAAQ,WAAW;AAAA,EAC9B,CAAC;AAAA,EACD,oBAAoB,OAAO;AAAA,IACzB,OAAO,iBAAE,QAAQ,SAAS;AAAA,EAC5B,CAAC;AACH,CAAC;AASM,IAAM,0BAA0B,iBAAE,OAAO;AAAA;AAAA,EAE9C,KAAK,iBAAE,OAAO;AAAA;AAAA,EAEd,aAAa,iBAAE,OAAO;AAAA;AAAA,EAEtB,WAAW,iBAAE,MAAM,iBAAE,OAAO,CAAC;AAAA,EAC7B,KAAK,iBAAE,OAAO;AAAA,EACd,KAAK,iBAAE,OAAO;AAAA;AAAA,EAEd,OAAO,iBAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAE3B,WAAW,iBAAE,OAAO,EAAE,SAAS;AACjC,CAAC;AASM,IAAM,4BAA4B,iBAAE,OAAO;AAAA;AAAA,EAEhD,QAAQ,iBAAE,OAAO;AAAA;AAAA,EAEjB,QAAQ,iBAAE,OAAO;AAAA;AAAA,EAEjB,WAAW,iBAAE,OAAO;AAAA;AAAA,EAEpB,KAAK,iBAAE,OAAO;AAAA;AAAA,EAEd,MAAM,uBAAuB,SAAS;AAAA;AAAA,EAEtC,YAAY,iBAAE,OAAO,EAAE,SAAS;AAClC,CAAC;AAWM,IAAM,4BAA4B,iBACtC,OAAO;AAAA,EACN,SAAS,iBAAE,MAAM,iBAAE,KAAK,CAAC,QAAQ,OAAO,UAAU,QAAQ,SAAS,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC;AAAA,EACjF,eAAe,iBAAE,KAAK,CAAC,QAAQ,OAAO,UAAU,QAAQ,SAAS,KAAK,CAAC;AACzE,CAAC,EACA,OAAO,CAAC,SAAS,KAAK,QAAQ,SAAS,KAAK,aAAa,GAAG;AAAA,EAC3D,SAAS;AACX,CAAC;AAOI,IAAM,kBAAkB,iBAAE,OAAO;AAAA,EACtC,IAAI,iBAAE,OAAO;AAAA,EACb,MAAM,iBAAE,OAAO;AAAA,EACf,UAAU,iBAAE,OAAO;AAAA,EACnB,aAAa,iBAAE,OAAO,EAAE,SAAS;AAAA,EACjC,WAAW,0BAA0B,SAAS;AAAA,EAC9C,kBAAkB,iBAAE,QAAQ,EAAE,SAAS;AACzC,CAAC;AAOM,IAAM,oBAAoB,iBAAE,OAAO;AAAA,EACxC,MAAM,iBAAE,OAAO;AAAA,EACf,MAAM,iBAAE,OAAO;AAAA,EACf,QAAQ,iBAAE,OAAO;AAAA,EACjB,QAAQ,iBAAE,OAAO,EAAE,SAAS;AAC9B,CAAC;AAOM,IAAM,uBAAuB,iBAAE,KAAK,CAAC,WAAW,gBAAgB,QAAQ,UAAU,MAAM,CAAC;AAOhG,IAAM,0BAA0B,iBAAE,KAAK;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,IAAM,4BAA4B,iBAAE,OAAO;AAAA,EAChD,QAAQ,iBAAE,KAAK,CAAC,iBAAiB,mBAAmB,SAAS,CAAC;AAAA,EAC9D,QAAQ;AAAA,EACR,OAAO,iBAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,SAAS,iBAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,kBAAkB,iBAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACjD,aAAa,iBAAE,OAAO,EAAE,SAAS;AAAA,EACjC,cAAc,iBACX,OAAO;AAAA,IACN,UAAU;AAAA,IACV,WAAW;AAAA,IACX,QAAQ,iBAAE,OAAO;AAAA,EACnB,CAAC,EACA,SAAS;AACd,CAAC;AAIM,IAAM,4BAA4B,iBAAE,KAAK,CAAC,iBAAiB,mBAAmB,SAAS,CAAC;AAGxF,IAAM,wBAAwB,iBAAE,KAAK;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGD,IAAM,mBAAmB,CAAC,SAAS,QAAQ,KAAK;AACzC,IAAM,sBAAsB,iBAAE,KAAK,gBAAgB;AAGnD,IAAM,uBAAuB,iBAAE,OAAO;AAAA,EAC3C,UAAU,iBAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,cAAc,iBAAE,OAAO,EAAE,SAAS;AACpC,CAAC;AAEM,IAAM,sBAAsB,iBAAE,OAAO;AAAA,EAC1C,MAAM,iBAAE,OAAO;AAAA,EACf,MAAM,oBAAoB,QAAQ,OAAO;AAAA,EACzC,SAAS,iBAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,MAAM,iBAAE,MAAM,iBAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACnC,KAAK,iBAAE,OAAO,iBAAE,OAAO,GAAG,iBAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EAC/C,KAAK,iBAAE,OAAO,EAAE,SAAS;AAAA,EACzB,SAAS,iBAAE,OAAO,iBAAE,OAAO,GAAG,iBAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACnD,OAAO,qBAAqB,SAAS;AAAA,EACrC,SAAS,iBAAE,QAAQ;AAAA,EACnB,QAAQ;AAAA,EACR,YAAY;AACd,CAAC;AAGM,IAAM,kBAAkB,iBAAE,OAAO;AAAA,EACtC,MAAM,iBAAE,OAAO;AAAA,EACf,aAAa,iBAAE,OAAO;AACxB,CAAC;AAMM,IAAM,8BAA8B,iBAAE,OAAO;AAAA,EAClD,MAAM,iBAAE,OAAO;AAAA,EACf,aAAa,iBAAE,OAAO;AAAA,EACtB,QAAQ,iBAAE,OAAO;AAAA,EACjB,aAAa,iBAAE,OAAO;AAAA,EACtB,cAAc,iBAAE,OAAO,EAAE,SAAS;AAAA,EAClC,WAAW,iBAAE,QAAQ;AAAA,EACrB,SAAS,iBAAE,QAAQ;AAAA,EACnB,SAAS,iBAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,YAAY,iBAAE,QAAQ;AACxB,CAAC;AAGM,IAAM,wBAAwB,iBAAE,OAAO;AAAA,EAC5C,IAAI,iBAAE,QAAQ,aAAa;AAAA,EAC3B,MAAM,iBAAE,QAAQ,aAAa;AAAA,EAC7B,SAAS,iBAAE,OAAO,EAAE,SAAS;AAC/B,CAAC;AAEM,IAAM,uBAAuB,iBAAE,mBAAmB,MAAM,CAAC,qBAAqB,CAAC;AAG/E,IAAM,4BAA4B,iBAAE,OAAO;AAAA,EAChD,QAAQ,iBAAE,MAAM,eAAe;AAAA,EAC/B,cAAc,iBAAE,MAAM,iBAAiB;AAAA,EACvC,iBAAiB,iBAAE,MAAM,oBAAoB;AAAA,EAC7C,SAAS,iBAAE,OAAO;AAAA,EAClB,eAAe,0BAA0B,SAAS;AAAA,EAClD,YAAY,iBAAE,MAAM,mBAAmB;AAAA,EACvC,QAAQ,iBAAE,MAAM,eAAe;AAAA,EAC/B,oBAAoB,iBAAE,MAAM,2BAA2B;AAAA,EACvD,iBAAiB,iBAAE,QAAQ,EAAE,SAAS;AAAA,EACtC,iBAAiB,iBAAE,MAAM,oBAAoB;AAC/C,CAAC;AAmBM,IAAM,iCAAiC,iBAAE,OAAO;AAAA,EACrD,MAAM,iBAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,KAAK;AAAA,EACvC,OAAO,iBAAE,OAAO,EAAE,IAAI,EAAE;AAC1B,CAAC;AAIM,IAAM,sBAAsB,iBAAE,OAAO;AAAA,EAC1C,MAAM,iBAAE,QAAQ,gBAAgB;AAAA,EAChC,SAAS,iBAAE,OAAO;AAAA,EAClB,WAAW,iBAAE,OAAO;AAAA,EACpB,aAAa,iBAAE,OAAO;AAAA,EACtB,WAAW,iBAAE,OAAO;AAAA,EACpB,iBAAiB,iBAAE,OAAO,EAAE,SAAS;AAAA,EACrC,YAAY,iBAAE,OAAO,EAAE,SAAS;AAAA,EAChC,aAAa,+BAA+B,SAAS;AACvD,CAAC;AAKM,IAAM,wBAAwB,iBAAE,OAAO;AAAA,EAC5C,MAAM,iBAAE,QAAQ,kBAAkB;AAAA,EAClC,SAAS,iBAAE,OAAO;AACpB,CAAC;AAKM,IAAM,oBAAoB,iBAAE,OAAO;AAAA,EACxC,MAAM,iBAAE,QAAQ,cAAc;AAAA,EAC9B,SAAS,iBAAE,OAAO;AAAA,EAClB,QAAQ,iBAAE,KAAK,CAAC,QAAQ,WAAW,OAAO,CAAC;AAAA,EAC3C,cAAc,iBAAE,OAAO,EAAE,SAAS;AACpC,CAAC;AAeM,IAAM,oBAAoB,iBAAE,OAAO;AAAA,EACxC,MAAM,iBAAE,QAAQ,cAAc;AAAA,EAC9B,iBAAiB,iBAAE,OAAO;AAAA,EAC1B,eAAe,iBAAE,OAAO,EAAE,SAAS;AAAA,EACnC,cAAc,iBAAE,OAAO;AAAA,EACvB,OAAO,iBAAE,QAAQ;AAAA,EACjB,WAAW,iBAAE,OAAO,EAAE,SAAS;AACjC,CAAC;AAWM,IAAM,qBAAqB,iBAAE,OAAO;AAAA,EACzC,MAAM,iBAAE,QAAQ,eAAe;AAAA,EAC/B,iBAAiB,iBAAE,OAAO;AAAA,EAC1B,eAAe,iBAAE,OAAO,EAAE,SAAS;AAAA,EACnC,cAAc,iBAAE,OAAO;AAAA,EACvB,QAAQ,iBAAE,QAAQ;AAAA,EAClB,WAAW,iBAAE,OAAO,EAAE,SAAS;AACjC,CAAC;AAYM,IAAM,kBAAkB,iBAAE,OAAO;AAAA,EACtC,MAAM,iBAAE,QAAQ,YAAY;AAAA,EAC5B,iBAAiB,iBAAE,OAAO;AAAA,EAC1B,eAAe,iBAAE,OAAO,EAAE,SAAS;AAAA,EACnC,cAAc,iBAAE,OAAO;AAAA,EACvB,WAAW,iBAAE,QAAQ;AACvB,CAAC;AAKM,IAAM,kBAAkB,iBAAE,OAAO;AAAA,EACtC,MAAM,iBAAE,MAAM,CAAC,iBAAE,OAAO,GAAG,iBAAE,MAAM,iBAAE,OAAO,CAAC,CAAC,CAAC;AAAA,EAC/C,UAAU,iBAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,YAAY,iBAAE,OAAO,EAAE,SAAS;AAClC,CAAC;AASM,IAAM,sBAAmC,CAAC,EAAE,MAAM,gCAAgC,CAAC;AAOnF,IAAM,mBAAmB,iBAAE,OAAO;AAAA,EACvC,MAAM,iBAAE,QAAQ,aAAa;AAAA,EAC7B,YAAY,iBAAE,MAAM,eAAe;AACrC,CAAC;AAKM,IAAM,qBAAqB,iBAAE,OAAO;AAAA,EACzC,MAAM,iBAAE,QAAQ,OAAO;AAAA,EACvB,MAAM,iBAAE,OAAO;AAAA,EACf,SAAS,iBAAE,OAAO;AAAA,EAClB,WAAW,iBAAE,OAAO,EAAE,SAAS;AACjC,CAAC;AAKM,IAAM,qBAAqB,iBAAE,OAAO;AAAA,EACzC,qBAAqB,iBAAE,OAAO,EAAE,SAAS;AAC3C,CAAC;AASM,IAAM,4BAA4B,iBAAE,OAAO;AAAA,EAChD,MAAM,iBAAE,QAAQ,uBAAuB;AAAA,EACvC,iBAAiB,iBAAE,OAAO;AAAA,EAC1B,eAAe,iBAAE,OAAO,EAAE,SAAS;AAAA,EACnC,gBAAgB,iBAAE,OAAO;AAC3B,CAAC;AAcM,IAAM,2BAA2B,iBAAE,OAAO;AAAA,EAC/C,MAAM,iBAAE,QAAQ,sBAAsB;AAAA,EACtC,eAAe,iBAAE,OAAO,EAAE,SAAS;AAAA,EACnC,QAAQ,iBAAE,KAAK;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAAA,EACD,OAAO,iBAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,eAAe,iBAAE,OAAO,EAAE,SAAS;AAAA,EACnC,iBAAiB,iBAAE,OAAO,EAAE,SAAS;AACvC,CAAC;AAOM,IAAM,kCAAkC,iBAAE,mBAAmB,QAAQ;AAAA,EAC1E;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAOM,IAAM,sBAAsB,iBAAE,OAAO;AAAA,EAC1C,MAAM,iBAAE,QAAQ,eAAe;AAAA,EAC/B,QAAQ,iBAAE,OAAO;AAAA,EACjB,UAAU,iBAAE,OAAO;AACrB,CAAC;AAMM,IAAM,kBAAkB,iBAAE,OAAO;AAAA,EACtC,SAAS,iBAAE,OAAO;AAAA,EAClB,WAAW,iBAAE,OAAO;AAAA,EACpB,aAAa,iBAAE,OAAO;AAAA,EACtB,WAAW,iBAAE,OAAO;AAAA,EACpB,QAAQ,iBAAE,KAAK,CAAC,QAAQ,WAAW,OAAO,CAAC;AAAA,EAC3C,cAAc,iBAAE,OAAO,EAAE,SAAS;AAAA,EAClC,iBAAiB,iBAAE,OAAO,EAAE,SAAS;AAAA,EACrC,YAAY,iBAAE,OAAO,EAAE,SAAS;AAAA,EAChC,aAAa,+BAA+B,SAAS;AACvD,CAAC;AAOM,IAAM,mBAAmB,iBAAE,OAAO;AAAA,EACvC,MAAM,iBAAE,QAAQ,aAAa;AAAA,EAC7B,QAAQ,iBAAE,MAAM,eAAe;AAAA,EAC/B,qBAAqB,iBAAE,QAAQ,EAAE,SAAS;AAC5C,CAAC;AAKM,IAAM,oBAAoB,iBAAE,OAAO;AAAA,EACxC,MAAM,iBAAE,QAAQ,cAAc;AAAA,EAC9B,OAAO;AACT,CAAC;AAKM,IAAM,kBAAkB,iBAAE,OAAO;AAAA,EACtC,MAAM,iBAAE,QAAQ,YAAY;AAAA,EAC5B,SAAS,iBAAE,OAAO;AACpB,CAAC;AAKM,IAAM,2BAA2B,iBAAE,OAAO;AAAA,EAC/C,MAAM,iBAAE,QAAQ,sBAAsB;AAAA,EACtC,SAAS,iBAAE,OAAO;AAAA,EAClB,QAAQ,iBAAE,KAAK,CAAC,QAAQ,WAAW,OAAO,CAAC;AAAA,EAC3C,cAAc,iBAAE,OAAO,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQlC,aAAa,+BAA+B,SAAS;AACvD,CAAC;AAMM,IAAM,qBAAqB,iBAAE,OAAO;AAAA,EACzC,MAAM,iBAAE,QAAQ,eAAe;AAAA,EAC/B,QAAQ,iBAAE,OAAO;AAAA,EACjB,OAAO,iBAAE,OAAO;AAAA,EAChB,SAAS,iBAAE,OAAO,iBAAE,OAAO,GAAG,iBAAE,QAAQ,CAAC;AAAA,EACzC,WAAW,iBAAE,OAAO;AACtB,CAAC;AAOM,IAAM,kCAAkC,iBAAE,mBAAmB,QAAQ;AAAA,EAC1E;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAaM,IAAM,0BAA0B,iBAAE,OAAO;AAAA,EAC9C,MAAM,iBAAE,QAAQ,cAAc;AAAA,EAC9B,cAAc,iBAAE,OAAO;AAAA,EACvB,YAAY,iBAAE,OAAO,EAAE,SAAS;AAAA,EAChC,cAAc,iBAAE,OAAO;AAAA,EACvB,OAAO,iBAAE,QAAQ;AACnB,CAAC;AAQM,IAAM,2BAA2B,iBAAE,OAAO;AAAA,EAC/C,MAAM,iBAAE,QAAQ,eAAe;AAAA,EAC/B,cAAc,iBAAE,OAAO;AAAA,EACvB,YAAY,iBAAE,OAAO,EAAE,SAAS;AAAA,EAChC,cAAc,iBAAE,OAAO;AAAA,EACvB,QAAQ,iBAAE,QAAQ;AACpB,CAAC;AASM,IAAM,wBAAwB,iBAAE,OAAO;AAAA,EAC5C,MAAM,iBAAE,QAAQ,YAAY;AAAA,EAC5B,cAAc,iBAAE,OAAO;AAAA,EACvB,YAAY,iBAAE,OAAO,EAAE,SAAS;AAAA,EAChC,cAAc,iBAAE,OAAO;AAAA,EACvB,WAAW,iBAAE,QAAQ;AACvB,CAAC;AAKM,IAAM,gCAAgC,iBAAE,mBAAmB,QAAQ;AAAA,EACxE;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAeM,IAAM,oBAAoB,iBAAE,OAAO;AAAA,EACxC,QAAQ,iBAAE,OAAO;AAAA,EACjB,UAAU,iBAAE,OAAO;AAAA,EACnB,WAAW,iBAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC1C,MAAM;AAAA,EACN,cAAc,iBAAE,OAAO;AACzB,CAAC;AAOM,IAAM,4BAA4B,iBAAE,OAAO;AAAA,EAChD,MAAM,iBAAE,QAAQ,eAAe;AAAA,EAC/B,QAAQ,iBAAE,OAAO;AAAA,EACjB,UAAU,iBAAE,OAAO;AAAA,EACnB,QAAQ,iBAAE,OAAO;AACnB,CAAC;AAKM,IAAM,yBAAyB,iBAAE,OAAO;AAAA,EAC7C,MAAM,iBAAE,QAAQ,mBAAmB;AAAA,EACnC,cAAc,iBAAE,MAAM,iBAAiB;AACzC,CAAC;AAKM,IAAM,0BAA0B,iBAAE,OAAO;AAAA,EAC9C,MAAM,iBAAE,QAAQ,oBAAoB;AAAA,EACpC,aAAa;AACf,CAAC;AAYM,IAAM,wBAAwB,iBAAE,OAAO;AAAA,EAC5C,MAAM,iBAAE,QAAQ,kBAAkB;AAAA,EAClC,QAAQ,iBAAE,OAAO;AAAA,EACjB,cAAc,iBAAE,OAAO;AACzB,CAAC;AAKM,IAAM,gCAAgC,iBAAE,mBAAmB,QAAQ;AAAA,EACxE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAOM,IAAM,wBAAwB,iBAAE,KAAK,CAAC,OAAO,WAAW,YAAY,QAAQ,CAAC;AAM7E,IAAM,iCAAiC,iBAAE,OAAO;AAAA,EACrD,MAAM;AAAA,EACN,OAAO,iBAAE,OAAO,EAAE,IAAI,GAAG,mBAAmB,EAAE,IAAI,KAAK,kCAAkC;AAAA,EACzF,aAAa,iBAAE,OAAO,EAAE,IAAI,GAAK,EAAE,SAAS;AAAA,EAC5C,MAAM,iBAAE,OAAO,EAAE,IAAI,GAAK,EAAE,SAAS;AAAA,EACrC,SAAS,iBACN,OAAO;AAAA,IACN,KAAK,iBAAE,OAAO,EAAE,SAAS;AAAA,IACzB,QAAQ,iBAAE,OAAO,EAAE,SAAS;AAAA,IAC5B,WAAW,iBAAE,OAAO,EAAE,SAAS;AAAA,IAC/B,WAAW,iBAAE,OAAO,EAAE,SAAS;AAAA,EACjC,CAAC,EACA,SAAS;AACd,CAAC;AAOM,IAAM,kCAAkC,iBAAE,OAAO;AAAA,EACtD,UAAU,iBAAE,OAAO;AAAA,EACnB,aAAa,iBAAE,OAAO;AACxB,CAAC;AAUM,IAAM,kCAAkC,iBAAE,OAAO;AAAA;AAAA,EAEtD,MAAM,iBAAE,OAAO,EAAE,IAAI,GAAG,kBAAkB;AAAA;AAAA,EAE1C,cAAc,iBAAE,OAAO,EAAE,IAAI,kCAAkC;AACjE,CAAC;AASM,IAAM,mCAAmC,iBAAE,OAAO;AAAA;AAAA,EAEvD,mBAAmB,iBAAE,OAAO;AAAA;AAAA,EAE5B,WAAW,iBAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAE/B,YAAY,iBAAE,OAAO;AAAA,IACnB,IAAI,iBAAE,OAAO;AAAA,IACb,MAAM,iBAAE,OAAO,EAAE,SAAS;AAAA,IAC1B,OAAO,iBAAE,OAAO,EAAE,SAAS;AAAA,IAC3B,WAAW,iBAAE,OAAO,EAAE,SAAS;AAAA,EACjC,CAAC;AACH,CAAC;AAKM,IAAM,4BAA4B,iBAAE,OAAO;AAAA,EAChD,YAAY,iBAAE,OAAO;AAAA,EACrB,UAAU,iBAAE,OAAO;AAAA,EACnB,iBAAiB,iBAAE,OAAO,EAAE,IAAI;AAAA,EAChC,WAAW,iBAAE,OAAO;AAAA,EACpB,UAAU,iBAAE,OAAO;AACrB,CAAC;AAIM,IAAM,0BAA0B,iBAAE,OAAO;AAAA,EAC9C,YAAY,iBAAE,OAAO,EAAE,IAAI,GAAG,wBAAwB;AACxD,CAAC;AAIM,IAAM,2BAA2B,iBAAE,OAAO;AAAA,EAC/C,OAAO,iBAAE,OAAO;AAAA,EAChB,MAAM;AACR,CAAC;AAIM,IAAM,0BAA0B,iBAAE,OAAO;AAAA,EAC9C,OAAO,iBAAE,KAAK,CAAC,yBAAyB,aAAa,eAAe,CAAC;AACvE,CAAC;AAIM,IAAM,+BAA+B,iBAAE,OAAO;AAAA,EACnD,UAAU,iBAAE,OAAO,EAAE,IAAI,GAAG,sBAAsB;AACpD,CAAC;AAGM,IAAM,gCAAgC,iBAAE,OAAO;AAAA,EACpD,YAAY,iBAAE,QAAQ;AACxB,CAAC;AAIM,IAAM,kCAAkC,iBAAE,OAAO;AAAA,EACtD,UAAU,iBAAE,OAAO,EAAE,IAAI,GAAG,sBAAsB;AACpD,CAAC;AAGM,IAAM,mCAAmC,iBAAE,OAAO;AAAA,EACvD,YAAY,iBAAE,OAAO;AACvB,CAAC;AAIM,IAAM,4BAA4B,iBAAE,OAAO;AAAA,EAChD,MAAM,iBAAE,OAAO;AAAA,EACf,WAAW,iBAAE,OAAO;AACtB,CAAC;AAIM,IAAM,mCAAmC,iBAAE,OAAO;AAAA,EACvD,MAAM,iBAAE,OAAO,EAAE,IAAI,GAAG,kBAAkB;AAC5C,CAAC;AAGM,IAAM,oCAAoC,iBAAE,OAAO;AAAA,EACxD,OAAO,iBAAE,OAAO;AAAA,EAChB,MAAM;AACR,CAAC;AAIM,IAAM,4BAA4B,iBAAE,OAAO;AAAA,EAChD,cAAc,iBAAE,OAAO;AAAA,EACvB,WAAW,iBAAE,OAAO;AACtB,CAAC;AAIM,IAAM,2BAA2B,iBAAE,OAAO;AAAA,EAC/C,cAAc,iBAAE,OAAO,EAAE,IAAI,GAAG,0BAA0B,EAAE,IAAI,IAAI;AACtE,CAAC;AAIM,IAAM,4BAA4B,iBAAE,OAAO;AAAA,EAChD,SAAS,iBAAE,QAAQ;AACrB,CAAC;AAKM,IAAM,qBAAqB,iBAAE,OAAO;AAAA,EACzC,WAAW,iBAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AAAA,EACpC,QAAQ,iBAAE,OAAO,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA,EACrC,SAAS,iBAAE,OAAO,iBAAE,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,EACzC,iBAAiB,iBAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAC7C,CAAC;AAGM,IAAM,6BAA6B,iBAAE,OAAO;AAAA,EACjD,QAAQ,iBAAE,MAAM,kBAAkB,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AACpD,CAAC;AAGM,IAAM,8BAA8B,iBAAE,OAAO;AAAA,EAClD,UAAU,iBAAE,OAAO;AACrB,CAAC;;;AChmCM,IAAM,SAAS;AAAA,EACpB,QAAQ;AAAA,EACR,sBAAsB;AAAA,EACtB,qBAAqB;AAAA,EACrB,mBAAmB;AAAA,EACnB,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,uBAAuB;AAAA,EACvB,2BAA2B;AAAA,EAC3B,mBAAmB;AAAA,EACnB,4BAA4B;AAAA,EAC5B,aAAa;AAAA,EACb,eAAe;AAAA,EACf,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,WAAW;AAAA,EACX,aAAa;AAAA,EACb,sBAAsB;AAAA,EACtB,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,WAAW;AAAA,EACX,gBAAgB;AAAA,EAChB,sBAAsB;AAAA,EACtB,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,cAAc;AAChB;AAKO,IAAM,qBAAqB;AAAA,EAChC,OAAO,OAAO,MAAM;AAAA,EACpB,QAAQ,OAAO,oBAAoB;AAAA,EACnC,QAAQ,OAAO,mBAAmB;AAAA,EAClC,QAAQ,OAAO,iBAAiB;AAAA,EAChC,OAAO,OAAO,kBAAkB;AAAA,EAChC,QAAQ,OAAO,gBAAgB;AAAA,EAC/B,QAAQ,OAAO,qBAAqB;AAAA,EACpC,QAAQ,OAAO,yBAAyB;AAAA,EACxC,QAAQ,OAAO,iBAAiB;AAAA,EAChC,QAAQ,OAAO,0BAA0B;AAAA,EACzC,OAAO,OAAO,WAAW;AAAA,EACzB,QAAQ,OAAO,aAAa;AAAA,EAC5B,UAAU,OAAO,aAAa;AAAA,EAC9B,QAAQ,OAAO,mBAAmB;AAAA,EAClC,OAAO,OAAO,SAAS;AAAA,EACvB,OAAO,OAAO,SAAS;AAAA,EACvB,OAAO,OAAO,WAAW;AAAA,EACzB,OAAO,OAAO,oBAAoB;AAAA,EAClC,QAAQ,OAAO,cAAc;AAAA,EAC7B,MAAM,OAAO,WAAW;AAAA,EACxB,MAAM,OAAO,SAAS;AAAA,EACtB,QAAQ,OAAO,cAAc;AAAA,EAC7B,OAAO,OAAO,oBAAoB;AAAA,EAClC,QAAQ,OAAO,cAAc;AAAA,EAC7B,OAAO,OAAO,YAAY;AAAA,EAC1B,UAAU,OAAO,YAAY;AAAA,EAC7B,OAAO,OAAO,YAAY;AAC5B;;;ACvDO,IAAM,6BAA6B;AAcnC,SAAS,gCACd,UACA,SAAiB,4BACO;AACxB,MAAI,CAAC,SAAU,QAAO,EAAE,QAAQ,UAAU;AAE1C,QAAM,gBAAgB,SAAS,MAAM,GAAG;AACxC,QAAM,cAAc,OAAO,MAAM,GAAG;AAEpC,MAAI,cAAc,CAAC,MAAM,YAAY,CAAC,KAAK,cAAc,CAAC,MAAM,YAAY,CAAC,GAAG;AAC9E,WAAO,EAAE,QAAQ,aAAa;AAAA,EAChC;AAEA,SAAO,EAAE,QAAQ,YAAY,UAAU,OAAO;AAChD;;;AChBO,IAAM,uBAAN,MAA2B;AAAA,EACxB,QAAyB;AAAA,EACzB,KAA8B;AAAA,EACrB,kBAAkB,oBAAI,IAA4C;AAAA,EAClE,sBAAsB,oBAAI,IAAsC;AAAA,EAChE;AAAA,EACT,aAAa;AAAA,EACb,aAAmD;AAAA,EACnD,YAAkD;AAAA,EAClD,wBAAwB;AAAA,EAEhC,YAAY,QAAoC;AAC9C,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,WAA4B;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,UAAgB;AACd,SAAK,wBAAwB;AAE7B,QAAI,KAAK,eAAe,MAAM;AAC5B,mBAAa,KAAK,UAAU;AAC5B,WAAK,aAAa;AAAA,IACpB;AAEA,QAAI,KAAK,IAAI;AACX,WAAK,cAAc;AACnB,WAAK,GAAG,SAAS;AACjB,WAAK,GAAG,UAAU;AAClB,WAAK,GAAG,UAAU;AAClB,WAAK,GAAG,YAAY;AACpB,WAAK,GAAG,MAAM;AACd,WAAK,KAAK;AAAA,IACZ;AAEA,UAAM,OAAO,KAAK,OAAO,iBAAkB;AAC3C,QAAI;AACF,WAAK,KAAK,IAAI,KAAK,KAAK,OAAO,GAAG;AAAA,IACpC,QAAQ;AACN,WAAK,SAAS,OAAO;AACrB,WAAK,qBAAqB;AAC1B;AAAA,IACF;AACA,SAAK,SAAS,YAAY;AAE1B,SAAK,GAAG,SAAS,MAAM;AACrB,WAAK,SAAS,WAAW;AACzB,WAAK,eAAe;AAAA,IACtB;AAEA,SAAK,GAAG,UAAU,CAAC,OAAgB;AACjC,WAAK,cAAc;AACnB,UAAI,KAAK,UAAU,WAAW,KAAK,UAAU,gBAAgB;AAC3D,aAAK,SAAS,cAAc;AAAA,MAC9B;AACA,YAAM,OAAO,iBAAiB,EAAE;AAEhC,UAAI,SAAS,KAAM;AACjB,aAAK,OAAO,gBAAgB;AAC5B;AAAA,MACF;AAEA,UAAI,CAAC,KAAK,yBAAyB,SAAS,MAAM;AAChD,aAAK,qBAAqB;AAAA,MAC5B;AAAA,IACF;AAEA,SAAK,GAAG,UAAU,MAAM;AACtB,WAAK,cAAc;AACnB,WAAK,SAAS,OAAO;AACrB,UAAI,CAAC,KAAK,uBAAuB;AAC/B,aAAK,qBAAqB;AAAA,MAC5B;AAAA,IACF;AAEA,SAAK,GAAG,YAAY,CAAC,UAA4B;AAC/C,WAAK,eAAe;AAEpB,UAAI,MAAM,SAAS,OAAQ;AAE3B,UAAI;AACJ,UAAI;AACF,cAAM,KAAK,MAAM,MAAM,IAAI;AAAA,MAC7B,QAAQ;AACN;AAAA,MACF;AAEA,YAAM,SAAS,8BAA8B,UAAU,GAAG;AAC1D,UAAI,CAAC,OAAO,SAAS;AAEnB,gBAAQ;AAAA,UACN;AAAA,UACA,KAAK,UAAU,GAAG;AAAA,UAClB,OAAO,MAAM;AAAA,QACf;AACA;AAAA,MACF;AAEA,iBAAW,WAAW,CAAC,GAAG,KAAK,eAAe,GAAG;AAC/C,gBAAQ,OAAO,IAAI;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,KAAK,KAAoC;AACvC,QAAI;AACF,WAAK,IAAI,KAAK,KAAK,UAAU,GAAG,CAAC;AAAA,IACnC,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,UAAU,SAA6D;AACrE,SAAK,gBAAgB,IAAI,OAAO;AAChC,WAAO,MAAM;AACX,WAAK,gBAAgB,OAAO,OAAO;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,cAAc,SAAuD;AACnE,SAAK,oBAAoB,IAAI,OAAO;AACpC,WAAO,MAAM;AACX,WAAK,oBAAoB,OAAO,OAAO;AAAA,IACzC;AAAA,EACF;AAAA,EAEA,YAAkB;AAChB,SAAK,wBAAwB;AAC7B,QAAI,KAAK,eAAe,MAAM;AAC5B,mBAAa,KAAK,UAAU;AAC5B,WAAK,aAAa;AAAA,IACpB;AACA,SAAK,aAAa;AAClB,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,aAAmB;AACjB,SAAK,wBAAwB;AAC7B,SAAK,cAAc;AAEnB,QAAI,KAAK,eAAe,MAAM;AAC5B,mBAAa,KAAK,UAAU;AAC5B,WAAK,aAAa;AAAA,IACpB;AAEA,SAAK,aAAa;AAElB,QAAI,KAAK,IAAI;AACX,WAAK,GAAG,SAAS;AACjB,WAAK,GAAG,UAAU;AAClB,WAAK,GAAG,UAAU;AAClB,WAAK,GAAG,YAAY;AACpB,WAAK,GAAG,MAAM;AACd,WAAK,KAAK;AAAA,IACZ;AACA,SAAK,SAAS,cAAc;AAAA,EAC9B;AAAA,EAEQ,iBAAuB;AAC7B,SAAK,cAAc;AACnB,SAAK,aAAa;AAAA,EACpB;AAAA,EAEQ,gBAAsB;AAC5B,QAAI,KAAK,cAAc,MAAM;AAC3B,mBAAa,KAAK,SAAS;AAC3B,WAAK,YAAY;AAAA,IACnB;AAAA,EACF;AAAA,EAEQ,eAAqB;AAC3B,UAAM,SAAS,KAAK,MAAM,KAAK,OAAO,IAAI,IAAM;AAChD,UAAM,QAAQ,MAAS;AACvB,SAAK,YAAY,WAAW,MAAM;AAChC,WAAK,YAAY;AACjB,UAAI;AACF,aAAK,IAAI,KAAK,MAAM;AAAA,MACtB,QAAQ;AAAA,MAER;AACA,WAAK,aAAa;AAAA,IACpB,GAAG,KAAK;AAAA,EACV;AAAA,EAEQ,uBAA6B;AACnC,QAAI,KAAK,eAAe,KAAM;AAE9B,UAAM,aAAa,KAAK,OAAO;AAC/B,QAAI,eAAe,UAAa,eAAe,GAAG;AAChD;AAAA,IACF;AAEA,QAAI,eAAe,MAAM,KAAK,cAAc,YAAY;AACtD;AAAA,IACF;AAEA,SAAK,SAAS,cAAc;AAE5B,QAAI,KAAK,sBAAuB;AAEhC,UAAM,eAAe,KAAK,OAAO,kBAAkB;AACnD,UAAM,WAAW,KAAK,OAAO,cAAc;AAC3C,UAAM,aAAa,KAAK,OAAO,qBAAqB;AACpD,UAAM,QAAQ,KAAK,IAAI,eAAe,cAAc,KAAK,YAAY,QAAQ;AAE7E,SAAK;AAEL,SAAK,aAAa,WAAW,MAAM;AACjC,WAAK,aAAa;AAClB,WAAK,QAAQ;AAAA,IACf,GAAG,KAAK;AAAA,EACV;AAAA,EAEQ,SAAS,UAAiC;AAChD,SAAK,QAAQ;AACb,QAAI,aAAa,aAAa;AAC5B,WAAK,aAAa;AAAA,IACpB;AACA,eAAW,WAAW,CAAC,GAAG,KAAK,mBAAmB,GAAG;AACnD,cAAQ,QAAQ;AAAA,IAClB;AAAA,EACF;AACF;AAEA,SAAS,iBAAiB,IAAiC;AACzD,MAAI,OAAO,OAAO,YAAY,OAAO,QAAQ,EAAE,UAAU,IAAK,QAAO;AACrE,QAAM,OAAgB,GAAG;AACzB,SAAO,OAAO,SAAS,WAAW,OAAO;AAC3C;;;AClOO,IAAM,yBAAN,MAA6B;AAAA,EAC1B,QAAyB;AAAA,EACzB,KAA8B;AAAA,EACrB,kBAAkB,oBAAI,IAA8C;AAAA,EACpE,sBAAsB,oBAAI,IAAsC;AAAA,EAChE;AAAA,EACT,aAAa;AAAA,EACb,aAAmD;AAAA,EACnD,YAAkD;AAAA,EAClD,wBAAwB;AAAA,EAEhC,YAAY,QAAsC;AAChD,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,WAA4B;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,UAAgB;AACd,SAAK,wBAAwB;AAE7B,QAAI,KAAK,eAAe,MAAM;AAC5B,mBAAa,KAAK,UAAU;AAC5B,WAAK,aAAa;AAAA,IACpB;AAEA,QAAI,KAAK,IAAI;AACX,WAAK,cAAc;AACnB,WAAK,GAAG,SAAS;AACjB,WAAK,GAAG,UAAU;AAClB,WAAK,GAAG,UAAU;AAClB,WAAK,GAAG,YAAY;AACpB,WAAK,GAAG,MAAM;AACd,WAAK,KAAK;AAAA,IACZ;AAEA,UAAM,OAAO,KAAK,OAAO,iBAAkB;AAC3C,QAAI;AACF,WAAK,KAAK,IAAI,KAAK,KAAK,OAAO,GAAG;AAAA,IACpC,QAAQ;AACN,WAAK,SAAS,OAAO;AACrB,WAAK,qBAAqB;AAC1B;AAAA,IACF;AACA,SAAK,SAAS,YAAY;AAE1B,SAAK,GAAG,SAAS,MAAM;AACrB,WAAK,SAAS,WAAW;AACzB,WAAK,eAAe;AAAA,IACtB;AAEA,SAAK,GAAG,UAAU,MAAM;AACtB,WAAK,cAAc;AACnB,UAAI,KAAK,UAAU,WAAW,KAAK,UAAU,gBAAgB;AAC3D,aAAK,SAAS,cAAc;AAAA,MAC9B;AACA,UAAI,CAAC,KAAK,uBAAuB;AAC/B,aAAK,qBAAqB;AAAA,MAC5B;AAAA,IACF;AAEA,SAAK,GAAG,UAAU,MAAM;AACtB,WAAK,cAAc;AACnB,WAAK,SAAS,OAAO;AACrB,UAAI,CAAC,KAAK,uBAAuB;AAC/B,aAAK,qBAAqB;AAAA,MAC5B;AAAA,IACF;AAEA,SAAK,GAAG,YAAY,CAAC,UAA4B;AAC/C,WAAK,eAAe;AAEpB,UAAI,MAAM,SAAS,OAAQ;AAE3B,UAAI;AACJ,UAAI;AACF,cAAM,KAAK,MAAM,MAAM,IAAI;AAAA,MAC7B,QAAQ;AACN;AAAA,MACF;AAEA,YAAM,SAAS,gCAAgC,UAAU,GAAG;AAC5D,UAAI,CAAC,OAAO,SAAS;AACnB,YAAI,KAAK,UAAU,aAAa;AAE9B,kBAAQ;AAAA,YACN;AAAA,YACA,KAAK,UAAU,GAAG;AAAA,YAClB,OAAO,MAAM;AAAA,UACf;AAAA,QACF;AACA;AAAA,MACF;AAEA,iBAAW,WAAW,CAAC,GAAG,KAAK,eAAe,GAAG;AAC/C,gBAAQ,OAAO,IAAI;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,KAAK,KAAsC;AACzC,QAAI;AACF,WAAK,IAAI,KAAK,KAAK,UAAU,GAAG,CAAC;AAAA,IACnC,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,UAAU,SAA+D;AACvE,SAAK,gBAAgB,IAAI,OAAO;AAChC,WAAO,MAAM;AACX,WAAK,gBAAgB,OAAO,OAAO;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,cAAc,SAAuD;AACnE,SAAK,oBAAoB,IAAI,OAAO;AACpC,WAAO,MAAM;AACX,WAAK,oBAAoB,OAAO,OAAO;AAAA,IACzC;AAAA,EACF;AAAA,EAEA,YAAkB;AAChB,SAAK,wBAAwB;AAC7B,QAAI,KAAK,eAAe,MAAM;AAC5B,mBAAa,KAAK,UAAU;AAC5B,WAAK,aAAa;AAAA,IACpB;AACA,SAAK,aAAa;AAClB,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,aAAmB;AACjB,SAAK,wBAAwB;AAC7B,SAAK,cAAc;AAEnB,QAAI,KAAK,eAAe,MAAM;AAC5B,mBAAa,KAAK,UAAU;AAC5B,WAAK,aAAa;AAAA,IACpB;AAEA,SAAK,aAAa;AAElB,QAAI,KAAK,IAAI;AACX,WAAK,GAAG,SAAS;AACjB,WAAK,GAAG,UAAU;AAClB,WAAK,GAAG,UAAU;AAClB,WAAK,GAAG,YAAY;AACpB,WAAK,GAAG,MAAM;AACd,WAAK,KAAK;AAAA,IACZ;AACA,SAAK,SAAS,cAAc;AAAA,EAC9B;AAAA,EAEQ,iBAAuB;AAC7B,SAAK,cAAc;AACnB,SAAK,aAAa;AAAA,EACpB;AAAA,EAEQ,gBAAsB;AAC5B,QAAI,KAAK,cAAc,MAAM;AAC3B,mBAAa,KAAK,SAAS;AAC3B,WAAK,YAAY;AAAA,IACnB;AAAA,EACF;AAAA,EAEQ,eAAqB;AAC3B,UAAM,SAAS,KAAK,MAAM,KAAK,OAAO,IAAI,IAAM;AAChD,UAAM,QAAQ,MAAS;AACvB,SAAK,YAAY,WAAW,MAAM;AAChC,WAAK,YAAY;AACjB,UAAI;AACF,aAAK,IAAI,KAAK,MAAM;AAAA,MACtB,QAAQ;AAAA,MAER;AACA,WAAK,aAAa;AAAA,IACpB,GAAG,KAAK;AAAA,EACV;AAAA,EAEQ,uBAA6B;AACnC,QAAI,KAAK,eAAe,KAAM;AAE9B,UAAM,aAAa,KAAK,OAAO;AAC/B,QAAI,eAAe,UAAa,eAAe,GAAG;AAChD;AAAA,IACF;AAEA,QAAI,eAAe,MAAM,KAAK,cAAc,YAAY;AACtD;AAAA,IACF;AAEA,SAAK,SAAS,cAAc;AAE5B,QAAI,KAAK,sBAAuB;AAEhC,UAAM,eAAe,KAAK,OAAO,kBAAkB;AACnD,UAAM,WAAW,KAAK,OAAO,cAAc;AAC3C,UAAM,aAAa,KAAK,OAAO,qBAAqB;AACpD,UAAM,QAAQ,KAAK,IAAI,eAAe,cAAc,KAAK,YAAY,QAAQ;AAE7E,SAAK;AAEL,SAAK,aAAa,WAAW,MAAM;AACjC,WAAK,aAAa;AAClB,WAAK,QAAQ;AAAA,IACf,GAAG,KAAK;AAAA,EACV;AAAA,EAEQ,SAAS,UAAiC;AAChD,SAAK,QAAQ;AACb,QAAI,aAAa,aAAa;AAC5B,WAAK,aAAa;AAAA,IACpB;AACA,eAAW,WAAW,CAAC,GAAG,KAAK,mBAAmB,GAAG;AACnD,cAAQ,QAAQ;AAAA,IAClB;AAAA,EACF;AACF;;;AC3OO,IAAM,mBAAmB;;;ACQzB,IAAM,0BAA0B;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAIO,IAAM,6BAA6B,iBAAE,KAAK,uBAAuB;AAKjE,IAAM,sBAAsB,CAAC,OAAO,MAAM,KAAK;AAG/C,IAAM,mBAAmB,iBAAE,KAAK,mBAAmB,EAAE,QAAQ,KAAK;AAiBlE,IAAM,wBAAwB,KAAK,OAAO;AAE1C,IAAM,wBAAwB,MAAM,OAAO;AAE3C,IAAM,2BAA2B,KAAK,OAAO;AAE7C,IAAM,uBAAuB;AAK7B,IAAM,4BAA4B,MAAM,OAAO;AAS/C,IAAM,6BAA6B,iBAAE,OAAO;AAAA,EACjD,MAAM;AAAA,EACN,KAAK;AAAA,EACL,WAAW,iBAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AAAA,EACpC,OAAO,iBAAE,OAAO,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA;AAAA,EAEpC,aAAa,iBAAE,KAAK,CAAC,KAAK,GAAG,CAAC,EAAE,QAAQ,GAAG;AAC7C,CAAC;AAeM,IAAM,8BAA8B,iBAAE,mBAAmB,MAAM;AAAA,EACpE,iBAAE,OAAO;AAAA,IACP,IAAI,iBAAE,QAAQ,IAAI;AAAA,IAClB,IAAI,iBAAE,OAAO,EAAE,IAAI,CAAC;AAAA,IACpB,KAAK,iBAAE,OAAO,EAAE,IAAI;AAAA,IACpB,WAAW,iBAAE,OAAO,EAAE,IAAI;AAAA,EAC5B,CAAC;AAAA,EACD,iBAAE,OAAO;AAAA,IACP,IAAI,iBAAE,QAAQ,KAAK;AAAA,IACnB,OAAO,iBAAE,OAAO;AAAA,EAClB,CAAC;AACH,CAAC;AAMM,IAAM,8BAA8B,iBAAE,OAAO;AAAA,EAClD,IAAI,iBAAE,QAAQ,IAAI;AACpB,CAAC;AAMM,IAAM,wBAAwB,iBAAE,OAAO;AAAA,EAC5C,IAAI,iBAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACpB,KAAK,iBAAE,OAAO,EAAE,IAAI;AAAA,EACpB,MAAM,iBAAE,OAAO;AAAA,EACf,OAAO,iBAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,WAAW,iBAAE,OAAO,EAAE,IAAI;AAAA,EAC1B,WAAW,iBAAE,OAAO,EAAE,IAAI;AAAA,EAC1B,WAAW,iBAAE,OAAO,EAAE,IAAI,EAAE,YAAY;AAC1C,CAAC;AAMM,IAAM,4BAA4B,iBAAE,OAAO;AAAA,EAChD,OAAO,iBAAE,MAAM,qBAAqB;AACtC,CAAC;","names":[]}
|