@thxgg/steward 0.1.6 → 0.1.10
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/.output/nitro.json +1 -1
- package/.output/public/_nuxt/{lAfn4NY4.js → BPaqwWyl.js} +19 -19
- package/.output/public/_nuxt/{jgc2Z7xi.js → C8LtDyY4.js} +2 -2
- package/.output/public/_nuxt/{BPnSj2YP.js → CQgu_W_k.js} +1 -1
- package/.output/public/_nuxt/{Ck5q4LNZ.js → CZKCADv6.js} +2 -2
- package/.output/public/_nuxt/{MKpq065x.js → CeO4HNxC.js} +1 -1
- package/.output/public/_nuxt/{BklAyl7e.js → Cs5ptsBk.js} +1 -1
- package/.output/public/_nuxt/{DuGNRgMW.js → CshyynD6.js} +1 -1
- package/.output/public/_nuxt/CzKPXRws.js +1 -0
- package/.output/public/_nuxt/{DIeYonPk.js → DOvbLsAq.js} +1 -1
- package/.output/public/_nuxt/{CxUtB6on.js → DbloiS5Y.js} +1 -1
- package/.output/public/_nuxt/{DZSVDCT3.js → DcRwFvvS.js} +1 -1
- package/.output/public/_nuxt/builds/latest.json +1 -1
- package/.output/public/_nuxt/builds/meta/7fda7510-94bc-443a-a338-a8d2af142ed9.json +1 -0
- package/.output/public/_nuxt/{C3Sxm8SF.js → vr7VLA9A.js} +1 -1
- package/.output/server/chunks/_/git-api.mjs +100 -0
- package/.output/server/chunks/_/git-api.mjs.map +1 -0
- package/.output/server/chunks/_/git.mjs +1 -1
- package/.output/server/chunks/build/{_prd_-JbQLT1IJ.mjs → _prd_-CkKfJB6U.mjs} +13 -10
- package/.output/server/chunks/build/_prd_-CkKfJB6U.mjs.map +1 -0
- package/.output/server/chunks/build/client.precomputed.mjs +1 -1
- package/.output/server/chunks/build/server.mjs +1 -1
- package/.output/server/chunks/nitro/nitro.mjs +585 -585
- package/.output/server/chunks/routes/api/repos/_repoId/git/commits.get.mjs +41 -22
- package/.output/server/chunks/routes/api/repos/_repoId/git/commits.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/repos/_repoId/git/diff.get.mjs +27 -15
- package/.output/server/chunks/routes/api/repos/_repoId/git/diff.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/repos/_repoId/git/file-content.get.mjs +42 -13
- package/.output/server/chunks/routes/api/repos/_repoId/git/file-content.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/repos/_repoId/git/file-diff.get.mjs +29 -17
- package/.output/server/chunks/routes/api/repos/_repoId/git/file-diff.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/progress.get.mjs +3 -2
- package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/progress.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/tasks/_taskId/commits.get.mjs +3 -2
- package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/tasks/_taskId/commits.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/tasks.get.mjs +3 -2
- package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/tasks.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/repos/_repoId/refresh-git-repos.post.mjs +1 -1
- package/.output/server/package.json +1 -1
- package/README.md +22 -4
- package/dist/host/src/api/git.js +1 -8
- package/dist/host/src/api/prds.js +2 -8
- package/dist/host/src/api/repo-context.js +60 -0
- package/dist/host/src/api/repos.js +6 -0
- package/dist/host/src/api/state.js +20 -21
- package/dist/host/src/executor.js +215 -29
- package/dist/host/src/help.js +124 -0
- package/dist/host/src/mcp.js +49 -25
- package/dist/host/src/ui.js +43 -6
- package/dist/server/utils/repos.js +2 -2
- package/docs/MCP.md +50 -3
- package/package.json +1 -1
- package/.output/public/_nuxt/builds/meta/7bb8c982-dc40-47ba-9dfb-5efd6fd086ac.json +0 -1
- package/.output/public/_nuxt/tuYgPddM.js +0 -1
- package/.output/server/chunks/build/_prd_-JbQLT1IJ.mjs.map +0 -1
package/dist/host/src/mcp.js
CHANGED
|
@@ -1,57 +1,81 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { execute
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return error.stackTrace
|
|
8
|
-
? `${error.message}\n\n${error.stackTrace}`
|
|
9
|
-
: error.message;
|
|
10
|
-
}
|
|
11
|
-
if (error instanceof Error) {
|
|
12
|
-
return error.stack
|
|
13
|
-
? `${error.message}\n\n${error.stack}`
|
|
14
|
-
: error.message;
|
|
15
|
-
}
|
|
16
|
-
return String(error);
|
|
17
|
-
}
|
|
18
|
-
function serializeResult(result) {
|
|
19
|
-
if (result === undefined) {
|
|
20
|
-
return 'undefined';
|
|
21
|
-
}
|
|
4
|
+
import { execute } from './executor.js';
|
|
5
|
+
import { getExecuteToolDescription } from './help.js';
|
|
6
|
+
function serializeEnvelope(envelope) {
|
|
22
7
|
try {
|
|
23
|
-
return JSON.stringify(
|
|
8
|
+
return JSON.stringify(envelope, null, 2);
|
|
24
9
|
}
|
|
25
10
|
catch {
|
|
26
|
-
|
|
11
|
+
const fallback = {
|
|
12
|
+
ok: false,
|
|
13
|
+
result: null,
|
|
14
|
+
logs: [],
|
|
15
|
+
error: {
|
|
16
|
+
code: 'SERIALIZATION_ERROR',
|
|
17
|
+
message: 'Failed to serialize execution envelope'
|
|
18
|
+
},
|
|
19
|
+
meta: {
|
|
20
|
+
timeoutMs: 30_000,
|
|
21
|
+
durationMs: 0,
|
|
22
|
+
truncatedResult: false,
|
|
23
|
+
truncatedLogs: false,
|
|
24
|
+
resultWasUndefined: false
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
return JSON.stringify(fallback, null, 2);
|
|
27
28
|
}
|
|
28
29
|
}
|
|
30
|
+
function buildUnexpectedErrorEnvelope(error) {
|
|
31
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
32
|
+
const stack = error instanceof Error ? error.stack : undefined;
|
|
33
|
+
return {
|
|
34
|
+
ok: false,
|
|
35
|
+
result: null,
|
|
36
|
+
logs: [],
|
|
37
|
+
error: {
|
|
38
|
+
code: 'MCP_EXECUTION_FAILURE',
|
|
39
|
+
message,
|
|
40
|
+
...(stack && { stack })
|
|
41
|
+
},
|
|
42
|
+
meta: {
|
|
43
|
+
timeoutMs: 30_000,
|
|
44
|
+
durationMs: 0,
|
|
45
|
+
truncatedResult: false,
|
|
46
|
+
truncatedLogs: false,
|
|
47
|
+
resultWasUndefined: false
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
29
51
|
export async function runMcpServer() {
|
|
30
52
|
const server = new McpServer({
|
|
31
53
|
name: 'steward',
|
|
32
54
|
version: '0.1.0'
|
|
33
55
|
});
|
|
34
|
-
server.tool('execute',
|
|
35
|
-
code: z.string().
|
|
56
|
+
server.tool('execute', getExecuteToolDescription(), {
|
|
57
|
+
code: z.string().optional()
|
|
36
58
|
}, async ({ code }) => {
|
|
37
59
|
try {
|
|
38
|
-
const
|
|
60
|
+
const envelope = await execute(code || '');
|
|
39
61
|
return {
|
|
62
|
+
isError: !envelope.ok,
|
|
40
63
|
content: [
|
|
41
64
|
{
|
|
42
65
|
type: 'text',
|
|
43
|
-
text:
|
|
66
|
+
text: serializeEnvelope(envelope)
|
|
44
67
|
}
|
|
45
68
|
]
|
|
46
69
|
};
|
|
47
70
|
}
|
|
48
71
|
catch (error) {
|
|
72
|
+
const envelope = buildUnexpectedErrorEnvelope(error);
|
|
49
73
|
return {
|
|
50
74
|
isError: true,
|
|
51
75
|
content: [
|
|
52
76
|
{
|
|
53
77
|
type: 'text',
|
|
54
|
-
text:
|
|
78
|
+
text: serializeEnvelope(envelope)
|
|
55
79
|
}
|
|
56
80
|
]
|
|
57
81
|
};
|
package/dist/host/src/ui.js
CHANGED
|
@@ -42,23 +42,60 @@ export async function runUi(options) {
|
|
|
42
42
|
env
|
|
43
43
|
});
|
|
44
44
|
return await new Promise((resolveExit, reject) => {
|
|
45
|
+
const signalGracePeriodMs = 2000;
|
|
46
|
+
let forceKillTimer = null;
|
|
47
|
+
let signalCount = 0;
|
|
48
|
+
let childExited = false;
|
|
49
|
+
const clearForceKillTimer = () => {
|
|
50
|
+
if (forceKillTimer) {
|
|
51
|
+
clearTimeout(forceKillTimer);
|
|
52
|
+
forceKillTimer = null;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const cleanup = () => {
|
|
56
|
+
process.off('SIGINT', forwardSignal);
|
|
57
|
+
process.off('SIGTERM', forwardSignal);
|
|
58
|
+
clearForceKillTimer();
|
|
59
|
+
};
|
|
60
|
+
const forceKill = () => {
|
|
61
|
+
if (!childExited && child.exitCode === null && child.signalCode === null) {
|
|
62
|
+
child.kill('SIGKILL');
|
|
63
|
+
}
|
|
64
|
+
};
|
|
45
65
|
const forwardSignal = (signal) => {
|
|
46
|
-
if (
|
|
66
|
+
if (childExited) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
signalCount += 1;
|
|
70
|
+
if (signalCount > 1) {
|
|
71
|
+
forceKill();
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (child.exitCode === null && child.signalCode === null) {
|
|
47
75
|
child.kill(signal);
|
|
48
76
|
}
|
|
77
|
+
clearForceKillTimer();
|
|
78
|
+
forceKillTimer = setTimeout(forceKill, signalGracePeriodMs);
|
|
49
79
|
};
|
|
50
80
|
process.on('SIGINT', forwardSignal);
|
|
51
81
|
process.on('SIGTERM', forwardSignal);
|
|
52
82
|
child.on('error', (error) => {
|
|
53
|
-
|
|
54
|
-
process.off('SIGTERM', forwardSignal);
|
|
83
|
+
cleanup();
|
|
55
84
|
reject(error);
|
|
56
85
|
});
|
|
57
86
|
child.on('exit', (code, signal) => {
|
|
58
|
-
|
|
59
|
-
|
|
87
|
+
childExited = true;
|
|
88
|
+
cleanup();
|
|
60
89
|
if (signal) {
|
|
61
|
-
|
|
90
|
+
if (signal === 'SIGINT') {
|
|
91
|
+
resolveExit(130);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (signal === 'SIGTERM') {
|
|
95
|
+
resolveExit(143);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
resolveExit(1);
|
|
62
99
|
return;
|
|
63
100
|
}
|
|
64
101
|
resolveExit(code ?? 0);
|
|
@@ -174,7 +174,7 @@ async function isGitRepo(dirPath) {
|
|
|
174
174
|
try {
|
|
175
175
|
const gitPath = join(dirPath, '.git');
|
|
176
176
|
const stats = await fs.stat(gitPath);
|
|
177
|
-
return stats.isDirectory();
|
|
177
|
+
return stats.isDirectory() || stats.isFile();
|
|
178
178
|
}
|
|
179
179
|
catch {
|
|
180
180
|
return false;
|
|
@@ -188,7 +188,7 @@ async function isGitRepo(dirPath) {
|
|
|
188
188
|
* @param maxDepth - Maximum depth to scan (default: 2)
|
|
189
189
|
* @returns Array of discovered git repository info
|
|
190
190
|
*/
|
|
191
|
-
export async function discoverGitRepos(basePath, maxDepth =
|
|
191
|
+
export async function discoverGitRepos(basePath, maxDepth = 4) {
|
|
192
192
|
const resolvedBase = resolve(basePath);
|
|
193
193
|
// If basePath itself is a git repo, return empty (standard repo case)
|
|
194
194
|
if (await isGitRepo(resolvedBase)) {
|
package/docs/MCP.md
CHANGED
|
@@ -58,7 +58,31 @@ Example MCP client config:
|
|
|
58
58
|
|
|
59
59
|
Your code is wrapped in an async function, so you can use `await` directly.
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
Each call returns a JSON envelope:
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"ok": true,
|
|
66
|
+
"result": {},
|
|
67
|
+
"logs": [],
|
|
68
|
+
"error": null,
|
|
69
|
+
"meta": {
|
|
70
|
+
"timeoutMs": 30000,
|
|
71
|
+
"durationMs": 12,
|
|
72
|
+
"truncatedResult": false,
|
|
73
|
+
"truncatedLogs": false,
|
|
74
|
+
"resultWasUndefined": false
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
- `result` is `null` when your code does not explicitly return a value.
|
|
80
|
+
- `logs` contains captured `console.log/info/warn/error` output from sandbox code.
|
|
81
|
+
- `error` is populated with `{ code, message, stack?, details? }` on failure.
|
|
82
|
+
|
|
83
|
+
In-sandbox discovery helper:
|
|
84
|
+
|
|
85
|
+
- `steward.help()`
|
|
62
86
|
|
|
63
87
|
## Available APIs
|
|
64
88
|
|
|
@@ -66,6 +90,7 @@ Return values are JSON-stringified in the MCP response.
|
|
|
66
90
|
|
|
67
91
|
- `repos.list()`
|
|
68
92
|
- `repos.get(repoId)`
|
|
93
|
+
- `repos.current()`
|
|
69
94
|
- `repos.add(path, name?)`
|
|
70
95
|
- `repos.remove(repoId)`
|
|
71
96
|
- `repos.refreshGitRepos(repoId)`
|
|
@@ -89,10 +114,13 @@ Return values are JSON-stringified in the MCP response.
|
|
|
89
114
|
|
|
90
115
|
- `state.get(repoId, slug)`
|
|
91
116
|
- `state.getByPath(repoPath, slug)`
|
|
117
|
+
- `state.getCurrent(slug)`
|
|
92
118
|
- `state.summaries(repoId)`
|
|
93
119
|
- `state.summariesByPath(repoPath)`
|
|
120
|
+
- `state.summariesCurrent()`
|
|
94
121
|
- `state.upsert(repoId, slug, payload)`
|
|
95
122
|
- `state.upsertByPath(repoPath, slug, payload)`
|
|
123
|
+
- `state.upsertCurrent(slug, payload)`
|
|
96
124
|
|
|
97
125
|
`payload` supports any combination of:
|
|
98
126
|
|
|
@@ -116,7 +144,7 @@ return await Promise.all(reposList.map(async (repo) => ({
|
|
|
116
144
|
Load one PRD with state:
|
|
117
145
|
|
|
118
146
|
```js
|
|
119
|
-
const repo =
|
|
147
|
+
const repo = await repos.current()
|
|
120
148
|
const slug = 'prd-viewer'
|
|
121
149
|
|
|
122
150
|
return {
|
|
@@ -139,6 +167,24 @@ return await Promise.all(commits.map(async (entry) => ({
|
|
|
139
167
|
})))
|
|
140
168
|
```
|
|
141
169
|
|
|
170
|
+
Inspect signatures at runtime:
|
|
171
|
+
|
|
172
|
+
```js
|
|
173
|
+
return steward.help()
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Update state in the current repo (no repoId required):
|
|
177
|
+
|
|
178
|
+
```js
|
|
179
|
+
const slug = 'prd-viewer'
|
|
180
|
+
|
|
181
|
+
await state.upsertCurrent(slug, {
|
|
182
|
+
notes: '# Updated from codemode'
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
return { saved: true }
|
|
186
|
+
```
|
|
187
|
+
|
|
142
188
|
Update state directly by path (replacement for shell helpers):
|
|
143
189
|
|
|
144
190
|
```js
|
|
@@ -170,7 +216,8 @@ return { saved: true }
|
|
|
170
216
|
## Limits
|
|
171
217
|
|
|
172
218
|
- Execution timeout: 30 seconds
|
|
173
|
-
-
|
|
219
|
+
- Result preview limit: 50,000 characters
|
|
220
|
+
- Captured log limit: 20,000 characters (max 200 log entries)
|
|
174
221
|
- Timer limit: 100 active timers in sandbox
|
|
175
222
|
|
|
176
223
|
## Safety Notes
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"id":"7bb8c982-dc40-47ba-9dfb-5efd6fd086ac","timestamp":1771764393983,"prerendered":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as z,l as e,Y as _t,g as D,k as te,o as u,z as g,E as M,c as k,n as K,F as Y,r as ee,y as bt,C as ne,w as c,A as I,q as E,b as v,N as he,p as Ce,Z as xt,x as re,B as ge,$ as Ct,j as Xe,X as Le,a as d,t as L,a0 as kt,a1 as wt,m as me,S as ie,d as W,a2 as St,O as Be,P as Ae,V as Fe,a3 as Je,W as $t,a4 as Et,a5 as Dt}from"./Ck5q4LNZ.js";import{c as ye,l as Pe,e as Rt,r as Qe,f as Ye,P as se,d as De,u as ke,o as Bt,B as le,b as Ze,a as Me,F as Ie,k as Q,j as N,m as At}from"./BPnSj2YP.js";import{x as Ft,V as Pt,y as Te,a as je,u as It,g as Ot,c as _e,d as we,e as Lt,z as Mt,j as Tt,t as et,k as jt,s as zt,r as Vt,m as qt,n as Kt,o as Ht,p as Ut,S as Nt,L as Gt,C as Wt,R as tt,B as Xt,i as ue,A as Jt,F as ze,G as st,H as ot,I as at,X as nt,h as Se,J as Qt,M as Yt,N as Zt,l as es,v as ts,K as ss}from"./jgc2Z7xi.js";import{F as os,I as as,a as Oe}from"./DuGNRgMW.js";import{_ as ns}from"./C3Sxm8SF.js";const lt=ye("monitor",[["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2",key:"48i651"}],["line",{x1:"8",x2:"16",y1:"21",y2:"21",key:"1svkeh"}],["line",{x1:"12",x2:"12",y1:"17",y2:"21",key:"vw1qmm"}]]);const rt=ye("moon",[["path",{d:"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401",key:"kfwtm"}]]);const ls=ye("search",[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]]);const it=ye("sun",[["circle",{cx:"12",cy:"12",r:"4",key:"4exip2"}],["path",{d:"M12 2v2",key:"tus03m"}],["path",{d:"M12 20v2",key:"1lh1kg"}],["path",{d:"m4.93 4.93 1.41 1.41",key:"149t6j"}],["path",{d:"m17.66 17.66 1.41 1.41",key:"ptbguv"}],["path",{d:"M2 12h2",key:"1t8f8n"}],["path",{d:"M20 12h2",key:"1q8mjw"}],["path",{d:"m6.34 17.66-1.41 1.41",key:"1m8zz5"}],["path",{d:"m19.07 4.93-1.41 1.41",key:"1shlcs"}]]);const rs=ye("trash-2",[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]]);function is(o,t,s){const a=o.findIndex(l=>Pe(l,t)),r=o.findIndex(l=>Pe(l,s));if(a===-1||r===-1)return[];const[i,n]=[a,r].sort((l,f)=>l-f);return o.slice(i,n+1)}function us(o){const t=z(()=>e(o)),s=z(()=>new Intl.Collator("en",{usage:"search",...t.value}));return{startsWith:(n,l)=>l.length===0?!0:(n=n.normalize("NFC"),l=l.normalize("NFC"),s.value.compare(n.slice(0,l.length),l)===0),endsWith:(n,l)=>l.length===0?!0:(n=n.normalize("NFC"),l=l.normalize("NFC"),s.value.compare(n.slice(-l.length),l)===0),contains:(n,l)=>{if(l.length===0)return!0;n=n.normalize("NFC"),l=l.normalize("NFC");let f=0;const p=l.length;for(;f+p<=n.length;f++){const y=n.slice(f,f+p);if(s.value.compare(l,y)===0)return!0}return!1}}}function ds(o){return z(()=>_t(o)?!!Rt(o)?.closest("form"):!0)}function cs(){return{ALT:"Alt",ARROW_DOWN:"ArrowDown",ARROW_LEFT:"ArrowLeft",ARROW_RIGHT:"ArrowRight",ARROW_UP:"ArrowUp",BACKSPACE:"Backspace",CAPS_LOCK:"CapsLock",CONTROL:"Control",DELETE:"Delete",END:"End",ENTER:"Enter",ESCAPE:"Escape",F1:"F1",F10:"F10",F11:"F11",F12:"F12",F2:"F2",F3:"F3",F4:"F4",F5:"F5",F6:"F6",F7:"F7",F8:"F8",F9:"F9",HOME:"Home",META:"Meta",PAGE_DOWN:"PageDown",PAGE_UP:"PageUp",SHIFT:"Shift",SPACE:" ",TAB:"Tab",CTRL:"Control",ASTERISK:"*",SPACE_CODE:"Space"}}function ps(o){const t=Qe("",1e3);return{search:t,handleTypeaheadSearch:(r,i)=>{t.value=t.value+r;{const n=Ft(),l=i.map(_=>({..._,textValue:_.value?.textValue??_.ref.textContent?.trim()??""})),f=l.find(_=>_.ref===n),p=l.map(_=>_.textValue),y=ms(p,t.value,f?.textValue),m=l.find(_=>_.textValue===y);return m&&m.ref.focus(),m?.ref}},resetTypeahead:()=>{t.value=""}}}function fs(o,t){return o.map((s,a)=>o[(t+a)%o.length])}function ms(o,t,s){const r=t.length>1&&Array.from(t).every(p=>p===t[0])?t[0]:t,i=s?o.indexOf(s):-1;let n=fs(o,Math.max(i,0));r.length===1&&(n=n.filter(p=>p!==s));const f=n.find(p=>p.toLowerCase().startsWith(r.toLowerCase()));return f!==s?f:void 0}var vs=D({inheritAttrs:!1,__name:"VisuallyHiddenInputBubble",props:{name:{type:String,required:!0},value:{type:null,required:!0},checked:{type:Boolean,required:!1,default:void 0},required:{type:Boolean,required:!1},disabled:{type:Boolean,required:!1},feature:{type:String,required:!1,default:"fully-hidden"}},setup(o){const t=o,{primitiveElement:s,currentElement:a}=Te(),r=z(()=>t.checked??t.value);return te(r,(i,n)=>{if(!a.value)return;const l=a.value,f=window.HTMLInputElement.prototype,y=Object.getOwnPropertyDescriptor(f,"value").set;if(y&&i!==n){const m=new Event("input",{bubbles:!0}),_=new Event("change",{bubbles:!0});y.call(l,i),l.dispatchEvent(m),l.dispatchEvent(_)}}),(i,n)=>(u(),g(Pt,M({ref_key:"primitiveElement",ref:s},{...t,...i.$attrs},{as:"input"}),null,16))}}),Ue=vs,hs=D({inheritAttrs:!1,__name:"VisuallyHiddenInput",props:{name:{type:String,required:!0},value:{type:null,required:!0},checked:{type:Boolean,required:!1,default:void 0},required:{type:Boolean,required:!1},disabled:{type:Boolean,required:!1},feature:{type:String,required:!1,default:"fully-hidden"}},setup(o){const t=o,s=z(()=>typeof t.value=="object"&&Array.isArray(t.value)&&t.value.length===0&&t.required),a=z(()=>typeof t.value=="string"||typeof t.value=="number"||typeof t.value=="boolean"||t.value===null||t.value===void 0?[{name:t.name,value:t.value}]:typeof t.value=="object"&&Array.isArray(t.value)?t.value.flatMap((r,i)=>typeof r=="object"?Object.entries(r).map(([n,l])=>({name:`${t.name}[${i}][${n}]`,value:l})):{name:`${t.name}[${i}]`,value:r}):t.value!==null&&typeof t.value=="object"&&!Array.isArray(t.value)?Object.entries(t.value).map(([r,i])=>({name:`${t.name}[${r}]`,value:i})):[]);return(r,i)=>(u(),k(Y,null,[K(" We render single input if it's required "),s.value?(u(),g(Ue,M({key:r.name},{...t,...r.$attrs},{name:r.name,value:r.value}),null,16,["name","value"])):(u(!0),k(Y,{key:1},ee(a.value,n=>(u(),g(Ue,M({key:n.name},{ref_for:!0},{...t,...r.$attrs},{name:n.name,value:n.value}),null,16,["name","value"]))),128))],2112))}}),gs=hs;function ys(o,t,s){return o===void 0?!1:Array.isArray(o)?o.some(a=>ve(a,t,s)):ve(o,t,s)}function ve(o,t,s){return o===void 0||t===void 0?!1:typeof o=="string"?o===t:typeof s=="function"?s(o,t):typeof s=="string"?o?.[s]===t?.[s]:Pe(o,t)}const[Ve,_s]=_e("ListboxRoot");var bs=D({__name:"ListboxRoot",props:{modelValue:{type:null,required:!1},defaultValue:{type:null,required:!1},multiple:{type:Boolean,required:!1},orientation:{type:String,required:!1,default:"vertical"},dir:{type:String,required:!1},disabled:{type:Boolean,required:!1},selectionBehavior:{type:String,required:!1,default:"toggle"},highlightOnHover:{type:Boolean,required:!1},by:{type:[String,Function],required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1},name:{type:String,required:!1},required:{type:Boolean,required:!1}},emits:["update:modelValue","highlight","entryFocus","leave"],setup(o,{expose:t,emit:s}){const a=o,r=s,{multiple:i,highlightOnHover:n,orientation:l,disabled:f,selectionBehavior:p,dir:y}=bt(a),{getItems:m}=je({isProvider:!0}),{handleTypeaheadSearch:_}=ps(),{primitiveElement:T,currentElement:x}=Te(),P=cs(),j=It(y),w=ds(x),H=E(),U=E(!1),X=E(!0),R=Ye(a,"modelValue",r,{defaultValue:a.defaultValue??(i.value?[]:void 0),passive:a.modelValue===void 0,deep:!0});function de(h){if(U.value=!0,a.multiple){const C=Array.isArray(R.value)?[...R.value]:[],$=C.findIndex(q=>ve(q,h,a.by));a.selectionBehavior==="toggle"?($===-1?C.push(h):C.splice($,1),R.value=C):(R.value=[h],H.value=h)}else a.selectionBehavior==="toggle"&&ve(R.value,h,a.by)?R.value=void 0:R.value=h;setTimeout(()=>{U.value=!1},1)}const V=E(null),G=E(null),S=E(!1),B=E(!1),O=De(),Z=De(),be=De();function ce(){return m().map(h=>h.ref).filter(h=>h.dataset.disabled!=="")}function J(h,C=!0){if(!h)return;V.value=h,X.value&&V.value.focus(),C&&V.value.scrollIntoView({block:"nearest"});const $=m().find(q=>q.ref===h);r("highlight",$)}function F(h){if(S.value)be.trigger(h);else{const C=m().find($=>ve($.value,h,a.by));C&&(V.value=C.ref,J(C.ref))}}function b(h){V.value&&V.value.isConnected&&(h.preventDefault(),h.stopPropagation(),B.value||V.value.click())}function A(h){if(X.value){if(U.value=!0,S.value)Z.trigger(h);else{const C=h.altKey||h.ctrlKey||h.metaKey;if(C&&h.key==="a"&&i.value){const $=m(),q=$.map(oe=>oe.value);R.value=[...q],h.preventDefault(),J($[$.length-1].ref)}else if(!C){const $=_(h.key,m());$&&J($)}}setTimeout(()=>{U.value=!1},1)}}function pe(){B.value=!0}function vt(){ne(()=>{B.value=!1})}function qe(){ne(()=>{const h=new KeyboardEvent("keydown",{key:"PageUp"});Ke(h)})}function Ee(h){const C=V.value;C?.isConnected&&(G.value=C),V.value=null,r("leave",h)}function ht(h){const C=new CustomEvent("listbox.entryFocus",{bubbles:!1,cancelable:!0});if(h.currentTarget?.dispatchEvent(C),r("entryFocus",C),!C.defaultPrevented)if(G.value)J(G.value);else{const $=ce()?.[0];J($)}}function Ke(h){const C=Ot(h,l.value,j.value);if(!C)return;let $=ce();if(V.value){if(C==="last")$.reverse();else if(C==="prev"||C==="next"){C==="prev"&&$.reverse();const q=$.indexOf(V.value);$=$.slice(q+1)}gt(h,$[0])}if($.length){const q=!V.value&&C==="prev"?$.length-1:0;J($[q])}if(S.value)return Z.trigger(h)}function gt(h,C){if(!(S.value||a.selectionBehavior!=="replace"||!i.value||!Array.isArray(R.value)||(h.altKey||h.ctrlKey||h.metaKey)&&!h.shiftKey)&&h.shiftKey){const q=m().filter(fe=>fe.ref.dataset.disabled!=="");let oe=q.find(fe=>fe.ref===C)?.value;if(h.key===P.END?oe=q[q.length-1].value:h.key===P.HOME&&(oe=q[0].value),!oe||!H.value)return;const yt=is(q.map(fe=>fe.value),H.value,oe);R.value=yt}}async function He(h){if(await ne(),S.value)O.trigger(h);else{const C=ce(),$=C.find(q=>q.dataset.state==="checked");$?J($):C.length&&J(C[0])}}return te(R,()=>{U.value||ne(()=>{He()})},{immediate:!0,deep:!0}),t({highlightedElement:V,highlightItem:F,highlightFirstItem:qe,highlightSelected:He,getItems:m}),_s({modelValue:R,onValueChange:de,multiple:i,orientation:l,dir:j,disabled:f,highlightOnHover:n,highlightedElement:V,isVirtual:S,virtualFocusHook:O,virtualKeydownHook:Z,virtualHighlightHook:be,by:a.by,firstValue:H,selectionBehavior:p,focusable:X,onLeave:Ee,onEnter:ht,changeHighlight:J,onKeydownEnter:b,onKeydownNavigation:Ke,onKeydownTypeAhead:A,onCompositionStart:pe,onCompositionEnd:vt,highlightFirstItem:qe}),(h,C)=>(u(),g(e(se),{ref_key:"primitiveElement",ref:T,as:h.as,"as-child":h.asChild,dir:e(j),"data-disabled":e(f)?"":void 0,onPointerleave:Ee,onFocusout:C[0]||(C[0]=async $=>{const q=$.relatedTarget||$.target;await ne(),V.value&&e(x)&&!e(x).contains(q)&&Ee($)})},{default:c(()=>[I(h.$slots,"default",{modelValue:e(R)}),e(w)&&h.name?(u(),g(e(gs),{key:0,name:h.name,value:e(R),disabled:e(f),required:h.required},null,8,["name","value","disabled","required"])):K("v-if",!0)]),_:3},8,["as","as-child","dir","data-disabled"]))}}),xs=bs,Cs=D({__name:"ListboxContent",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(o){const{CollectionSlot:t}=je(),s=Ve(),a=Qe(!1,10);return(r,i)=>(u(),g(e(t),null,{default:c(()=>[v(e(se),{role:"listbox",as:r.as,"as-child":r.asChild,tabindex:e(s).focusable.value?e(s).highlightedElement.value?"-1":"0":"-1","aria-orientation":e(s).orientation.value,"aria-multiselectable":!!e(s).multiple.value,"data-orientation":e(s).orientation.value,onMousedown:i[0]||(i[0]=Ce(n=>a.value=!0,["left"])),onFocus:i[1]||(i[1]=n=>{e(a)||e(s).onEnter(n)}),onKeydown:[i[2]||(i[2]=he(n=>{e(s).orientation.value==="vertical"&&(n.key==="ArrowLeft"||n.key==="ArrowRight")||e(s).orientation.value==="horizontal"&&(n.key==="ArrowUp"||n.key==="ArrowDown")||(n.preventDefault(),e(s).focusable.value&&e(s).onKeydownNavigation(n))},["down","up","left","right","home","end"])),he(e(s).onKeydownEnter,["enter"]),e(s).onKeydownTypeAhead]},{default:c(()=>[I(r.$slots,"default")]),_:3},8,["as","as-child","tabindex","aria-orientation","aria-multiselectable","data-orientation","onKeydown"])]),_:3}))}}),ks=Cs,ws=D({__name:"ListboxFilter",props:{modelValue:{type:String,required:!1},autoFocus:{type:Boolean,required:!1},disabled:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"input"}},emits:["update:modelValue"],setup(o,{emit:t}){const s=o,r=Ye(s,"modelValue",t,{defaultValue:"",passive:s.modelValue===void 0}),i=Ve(),{primitiveElement:n,currentElement:l}=Te(),f=z(()=>s.disabled||i.disabled.value||!1),p=E();return xt(()=>p.value=i.highlightedElement.value?.id),re(()=>{i.focusable.value=!1,setTimeout(()=>{s.autoFocus&&l.value?.focus()},1)}),ge(()=>{i.focusable.value=!0}),(y,m)=>(u(),g(e(se),{ref_key:"primitiveElement",ref:n,as:y.as,"as-child":y.asChild,value:e(r),disabled:f.value?"":void 0,"data-disabled":f.value?"":void 0,"aria-disabled":f.value??void 0,"aria-activedescendant":p.value,type:"text",onKeydown:[he(Ce(e(i).onKeydownNavigation,["prevent"]),["down","up","home","end"]),he(e(i).onKeydownEnter,["enter"])],onInput:m[0]||(m[0]=_=>{r.value=_.target.value,e(i).highlightFirstItem()}),onCompositionstart:e(i).onCompositionStart,onCompositionend:e(i).onCompositionEnd},{default:c(()=>[I(y.$slots,"default",{modelValue:e(r)})]),_:3},8,["as","as-child","value","disabled","data-disabled","aria-disabled","aria-activedescendant","onKeydown","onCompositionstart","onCompositionend"]))}}),Ss=ws;const[$s,Es]=_e("ListboxGroup");var Ds=D({__name:"ListboxGroup",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(o){const t=o,s=we(void 0,"reka-listbox-group");return Es({id:s}),(a,r)=>(u(),g(e(se),M({role:"group"},t,{"aria-labelledby":e(s)}),{default:c(()=>[I(a.$slots,"default")]),_:3},16,["aria-labelledby"]))}}),Rs=Ds,Bs=D({__name:"ListboxGroupLabel",props:{for:{type:String,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"div"}},setup(o){const t=o,s=$s({id:""});return(a,r)=>(u(),g(e(se),M(t,{id:e(s).id}),{default:c(()=>[I(a.$slots,"default")]),_:3},16,["id"]))}}),As=Bs;const Fs="listbox.select",[Ba,Ps]=_e("ListboxItem");var Is=D({__name:"ListboxItem",props:{value:{type:null,required:!0},disabled:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"div"}},emits:["select"],setup(o,{emit:t}){const s=o,a=t,r=we(void 0,"reka-listbox-item"),{CollectionItem:i}=je(),{forwardRef:n,currentElement:l}=Lt(),f=Ve(),p=z(()=>l.value===f.highlightedElement.value),y=z(()=>ys(f.modelValue.value,s.value,f.by)),m=z(()=>f.disabled.value||s.disabled);async function _(x){a("select",x),!x?.defaultPrevented&&!m.value&&x&&(f.onValueChange(s.value),f.changeHighlight(l.value))}function T(x){const P={originalEvent:x,value:s.value};Mt(Fs,_,P)}return Ps({isSelected:y}),(x,P)=>(u(),g(e(i),{value:x.value},{default:c(()=>[Ct([p.value,y.value],()=>v(e(se),M({id:e(r)},x.$attrs,{ref:e(n),role:"option",tabindex:e(f).focusable.value?p.value?"0":"-1":-1,"aria-selected":y.value,as:x.as,"as-child":x.asChild,disabled:m.value?"":void 0,"data-disabled":m.value?"":void 0,"data-highlighted":p.value?"":void 0,"data-state":y.value?"checked":"unchecked",onClick:T,onKeydown:he(Ce(T,["prevent"]),["space"]),onPointermove:P[0]||(P[0]=()=>{e(f).highlightedElement.value!==e(l)&&e(f).highlightOnHover.value&&!e(f).focusable.value&&e(f).changeHighlight(e(l),!1)})}),{default:c(()=>[I(x.$slots,"default")]),_:3},16,["id","tabindex","aria-selected","as","as-child","disabled","data-disabled","data-highlighted","data-state","onKeydown"]),P,1)]),_:3},8,["value"]))}}),Os=Is;const Ls={class:"flex items-center gap-2 truncate"},Ms={class:"truncate"},Ts={key:0,class:"absolute top-full right-0 z-[9999] mt-1 w-[280px] rounded-md border bg-popover p-1 text-popover-foreground shadow-md"},js={class:"max-h-[200px] overflow-y-auto"},zs=["aria-selected","onClick"],Vs={class:"flex flex-1 flex-col gap-0.5 overflow-hidden text-left"},qs={class:"truncate font-medium"},Ks={class:"truncate text-xs text-muted-foreground"},Hs=["onClick"],Us={key:1,class:"px-2 py-1.5 text-sm text-muted-foreground"},Ns={key:2,class:"my-1 h-px bg-border"},Gs={class:"space-y-2"},Ws={class:"flex gap-2"},Xs={key:0,class:"text-sm text-destructive"},Js={key:0,class:"space-y-2 rounded-md border p-3"},Qs={class:"flex items-center gap-2 text-sm"},Ys=["disabled"],Zs={class:"flex-1 truncate font-mono text-xs text-muted-foreground"},eo={class:"max-h-[200px] overflow-y-auto"},to={key:0,class:"py-2 text-center text-sm text-muted-foreground"},so={key:1,class:"py-2 text-center text-sm text-muted-foreground"},oo=["onClick"],ao={class:"truncate"},no={key:0},lo={key:1},ro=D({__name:"RepoSelector",setup(o,{expose:t}){const s=Xe(),a=Le(),{repos:r,currentRepo:i,currentRepoId:n,selectRepo:l,addRepo:f,removeRepo:p}=ke(),{showSuccess:y}=Ze(),m=E(!1),_=E(""),T=E(null);Bt(T,()=>{m.value&&(m.value=!1,_.value="")}),te(()=>a.fullPath,()=>{m.value=!1,_.value=""});async function x(F){l(F),m.value=!1,_.value="";try{const A=(await $fetch(`/api/repos/${F}/prds`))?.[0];A?s.push(`/${F}/${A.slug}`):s.push("/")}catch{s.push("/")}}function P(){m.value=!1,G.value=!0}const j=E(!1),w=E(""),H=E([]),U=E(!1);async function X(F){U.value=!0;try{const b=await $fetch("/api/browse",{query:{path:F||w.value||void 0}});w.value=b.current,H.value=b.directories}catch{}finally{U.value=!1}}function R(){j.value=!0,X(S.value||void 0)}function de(F){S.value=F,j.value=!1,B.value=null}function V(){const F=w.value.split("/").slice(0,-1).join("/")||"/";X(F)}const G=E(!1),S=E(""),B=E(null),O=E(!1),Z=z(()=>{if(!_.value)return r.value;const F=_.value.toLowerCase();return r.value?.filter(b=>b.name.toLowerCase().includes(F)||b.path.toLowerCase().includes(F))??[]});async function be(){if(!S.value.trim()){B.value="Please enter a repository path";return}O.value=!0,B.value=null;try{const F=await f(S.value.trim());if(G.value=!1,S.value="",y("Repository added",F?.name||"Successfully added repository"),F?.id)try{const A=(await $fetch(`/api/repos/${F.id}/prds`))?.[0];A&&s.push(`/${F.id}/${A.slug}`)}catch{}}catch(F){if(F instanceof Error){const b=F;B.value=b.data?.message||F.message}else B.value="Failed to add repository"}finally{O.value=!1}}async function ce(F,b){F.stopPropagation(),await p(b)}function J(){G.value=!1,S.value="",B.value=null}return t({openAddDialog:()=>{G.value=!0}}),(F,b)=>(u(),k("div",{ref_key:"dropdownRef",ref:T,class:"relative"},[d("button",{type:"button",class:"inline-flex h-8 w-[200px] items-center justify-between gap-2 rounded-md border border-input bg-background px-3 text-sm font-normal ring-offset-background transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",onClick:b[0]||(b[0]=A=>m.value=!e(m))},[d("span",Ls,[v(e(os),{class:"size-4 shrink-0 text-muted-foreground"}),d("span",Ms,L(e(i)?.name??"Select repository"),1)]),v(e(Tt),{class:"size-4 shrink-0 opacity-50"})]),e(m)?(u(),k("div",Ts,[kt(d("input",{"onUpdate:modelValue":b[1]||(b[1]=A=>me(_)?_.value=A:null),type:"text",placeholder:"Search repositories...",class:"mb-1 h-9 w-full rounded-md border border-input bg-background px-3 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"},null,512),[[wt,e(_)]]),d("div",js,[e(Z)?.length?(u(!0),k(Y,{key:0},ee(e(Z),A=>(u(),k("div",{key:A.id,class:"group flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm hover:bg-accent hover:text-accent-foreground cursor-pointer",role:"option","aria-selected":e(n)===A.id,onClick:pe=>x(A.id)},[v(e(et),{class:ie(["size-4 shrink-0",e(n)===A.id?"opacity-100":"opacity-0"])},null,8,["class"]),d("div",Vs,[d("span",qs,L(A.name),1),d("span",Ks,L(A.path),1)]),d("button",{type:"button",class:"ml-auto opacity-0 group-hover:opacity-100 p-1 hover:bg-destructive/10 rounded transition-opacity",title:"Remove repository",onClick:pe=>ce(pe,A.id)},[v(e(rs),{class:"size-3.5 text-destructive"})],8,Hs)],8,zs))),128)):(u(),k("div",Us," No repositories found. ")),e(Z)?.length?(u(),k("div",Ns)):K("",!0),d("button",{type:"button",class:"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-accent-foreground",onClick:P},[v(e(jt),{class:"size-4"}),b[5]||(b[5]=d("span",null,"Add repository...",-1))])])])):K("",!0),v(e(zt),{open:e(G),"onUpdate:open":b[4]||(b[4]=A=>G.value=A)},{default:c(()=>[v(e(Vt),{side:"right",class:"flex h-full flex-col",onEscapeKeyDown:J},{default:c(()=>[v(e(qt),{class:"px-6"},{default:c(()=>[v(e(Kt),null,{default:c(()=>[...b[6]||(b[6]=[W("Add Repository",-1)])]),_:1}),v(e(Ht),null,{default:c(()=>[...b[7]||(b[7]=[W(" Enter the absolute path to a repository containing PRD documents. ",-1)])]),_:1})]),_:1}),d("form",{id:"add-repo-form",class:"min-h-0 flex-1 space-y-4 overflow-y-auto px-6",onSubmit:Ce(be,["prevent"])},[d("div",Gs,[b[8]||(b[8]=d("label",{for:"repo-path",class:"text-sm font-medium"}," Repository Path ",-1)),d("div",Ws,[v(e(as),{id:"repo-path",modelValue:e(S),"onUpdate:modelValue":b[2]||(b[2]=A=>me(S)?S.value=A:null),placeholder:"/path/to/your/project","aria-invalid":!!e(B),disabled:e(O),class:"flex-1"},null,8,["modelValue","aria-invalid","disabled"]),v(e(le),{type:"button",variant:"outline",size:"icon",disabled:e(O),onClick:R},{default:c(()=>[v(e(Oe),{class:"size-4"})]),_:1},8,["disabled"])]),e(B)?(u(),k("p",Xs,L(e(B)),1)):K("",!0),b[9]||(b[9]=d("p",{class:"text-xs text-muted-foreground"},[W(" The repository should contain a "),d("code",{class:"rounded bg-muted px-1"},"docs/prd/"),W(" directory with markdown files. ")],-1))]),e(j)?(u(),k("div",Js,[d("div",Qs,[d("button",{type:"button",class:"hover:text-foreground text-muted-foreground",disabled:e(w)==="/",onClick:V}," .. ",8,Ys),d("span",Zs,L(e(w)),1),v(e(le),{type:"button",variant:"ghost",size:"sm",class:"h-7 text-xs",onClick:b[3]||(b[3]=A=>de(e(w)))},{default:c(()=>[...b[10]||(b[10]=[W(" Select ",-1)])]),_:1})]),d("div",eo,[e(U)?(u(),k("div",to," Loading... ")):e(H).length?(u(!0),k(Y,{key:2},ee(e(H),A=>(u(),k("button",{key:A.path,type:"button",class:"flex w-full items-center gap-2 rounded px-2 py-1 text-sm hover:bg-accent",onClick:pe=>X(A.path)},[v(e(Oe),{class:"size-4 text-muted-foreground"}),d("span",ao,L(A.name),1)],8,oo))),128)):(u(),k("div",so," No subdirectories "))])])):K("",!0)],32),v(e(Ut),{class:"px-6 pb-6"},{default:c(()=>[v(e(le),{type:"button",variant:"outline",disabled:e(O),onClick:J},{default:c(()=>[...b[11]||(b[11]=[W(" Cancel ",-1)])]),_:1},8,["disabled"]),v(e(le),{type:"submit",form:"add-repo-form",disabled:e(O)},{default:c(()=>[e(O)?(u(),k("span",no,"Adding...")):(u(),k("span",lo,"Add Repository"))]),_:1},8,["disabled"])]),_:1})]),_:1})]),_:1},8,["open"])],512))}}),io=Object.assign(ro,{__name:"LayoutRepoSelector"}),uo={class:"flex h-full w-64 flex-col border-r border-border bg-background"},co={class:"p-2"},po={key:0,class:"flex items-center justify-center py-8"},fo={key:1,class:"px-2 py-8 text-center"},mo={key:2,class:"px-2 py-8 text-center"},vo={key:3,class:"px-2 py-8 text-center"},ho={key:4,class:"space-y-1"},go={class:"flex-1 truncate"},yo=D({__name:"Sidebar",setup(o){const t=Le(),{prds:s,prdsStatus:a,refreshPrds:r}=Me(),{currentRepoId:i}=ke(),n=z(()=>t.params.prd);function l(f){return n.value===f}return(f,p)=>{const y=ns;return u(),k("aside",uo,[v(e(Nt),{class:"flex-1"},{default:c(()=>[d("div",co,[p[5]||(p[5]=d("h2",{class:"flex h-10 items-center px-2 text-sm font-medium text-muted-foreground"},"Documents",-1)),e(a)==="pending"?(u(),k("div",po,[v(e(Gt),{class:"size-5 animate-spin text-muted-foreground"})])):e(i)?e(a)==="error"?(u(),k("div",mo,[v(e(Wt),{class:"mx-auto size-8 text-destructive/50"}),p[2]||(p[2]=d("p",{class:"mt-2 text-sm text-muted-foreground"}," Failed to load PRDs ",-1)),v(e(le),{variant:"ghost",size:"sm",class:"mt-2",onClick:e(r)},{default:c(()=>[v(e(tt),{class:"mr-1 size-3"}),p[1]||(p[1]=W(" Retry ",-1))]),_:1},8,["onClick"])])):e(s)?.length?(u(),k("nav",ho,[(u(!0),k(Y,null,ee(e(s),m=>(u(),g(y,{key:m.slug,to:`/${e(i)}/${m.slug}`,class:ie(["group flex items-center gap-3 rounded-md px-3 py-2 text-sm transition-colors",[l(m.slug)?"bg-accent text-accent-foreground":"text-muted-foreground hover:bg-accent/50 hover:text-foreground"]])},{default:c(()=>[v(e(Ie),{class:"size-4 shrink-0"}),d("span",go,L(m.name),1),m.hasState&&m.taskCount?(u(),g(e(Xt),{key:0,variant:"secondary",class:"shrink-0 text-xs"},{default:c(()=>[W(L(m.completedCount??0)+"/"+L(m.taskCount),1)]),_:2},1024)):K("",!0)]),_:2},1032,["to","class"]))),128))])):(u(),k("div",vo,[v(e(Ie),{class:"mx-auto size-8 text-muted-foreground/50"}),p[3]||(p[3]=d("p",{class:"mt-2 text-sm text-muted-foreground"}," No PRDs found ",-1)),p[4]||(p[4]=d("p",{class:"mt-1 text-xs text-muted-foreground/70"}," Add .md files to docs/prd/ ",-1))])):(u(),k("div",fo,[...p[0]||(p[0]=[d("p",{class:"text-sm text-muted-foreground"}," Select a repository to view PRDs ",-1)])]))])]),_:1})])}}}),_o=Object.assign(yo,{__name:"LayoutSidebar"}),bo=D({__name:"Command",props:{modelValue:{default:""},defaultValue:{},multiple:{type:Boolean},orientation:{},dir:{},disabled:{type:Boolean},selectionBehavior:{},highlightOnHover:{type:Boolean},by:{},asChild:{type:Boolean},as:{},name:{},required:{type:Boolean},class:{},defaultSearch:{default:""}},emits:["update:modelValue","highlight","entryFocus","leave"],setup(o,{emit:t}){const s=o,a=t,r=Q(s,"class"),i=ue(r,a),n=E(new Map),l=E(new Map),{contains:f}=us({sensitivity:"base"}),p=St({search:s.defaultSearch||"",filtered:{count:0,items:new Map,groups:new Set}});te(()=>s.defaultSearch,m=>{m!==void 0&&(p.search=m)});function y(){if(!p.search){p.filtered.count=n.value.size;return}p.filtered.groups=new Set;let m=0;for(const[_,T]of n.value){const x=f(T,p.search);p.filtered.items.set(_,x?1:0),x&&m++}for(const[_,T]of l.value)for(const x of T)if(p.filtered.items.get(x)>0){p.filtered.groups.add(_);break}p.filtered.count=m}return te(()=>p.search,()=>{y()}),te(()=>n.value.size,()=>{p.search&&y()}),Go({allItems:n,allGroups:l,filterState:p}),(m,_)=>(u(),g(e(xs),M({"data-slot":"command"},e(i),{class:e(N)("bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md",s.class)}),{default:c(()=>[I(m.$slots,"default")]),_:3},16,["class"]))}}),xo=Object.assign(bo,{__name:"UiCommand"}),Co=D({__name:"Dialog",props:{open:{type:Boolean},defaultOpen:{type:Boolean},modal:{type:Boolean}},emits:["update:open"],setup(o,{emit:t}){const r=ue(o,t);return(i,n)=>(u(),g(e(Jt),M({"data-slot":"dialog"},e(r)),{default:c(l=>[I(i.$slots,"default",Be(Ae(l)))]),_:3},16))}}),ut=Object.assign(Co,{__name:"UiDialog"}),ko=D({__name:"DialogClose",props:{asChild:{type:Boolean},as:{}},setup(o){const t=o;return(s,a)=>(u(),g(e(ze),M({"data-slot":"dialog-close"},t),{default:c(()=>[I(s.$slots,"default")]),_:3},16))}});Object.assign(ko,{__name:"UiDialogClose"});const wo=D({__name:"DialogOverlay",props:{forceMount:{type:Boolean},asChild:{type:Boolean},as:{},class:{}},setup(o){const t=o,s=Q(t,"class");return(a,r)=>(u(),g(e(st),M({"data-slot":"dialog-overlay"},e(s),{class:e(N)("data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80",t.class)}),{default:c(()=>[I(a.$slots,"default")]),_:3},16,["class"]))}}),So=Object.assign(wo,{__name:"UiDialogOverlay"}),$o=D({inheritAttrs:!1,__name:"DialogContent",props:{forceMount:{type:Boolean},disableOutsidePointerEvents:{type:Boolean},asChild:{type:Boolean},as:{},class:{},showCloseButton:{type:Boolean,default:!0}},emits:["escapeKeyDown","pointerDownOutside","focusOutside","interactOutside","openAutoFocus","closeAutoFocus"],setup(o,{emit:t}){const s=o,a=t,r=Q(s,"class"),i=ue(r,a);return(n,l)=>(u(),g(e(ot),null,{default:c(()=>[v(So),v(e(at),M({"data-slot":"dialog-content"},{...n.$attrs,...e(i)},{class:e(N)("bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",s.class)}),{default:c(()=>[I(n.$slots,"default"),o.showCloseButton?(u(),g(e(ze),{key:0,"data-slot":"dialog-close",class:"ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"},{default:c(()=>[v(e(nt)),l[0]||(l[0]=d("span",{class:"sr-only"},"Close",-1))]),_:1})):K("",!0)]),_:3},16,["class"])]),_:3}))}}),dt=Object.assign($o,{__name:"UiDialogContent"}),Eo=D({__name:"DialogDescription",props:{asChild:{type:Boolean},as:{},class:{}},setup(o){const t=o,s=Q(t,"class"),a=Se(s);return(r,i)=>(u(),g(e(Qt),M({"data-slot":"dialog-description"},e(a),{class:e(N)("text-muted-foreground text-sm",t.class)}),{default:c(()=>[I(r.$slots,"default")]),_:3},16,["class"]))}}),ct=Object.assign(Eo,{__name:"UiDialogDescription"}),Do=D({__name:"DialogFooter",props:{class:{}},setup(o){const t=o;return(s,a)=>(u(),k("div",{"data-slot":"dialog-footer",class:ie(e(N)("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",t.class))},[I(s.$slots,"default")],2))}});Object.assign(Do,{__name:"UiDialogFooter"});const Ro=D({__name:"DialogHeader",props:{class:{}},setup(o){const t=o;return(s,a)=>(u(),k("div",{"data-slot":"dialog-header",class:ie(e(N)("flex flex-col gap-2 text-center sm:text-left",t.class))},[I(s.$slots,"default")],2))}}),pt=Object.assign(Ro,{__name:"UiDialogHeader"}),Bo=D({inheritAttrs:!1,__name:"DialogScrollContent",props:{forceMount:{type:Boolean},disableOutsidePointerEvents:{type:Boolean},asChild:{type:Boolean},as:{},class:{}},emits:["escapeKeyDown","pointerDownOutside","focusOutside","interactOutside","openAutoFocus","closeAutoFocus"],setup(o,{emit:t}){const s=o,a=t,r=Q(s,"class"),i=ue(r,a);return(n,l)=>(u(),g(e(ot),null,{default:c(()=>[v(e(st),{class:"fixed inset-0 z-50 grid place-items-center overflow-y-auto bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"},{default:c(()=>[v(e(at),M({class:e(N)("relative z-50 grid w-full max-w-lg my-8 gap-4 border border-border bg-background p-6 shadow-lg duration-200 sm:rounded-lg md:w-full",s.class)},{...n.$attrs,...e(i)},{onPointerDownOutside:l[0]||(l[0]=f=>{const p=f.detail.originalEvent,y=p.target;(p.offsetX>y.clientWidth||p.offsetY>y.clientHeight)&&f.preventDefault()})}),{default:c(()=>[I(n.$slots,"default"),v(e(ze),{class:"absolute top-4 right-4 p-0.5 transition-colors rounded-md hover:bg-secondary"},{default:c(()=>[v(e(nt),{class:"w-4 h-4"}),l[1]||(l[1]=d("span",{class:"sr-only"},"Close",-1))]),_:1})]),_:3},16,["class"])]),_:3})]),_:3}))}});Object.assign(Bo,{__name:"UiDialogScrollContent"});const Ao=D({__name:"DialogTitle",props:{asChild:{type:Boolean},as:{},class:{}},setup(o){const t=o,s=Q(t,"class"),a=Se(s);return(r,i)=>(u(),g(e(Yt),M({"data-slot":"dialog-title"},e(a),{class:e(N)("text-lg leading-none font-semibold",t.class)}),{default:c(()=>[I(r.$slots,"default")]),_:3},16,["class"]))}}),ft=Object.assign(Ao,{__name:"UiDialogTitle"}),Fo=D({__name:"DialogTrigger",props:{asChild:{type:Boolean},as:{}},setup(o){const t=o;return(s,a)=>(u(),g(e(Zt),M({"data-slot":"dialog-trigger"},t),{default:c(()=>[I(s.$slots,"default")]),_:3},16))}});Object.assign(Fo,{__name:"UiDialogTrigger"});const Po=D({__name:"CommandDialog",props:{open:{type:Boolean},defaultOpen:{type:Boolean},modal:{type:Boolean},title:{default:"Command Palette"},description:{default:"Search for a command to run..."},defaultSearch:{default:""}},emits:["update:open"],setup(o,{emit:t}){const r=ue(o,t);return(i,n)=>(u(),g(e(ut),Be(Ae(e(r))),{default:c(l=>[v(e(dt),{class:"overflow-hidden p-0","show-close-button":!1},{default:c(()=>[v(e(pt),{class:"sr-only"},{default:c(()=>[v(e(ft),null,{default:c(()=>[W(L(o.title),1)]),_:1}),v(e(ct),null,{default:c(()=>[W(L(o.description),1)]),_:1})]),_:1}),v(xo,{"default-search":o.defaultSearch},{default:c(()=>[I(i.$slots,"default",Be(Ae(l)))]),_:2},1032,["default-search"])]),_:2},1024)]),_:3},16))}}),Io=Object.assign(Po,{__name:"UiCommandDialog"}),Oo=D({__name:"CommandEmpty",props:{asChild:{type:Boolean},as:{},class:{}},setup(o){const t=o,s=Q(t,"class"),{filterState:a}=$e(),r=z(()=>!!a.search&&a.filtered.count===0);return(i,n)=>r.value?(u(),g(e(se),M({key:0,"data-slot":"command-empty"},e(s),{class:e(N)("py-6 text-center text-sm",t.class)}),{default:c(()=>[I(i.$slots,"default")]),_:3},16,["class"])):K("",!0)}}),Lo=Object.assign(Oo,{__name:"UiCommandEmpty"}),Mo=D({__name:"CommandGroup",props:{asChild:{type:Boolean},as:{},class:{},heading:{}},setup(o){const t=o,s=Q(t,"class"),{allGroups:a,filterState:r}=$e(),i=we(),n=z(()=>r.search?r.filtered.groups.has(i):!0);return Xo({id:i}),re(()=>{a.value.has(i)||a.value.set(i,new Set)}),ge(()=>{a.value.delete(i)}),(l,f)=>(u(),g(e(Rs),M(e(s),{id:e(i),"data-slot":"command-group",class:e(N)("text-foreground overflow-hidden p-1",t.class),hidden:n.value?void 0:!0}),{default:c(()=>[o.heading?(u(),g(e(As),{key:0,"data-slot":"command-group-heading",class:"px-2 py-1.5 text-xs font-medium text-muted-foreground"},{default:c(()=>[W(L(o.heading),1)]),_:1})):K("",!0),I(l.$slots,"default")]),_:3},16,["id","class","hidden"]))}}),Re=Object.assign(Mo,{__name:"UiCommandGroup"}),To={"data-slot":"command-input-wrapper",class:"flex h-9 items-center gap-2 border-b px-3"},jo=D({inheritAttrs:!1,__name:"CommandInput",props:{modelValue:{},autoFocus:{type:Boolean},disabled:{type:Boolean},asChild:{type:Boolean},as:{},class:{}},setup(o){const t=o,s=Q(t,"class"),a=Se(s),{filterState:r}=$e(),i=E(null);return re(()=>{ne(()=>{const n=i.value?.$el;if(n&&r.search){const l=r.search.length;n.setSelectionRange(l,l)}})}),(n,l)=>(u(),k("div",To,[v(e(ls),{class:"size-4 shrink-0 opacity-50"}),v(e(Ss),M({ref_key:"inputRef",ref:i},{...e(a),...n.$attrs},{modelValue:e(r).search,"onUpdate:modelValue":l[0]||(l[0]=f=>e(r).search=f),"data-slot":"command-input","auto-focus":"",class:e(N)("placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",t.class)}),null,16,["modelValue","class"])]))}}),zo=Object.assign(jo,{__name:"UiCommandInput"}),Vo=D({__name:"CommandItem",props:{value:{},disabled:{type:Boolean},asChild:{type:Boolean},as:{},class:{}},emits:["select"],setup(o,{emit:t}){const s=o,a=t,r=Q(s,"class"),i=ue(r,a),n=we(),{filterState:l,allItems:f,allGroups:p}=$e(),y=Wo(),m=z(()=>{if(l.search){const x=l.filtered.items.get(n);return x===void 0?!0:x>0}else return!0}),_=E(),T=At(_);return re(()=>{if(!(T.value instanceof HTMLElement))return;f.value.set(n,T.value.textContent??s.value?.toString()??"");const x=y?.id;x&&(p.value.has(x)?p.value.get(x)?.add(n):p.value.set(x,new Set([n])))}),ge(()=>{f.value.delete(n)}),(x,P)=>m.value?(u(),g(e(Os),M({key:0},e(i),{id:e(n),ref_key:"itemRef",ref:_,"data-slot":"command-item",class:e(N)("data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",s.class),onSelect:P[0]||(P[0]=()=>{e(l).search=""})}),{default:c(()=>[I(x.$slots,"default")]),_:3},16,["id","class"])):K("",!0)}}),ae=Object.assign(Vo,{__name:"UiCommandItem"}),qo={role:"presentation"},Ko=D({__name:"CommandList",props:{asChild:{type:Boolean},as:{},class:{}},setup(o){const t=o,s=Q(t,"class"),a=Se(s);return(r,i)=>(u(),g(e(ks),M({"data-slot":"command-list"},e(a),{class:e(N)("max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto scrollbar-none",t.class)}),{default:c(()=>[d("div",qo,[I(r.$slots,"default")])]),_:3},16,["class"]))}}),Ho=Object.assign(Ko,{__name:"UiCommandList"}),Uo=D({__name:"CommandSeparator",props:{orientation:{},decorative:{type:Boolean},asChild:{type:Boolean},as:{},class:{}},setup(o){const t=o,s=Q(t,"class");return(a,r)=>(u(),g(e(es),M({"data-slot":"command-separator"},e(s),{class:e(N)("bg-border -mx-1 h-px",t.class)}),{default:c(()=>[I(a.$slots,"default")]),_:3},16,["class"]))}}),Ne=Object.assign(Uo,{__name:"UiCommandSeparator"}),No=D({__name:"CommandShortcut",props:{class:{}},setup(o){const t=o;return(s,a)=>(u(),k("span",{"data-slot":"command-shortcut",class:ie(e(N)("text-muted-foreground ml-auto text-xs tracking-widest",t.class))},[I(s.$slots,"default")],2))}});Object.assign(No,{__name:"UiCommandShortcut"});const[$e,Go]=_e("Command"),[Wo,Xo]=_e("CommandGroup"),Jo={class:"flex-1"},Qo={class:"flex-1"},Yo={class:"ml-auto flex items-center gap-1"},Zo={class:"inline-flex h-5 min-w-5 items-center justify-center rounded border border-border bg-muted px-1.5 font-mono text-[10px] text-muted-foreground"},ea={class:"flex-1"},ta={class:"ml-auto flex items-center gap-1"},sa={class:"inline-flex h-5 min-w-5 items-center justify-center rounded border border-border bg-muted px-1.5 font-mono text-[10px] text-muted-foreground"},oa={class:"ml-auto flex items-center gap-1"},aa={class:"inline-flex h-5 min-w-5 items-center justify-center rounded border border-border bg-muted px-1.5 font-mono text-[10px] text-muted-foreground"},na=D({__name:"CommandPalette",props:{open:{type:Boolean,default:!1},openModifiers:{},filter:{default:""},filterModifiers:{}},emits:$t(["openShortcutsHelp"],["update:open","update:filter"]),setup(o,{emit:t}){const s=Fe(o,"open"),a=Fe(o,"filter"),r=t,i=Xe(),{themeMode:n,cycleThemeMode:l}=Je(),{prds:f}=Me(),{repos:p,currentRepoId:y,selectRepo:m,refreshGitRepos:_}=ke(),{showSuccess:T,showError:x}=Ze(),P=E("document");{const S=localStorage.getItem("prd-viewer-tab");(S==="document"||S==="board")&&(P.value=S)}function j(S){y.value&&(i.push(`/${y.value}/${S}`),s.value=!1)}function w(S){m(S),i.push("/"),s.value=!1}function H(){l(),s.value=!1}function U(){const S=P.value==="document"?"board":"document";P.value=S,localStorage.setItem("prd-viewer-tab",S),window.dispatchEvent(new StorageEvent("storage",{key:"prd-viewer-tab",newValue:S})),s.value=!1}function X(){s.value=!1,r("openShortcutsHelp")}const R=E(!1);async function de(){if(!(!y.value||R.value)){R.value=!0,s.value=!1;try{const S=await _(y.value);T(`Discovered ${S.discovered} git repositories`)}catch{x("Failed to refresh git repos")}finally{R.value=!1}}}te(s,S=>{S||(a.value="")});const V=z(()=>navigator.platform.toUpperCase().indexOf("MAC")>=0),G=z(()=>V.value?"⌘":"Ctrl");return(S,B)=>(u(),g(e(Io),{open:s.value,"onUpdate:open":B[0]||(B[0]=O=>s.value=O),"default-search":a.value},{default:c(()=>[v(e(zo),{placeholder:"Type a command or search..."}),v(e(Ho),null,{default:c(()=>[v(e(Lo),null,{default:c(()=>[...B[1]||(B[1]=[W("No results found.",-1)])]),_:1}),e(f)?.length?(u(),g(e(Re),{key:0,heading:"Documents"},{default:c(()=>[(u(!0),k(Y,null,ee(e(f),O=>(u(),g(e(ae),{key:O.slug,value:`PRD: ${O.name}`,onSelect:Z=>j(O.slug)},{default:c(()=>[v(e(Ie),{class:"size-4"}),d("span",null,L(O.name),1)]),_:2},1032,["value","onSelect"]))),128))]),_:1})):K("",!0),e(f)?.length&&e(p)?.length?(u(),g(e(Ne),{key:1})):K("",!0),e(p)?.length?(u(),g(e(Re),{key:2,heading:"Repositories"},{default:c(()=>[(u(!0),k(Y,null,ee(e(p),O=>(u(),g(e(ae),{key:O.id,value:`repo-${O.id} ${O.name}`,onSelect:Z=>w(O.id)},{default:c(()=>[v(e(Oe),{class:"size-4"}),d("span",Jo,L(O.name),1),O.id===e(y)?(u(),g(e(et),{key:0,class:"size-4 text-primary"})):K("",!0)]),_:2},1032,["value","onSelect"]))),128))]),_:1})):K("",!0),e(p)?.length?(u(),g(e(Ne),{key:3})):K("",!0),v(e(Re),{heading:"Actions"},{default:c(()=>[v(e(ae),{value:"cycle-theme light dark system",onSelect:H},{default:c(()=>[e(n)==="system"?(u(),g(e(lt),{key:0,class:"size-4"})):e(n)==="light"?(u(),g(e(it),{key:1,class:"size-4"})):(u(),g(e(rt),{key:2,class:"size-4"})),d("span",Qo,"Cycle theme mode ("+L(e(n))+")",1),d("div",Yo,[d("kbd",Zo,L(e(G)),1),B[2]||(B[2]=d("kbd",{class:"inline-flex h-5 min-w-5 items-center justify-center rounded border border-border bg-muted px-1.5 font-mono text-[10px] text-muted-foreground"},".",-1))])]),_:1}),v(e(ae),{value:`switch-tab ${e(P)==="document"?"task board":"document"}`,onSelect:U},{default:c(()=>[v(e(ts),{class:"size-4"}),d("span",ea,"Switch to "+L(e(P)==="document"?"Task Board":"Document"),1),d("div",ta,[d("kbd",sa,L(e(G)),1),B[3]||(B[3]=d("kbd",{class:"inline-flex h-5 min-w-5 items-center justify-center rounded border border-border bg-muted px-1.5 font-mono text-[10px] text-muted-foreground"},"\\",-1))])]),_:1},8,["value"]),v(e(ae),{value:"keyboard shortcuts help",onSelect:X},{default:c(()=>[v(e(ss),{class:"size-4"}),B[5]||(B[5]=d("span",{class:"flex-1"},"Keyboard shortcuts",-1)),d("div",oa,[d("kbd",aa,L(e(G)),1),B[4]||(B[4]=d("kbd",{class:"inline-flex h-5 min-w-5 items-center justify-center rounded border border-border bg-muted px-1.5 font-mono text-[10px] text-muted-foreground"},"/",-1))])]),_:1}),e(y)?(u(),g(e(ae),{key:0,value:"refresh git repos rescan discover",disabled:e(R),onSelect:de},{default:c(()=>[v(e(tt),{class:ie(["size-4",{"animate-spin":e(R)}])},null,8,["class"]),B[6]||(B[6]=d("span",{class:"flex-1"},"Refresh git repos",-1))]),_:1},8,["disabled"])):K("",!0)]),_:1})]),_:1})]),_:1},8,["open","default-search"]))}}),la=Object.assign(na,{__name:"CommandPalette"}),ra={class:"space-y-6"},ia={class:"mb-3 text-sm font-medium text-muted-foreground"},ua={class:"space-y-2"},da={class:"text-sm"},ca={class:"flex items-center gap-1"},pa=D({__name:"ShortcutsHelp",props:{open:{type:Boolean,default:!1},openModifiers:{}},emits:["update:open"],setup(o){const t=Fe(o,"open"),s=z(()=>navigator.platform.toUpperCase().indexOf("MAC")>=0),a=z(()=>s.value?"⌘":"Ctrl"),r=z(()=>[{name:"Navigation",shortcuts:[{keys:[a.value,"K"],description:"Open command palette"},{keys:[a.value,"J"],description:"Quick jump to document"}]},{name:"Actions",shortcuts:[{keys:[a.value,"."],description:"Cycle theme mode (light/dark/system)"},{keys:[a.value,"\\"],description:"Switch between Document and Task Board"},{keys:[a.value,","],description:"Add repository"}]},{name:"Help",shortcuts:[{keys:[a.value,"/"],description:"Show this help"},{keys:["Esc"],description:"Close dialog or palette"}]}]);return(i,n)=>(u(),g(e(ut),{open:t.value,"onUpdate:open":n[0]||(n[0]=l=>t.value=l)},{default:c(()=>[v(e(dt),{class:"max-w-md"},{default:c(()=>[v(e(pt),null,{default:c(()=>[v(e(ft),null,{default:c(()=>[...n[1]||(n[1]=[W("Keyboard Shortcuts",-1)])]),_:1}),v(e(ct),null,{default:c(()=>[...n[2]||(n[2]=[W(" Quick reference for available keyboard shortcuts. ",-1)])]),_:1})]),_:1}),d("div",ra,[(u(!0),k(Y,null,ee(e(r),l=>(u(),k("div",{key:l.name},[d("h3",ia,L(l.name),1),d("div",ua,[(u(!0),k(Y,null,ee(l.shortcuts,f=>(u(),k("div",{key:f.description,class:"flex items-center justify-between"},[d("span",da,L(f.description),1),d("div",ca,[(u(!0),k(Y,null,ee(f.keys,(p,y)=>(u(),k("kbd",{key:y,class:"inline-flex h-5 min-w-5 items-center justify-center rounded border border-border bg-muted px-1.5 font-mono text-xs font-medium text-muted-foreground"},L(p),1))),128))])]))),128))])]))),128))])]),_:1})]),_:1},8,["open"]))}}),fa=Object.assign(pa,{__name:"ShortcutsHelp"});function mt(){const o=document.activeElement;if(!o)return!1;const t=o.tagName.toLowerCase();return t==="input"||t==="textarea"||o.getAttribute("contenteditable")==="true"||o.getAttribute("role")==="textbox"}function ma(o){const t=o.toLowerCase().split("+"),s=t.pop()||"";return{meta:t.includes("meta"),ctrl:t.includes("ctrl"),shift:t.includes("shift"),alt:t.includes("alt"),key:s}}function va(o,t){const s=o.key.toLowerCase();let a=s===t.key;return t.key==="\\"&&(a=s==="\\"||o.code==="Backslash"),t.key==="/"&&(a=s==="/"||o.code==="Slash"),t.key==="."&&(a=s==="."||o.code==="Period"),t.key===","&&(a=s===","||o.code==="Comma"),a&&o.metaKey===t.meta&&o.ctrlKey===t.ctrl&&o.shiftKey===t.shift&&o.altKey===t.alt}const xe=[];let Ge=!1;function ha(o){for(const t of xe)if(va(o,t.combo)){if(!t.allowInInput&&mt())continue;o.preventDefault(),o.stopPropagation(),t.handler();return}}function We(){Ge||(document.addEventListener("keydown",ha,{capture:!0}),Ge=!0)}function ga(){re(()=>{We()});function o(s,a,r){const n={combo:ma(s),handler:a,allowInInput:r?.allowInInput??!1};xe.push(n),We(),ge(()=>{const l=xe.indexOf(n);l>-1&&xe.splice(l,1)})}function t(){return mt()}return{onShortcut:o,isInputFocused:t}}function ya(o){const t=E(null),s=E(!1),a=E(null);function r(){if(!t.value)try{const n=new EventSource("/api/watch");n.onopen=()=>{s.value=!0,a.value=null},n.onmessage=l=>{try{const f=JSON.parse(l.data);o(f)}catch{}},n.onerror=()=>{s.value=!1,a.value="Connection lost",setTimeout(()=>{t.value===n&&(t.value=null,r())},5e3)},t.value=n}catch{a.value="Failed to connect"}}function i(){t.value&&(t.value.close(),t.value=null,s.value=!1)}return re(()=>{r()}),ge(()=>{i()}),{isConnected:s,error:a,connect:r,disconnect:i}}const _a={class:"min-h-screen bg-background text-foreground"},ba={class:"fixed top-0 left-0 right-0 z-50 h-14 border-b border-border bg-background/95 backdrop-blur-sm supports-[backdrop-filter]:bg-background/80"},xa={class:"flex h-full items-center justify-between px-4 md:px-6"},Ca={class:"flex items-center gap-3"},ka={class:"flex h-screen pt-14"},wa={class:"flex-1 overflow-auto"},Aa=D({__name:"default",setup(o){const{themeMode:t,cycleThemeMode:s}=Je(),{refreshPrds:a}=Me(),{currentRepoId:r}=ke(),i=Le(),n=E(null);Et("fileChangeEvent",n);const l=E(!1),f=E(""),p=E(!1),y=E(null),{onShortcut:m}=ga();m("Meta+k",()=>{l.value=!0}),m("Ctrl+k",()=>{l.value=!0}),m("Meta+j",()=>{f.value="PRD: ",l.value=!0}),m("Ctrl+j",()=>{f.value="PRD: ",l.value=!0});function _(){const w=(localStorage.getItem("prd-viewer-tab")||"document")==="document"?"board":"document";localStorage.setItem("prd-viewer-tab",w),window.dispatchEvent(new StorageEvent("storage",{key:"prd-viewer-tab",newValue:w}))}m("Meta+\\",_),m("Ctrl+\\",_);function T(){s()}m("Meta+.",T),m("Ctrl+.",T);function x(){y.value?.openAddDialog()}m("Meta+,",x),m("Ctrl+,",x);function P(){p.value=!0}return m("Meta+/",P),m("Ctrl+/",P),m("Meta+Shift+/",P),m("Ctrl+Shift+/",P),ya(j=>{if(j.type==="connected"||!j.category)return;const w=j.category;if(j.repoId!==r.value)return;(w==="prd"||w==="tasks")&&a();const H=i.params.prd;if(H){const U=w==="prd"&&j.path?.includes(`/${H}.`),X=(w==="tasks"||w==="progress")&&j.path?.includes(`/${H}/`);(U||X)&&(n.value={category:w,path:j.path,timestamp:Date.now()})}}),(j,w)=>{const H=io,U=Dt,X=_o;return u(),k("div",_a,[v(la,{open:e(l),"onUpdate:open":w[0]||(w[0]=R=>me(l)?l.value=R:null),filter:e(f),"onUpdate:filter":w[1]||(w[1]=R=>me(f)?f.value=R:null),onOpenShortcutsHelp:P},null,8,["open","filter"]),v(fa,{open:e(p),"onUpdate:open":w[2]||(w[2]=R=>me(p)?p.value=R:null)},null,8,["open"]),d("header",ba,[d("div",xa,[w[5]||(w[5]=d("div",{class:"flex items-center gap-4"},[d("h1",{class:"text-lg font-semibold tracking-tight"}," PRD Viewer ")],-1)),v(U,null,{fallback:c(()=>[...w[4]||(w[4]=[d("div",{class:"flex items-center gap-3"},[d("div",{class:"h-8 w-[200px] animate-pulse rounded-md bg-muted"}),d("div",{class:"size-9 animate-pulse rounded-md bg-muted"})],-1)])]),default:c(()=>[d("div",Ca,[v(H,{ref_key:"repoSelectorRef",ref:y},null,512),v(e(le),{variant:"ghost",size:"icon",class:"size-9",onClick:T},{default:c(()=>[e(t)==="system"?(u(),g(e(lt),{key:0,class:"size-4"})):e(t)==="light"?(u(),g(e(it),{key:1,class:"size-4"})):(u(),g(e(rt),{key:2,class:"size-4"})),w[3]||(w[3]=d("span",{class:"sr-only"},"Cycle theme mode",-1))]),_:1})])]),_:1})])]),d("div",ka,[v(U,null,{fallback:c(()=>[...w[6]||(w[6]=[d("aside",{class:"flex h-full w-64 flex-col border-r border-border bg-background"},[d("div",{class:"flex h-12 items-center border-b border-border px-4"},[d("div",{class:"h-4 w-20 animate-pulse rounded bg-muted"})]),d("div",{class:"flex-1 p-2 space-y-2"},[d("div",{class:"h-9 animate-pulse rounded-md bg-muted"}),d("div",{class:"h-9 animate-pulse rounded-md bg-muted"}),d("div",{class:"h-9 animate-pulse rounded-md bg-muted"})])],-1)])]),default:c(()=>[v(X)]),_:1}),d("main",wa,[I(j.$slots,"default")])])])}}});export{Aa as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_prd_-JbQLT1IJ.mjs","sources":["../../../../node_modules/.cache/nuxt/.nuxt/dist/server/_nuxt/_prd_-JbQLT1IJ.js"],"names":[],"mappings":"","x_google_ignoreList":[0]}
|