plan-assistant 1.5.0 → 1.6.0-alpha.1
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 +31 -12
- package/build/client/_app/immutable/chunks/{CLpU78SQ.js → 5KpFG7Y3.js} +1 -1
- package/build/client/_app/immutable/chunks/AMggw8F_.js +1 -0
- package/build/client/_app/immutable/chunks/{3hcDFuOy.js → B0Br67Jm.js} +22 -22
- package/build/client/_app/immutable/chunks/{DAI9x5pz.js → BGuzEOEG.js} +1 -1
- package/build/client/_app/immutable/chunks/{C8APfMGc.js → BPC30ZkC.js} +1 -1
- package/build/client/_app/immutable/chunks/{C6lsq0EQ.js → BT-rYp04.js} +1 -1
- package/build/client/_app/immutable/chunks/{CuTEmqRN.js → BXachUYg.js} +1 -1
- package/build/client/_app/immutable/chunks/{BBUci_EN.js → BdxNwExl.js} +1 -1
- package/build/client/_app/immutable/chunks/{BExD98LF.js → Bdy6d4YN.js} +1 -1
- package/build/client/_app/immutable/chunks/{Bv2Fvpd-.js → BkkBWYh4.js} +1 -1
- package/build/client/_app/immutable/chunks/{CtvUvmNP.js → Bmsplg2Y.js} +1 -1
- package/build/client/_app/immutable/chunks/{B7UpUR8j.js → Bn0XLNse.js} +1 -1
- package/build/client/_app/immutable/chunks/{CsdQ7qj_.js → BuxFeYZa.js} +1 -1
- package/build/client/_app/immutable/chunks/{DmIm4oWg.js → C2OLrLCJ.js} +1 -1
- package/build/client/_app/immutable/chunks/C88p_n1l.js +3 -0
- package/build/client/_app/immutable/chunks/{CaQ_EsFt.js → CFomSPzW.js} +1 -1
- package/build/client/_app/immutable/chunks/{DVyAwrwy.js → CFx4VLDw.js} +1 -1
- package/build/client/_app/immutable/chunks/{BP4iV_qy.js → CRUUUIwS.js} +1 -1
- package/build/client/_app/immutable/chunks/{CQ3jUvrt.js → CRuCklg1.js} +1 -1
- package/build/client/_app/immutable/chunks/{PzsI0t6r.js → CUHvMbx0.js} +1 -1
- package/build/client/_app/immutable/chunks/{BE3d1fW1.js → C_5efo6-.js} +1 -1
- package/build/client/_app/immutable/chunks/{DgYrUT6W.js → Cb177sm-.js} +1 -1
- package/build/client/_app/immutable/chunks/{CMEI75WY.js → Cb9ekAV0.js} +1 -1
- package/build/client/_app/immutable/chunks/{Cklag6Wh.js → CdiHcRRA.js} +1 -1
- package/build/client/_app/immutable/chunks/{Bp1XOP3Y.js → CgIOtWnS.js} +1 -1
- package/build/client/_app/immutable/chunks/{Bc8p4D6T.js → CghPw8Xx.js} +1 -1
- package/build/client/_app/immutable/chunks/{BkgST-kf.js → Cmym6IfH.js} +1 -1
- package/build/client/_app/immutable/chunks/{C8TKm6Ie.js → Cvpo3167.js} +1 -1
- package/build/client/_app/immutable/chunks/{BxbztSiI.js → Cy0JyQfD.js} +1 -1
- package/build/client/_app/immutable/chunks/{D-JOz5e5.js → D-0mahX7.js} +1 -1
- package/build/client/_app/immutable/chunks/{DX0JfudZ.js → D8823oiN.js} +1 -1
- package/build/client/_app/immutable/chunks/{60AcEuIB.js → DIjXbgfi.js} +1 -1
- package/build/client/_app/immutable/chunks/{5WozQe49.js → DUIJXtzj.js} +1 -1
- package/build/client/_app/immutable/chunks/{2MoIsY2H.js → DXlvMCt6.js} +1 -1
- package/build/client/_app/immutable/chunks/{DhhVlT3Q.js → Dffa6mVP.js} +1 -1
- package/build/client/_app/immutable/chunks/{DmJI01FD.js → DgzenGSu.js} +1 -1
- package/build/client/_app/immutable/chunks/{DwtNXPRV.js → DqaGnr0n.js} +4 -4
- package/build/client/_app/immutable/chunks/{D82Ibe2Y.js → Drf3oeac.js} +1 -1
- package/build/client/_app/immutable/chunks/{v0r-xbZ1.js → EBvoHjF1.js} +1 -1
- package/build/client/_app/immutable/chunks/{BHlQNJvI.js → Fqo6xqtt.js} +1 -1
- package/build/client/_app/immutable/chunks/QDQklEwM.js +1 -0
- package/build/client/_app/immutable/chunks/{CDe5iF5C.js → Q_gMk3PN.js} +1 -1
- package/build/client/_app/immutable/chunks/{wkCjElX-.js → XHkT9caI.js} +1 -1
- package/build/client/_app/immutable/chunks/{BSmyMpB9.js → Zxe_1j0j.js} +1 -1
- package/build/client/_app/immutable/chunks/{NVoraB0x.js → czbfzgw3.js} +1 -1
- package/build/client/_app/immutable/chunks/{BLkN0eN4.js → mlMCI16G.js} +1 -1
- package/build/client/_app/immutable/chunks/{B5dqmTZt.js → qFFXeAvY.js} +1 -1
- package/build/client/_app/immutable/entry/{app.3iFud8JB.js → app.C_pWXh8R.js} +2 -2
- package/build/client/_app/immutable/entry/start.DfbNX0kb.js +1 -0
- package/build/client/_app/immutable/nodes/{1.DV_Uu5i6.js → 1.DN_p76XO.js} +1 -1
- package/build/client/_app/immutable/nodes/3.B0eShLlr.js +1 -0
- package/build/client/_app/version.json +1 -1
- package/build/server/chunks/{1-B0EuD9t5.js → 1-CEFNOpUG.js} +2 -2
- package/build/server/chunks/{1-B0EuD9t5.js.map → 1-CEFNOpUG.js.map} +1 -1
- package/build/server/chunks/{2-1iFROMDo.js → 2-qGWtN2-9.js} +3 -2
- package/build/server/chunks/{2-1iFROMDo.js.map → 2-qGWtN2-9.js.map} +1 -1
- package/build/server/chunks/{3-ChRVOXhH.js → 3-OUU46X3b.js} +6 -7
- package/build/server/chunks/3-OUU46X3b.js.map +1 -0
- package/build/server/chunks/{_page.svelte-Bg0Bxr-a.js → _page.svelte-DcqVlJwT.js} +13 -11
- package/build/server/chunks/_page.svelte-DcqVlJwT.js.map +1 -0
- package/build/server/chunks/_server.ts-BOWeAYnM.js +13 -0
- package/build/server/chunks/_server.ts-BOWeAYnM.js.map +1 -0
- package/build/server/chunks/{_server.ts-CEtvrNT1.js → _server.ts-BbMhMik1.js} +4 -3
- package/build/server/chunks/_server.ts-BbMhMik1.js.map +1 -0
- package/build/server/chunks/{_server.ts-H4qb8W_h.js → _server.ts-BhmTJZsP.js} +3 -4
- package/build/server/chunks/_server.ts-BhmTJZsP.js.map +1 -0
- package/build/server/chunks/{_server.ts-C91-5A8I.js → _server.ts-BjSxqsHx.js} +5 -7
- package/build/server/chunks/_server.ts-BjSxqsHx.js.map +1 -0
- package/build/server/chunks/{_server.ts-sRxHDQa9.js → _server.ts-C7d7vtwn.js} +3 -2
- package/build/server/chunks/_server.ts-C7d7vtwn.js.map +1 -0
- package/build/server/chunks/{_server.ts-B-Tg4-8H.js → _server.ts-D9nBKsq1.js} +2 -2
- package/build/server/chunks/{_server.ts-B-Tg4-8H.js.map → _server.ts-D9nBKsq1.js.map} +1 -1
- package/build/server/chunks/_server.ts-DTGwAmWz.js +14 -0
- package/build/server/chunks/_server.ts-DTGwAmWz.js.map +1 -0
- package/build/server/chunks/{_server.ts-DLQy-IHP.js → _server.ts-DiMlmks0.js} +2 -2
- package/build/server/chunks/{_server.ts-DLQy-IHP.js.map → _server.ts-DiMlmks0.js.map} +1 -1
- package/build/server/chunks/{hooks.server-rdEjirDu.js → hooks.server-DigZpFgW.js} +4 -3
- package/build/server/chunks/{hooks.server-rdEjirDu.js.map → hooks.server-DigZpFgW.js.map} +1 -1
- package/build/server/chunks/{idle-timer-CouFy_WF.js → idle-timer-BshN5Svi.js} +3 -2
- package/build/server/chunks/idle-timer-BshN5Svi.js.map +1 -0
- package/build/server/chunks/{session-manager-Df52lIJ3.js → session-manager-scAVAR7S.js} +10 -12
- package/build/server/chunks/session-manager-scAVAR7S.js.map +1 -0
- package/build/server/index.js +2 -2
- package/build/server/index.js.map +1 -1
- package/build/server/manifest.js +12 -12
- package/build/server/manifest.js.map +1 -1
- package/dist/cli/commands/clean.js +31 -28
- package/dist/cli/commands/export.js +2 -6
- package/dist/cli/commands/feedback.js +2 -6
- package/dist/cli/commands/status.js +6 -10
- package/dist/cli/commands/stop.js +7 -16
- package/dist/cli/markdown-parser.js +0 -8
- package/dist/cli/markdown-to-plan.js +1 -42
- package/dist/cli/server-client.js +15 -21
- package/dist/cli/session-reader.js +12 -8
- package/dist/cli/session-resolver.js +10 -0
- package/dist/lib/server/session-manager.js +8 -9
- package/dist/lib/utils/status.js +53 -0
- package/package.json +1 -1
- package/build/client/_app/immutable/chunks/CT9cgEPP.js +0 -1
- package/build/client/_app/immutable/chunks/DcuidqoU.js +0 -1
- package/build/client/_app/immutable/chunks/JT4pIYWD.js +0 -3
- package/build/client/_app/immutable/entry/start.CfusPEA0.js +0 -1
- package/build/client/_app/immutable/nodes/3.C2JIlVS_.js +0 -1
- package/build/server/chunks/3-ChRVOXhH.js.map +0 -1
- package/build/server/chunks/_page.svelte-Bg0Bxr-a.js.map +0 -1
- package/build/server/chunks/_server.ts-5D7tHXsH.js +0 -15
- package/build/server/chunks/_server.ts-5D7tHXsH.js.map +0 -1
- package/build/server/chunks/_server.ts-C91-5A8I.js.map +0 -1
- package/build/server/chunks/_server.ts-CEtvrNT1.js.map +0 -1
- package/build/server/chunks/_server.ts-H4qb8W_h.js.map +0 -1
- package/build/server/chunks/_server.ts-VG3gOvsa.js +0 -14
- package/build/server/chunks/_server.ts-VG3gOvsa.js.map +0 -1
- package/build/server/chunks/_server.ts-sRxHDQa9.js.map +0 -1
- package/build/server/chunks/idle-timer-CouFy_WF.js.map +0 -1
- package/build/server/chunks/session-manager-Df52lIJ3.js.map +0 -1
package/build/server/manifest.js
CHANGED
|
@@ -10,12 +10,12 @@ return {
|
|
|
10
10
|
assets: new Set(["favicon.png"]),
|
|
11
11
|
mimeTypes: {".png":"image/png"},
|
|
12
12
|
_: {
|
|
13
|
-
client: {start:"_app/immutable/entry/start.
|
|
13
|
+
client: {start:"_app/immutable/entry/start.DfbNX0kb.js",app:"_app/immutable/entry/app.C_pWXh8R.js",imports:["_app/immutable/entry/start.DfbNX0kb.js","_app/immutable/chunks/C88p_n1l.js","_app/immutable/chunks/CobJHAAW.js","_app/immutable/chunks/DGn8gxMH.js","_app/immutable/entry/app.C_pWXh8R.js","_app/immutable/chunks/Dj-iuGW3.js","_app/immutable/chunks/CobJHAAW.js","_app/immutable/chunks/dRJp6O4P.js","_app/immutable/chunks/BrjAEg64.js","_app/immutable/chunks/DGn8gxMH.js","_app/immutable/chunks/BZQqs639.js","_app/immutable/chunks/C5wtj4WQ.js"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},
|
|
14
14
|
nodes: [
|
|
15
15
|
__memo(() => import('./chunks/0-rXmaDIAK.js')),
|
|
16
|
-
__memo(() => import('./chunks/1-
|
|
17
|
-
__memo(() => import('./chunks/2-
|
|
18
|
-
__memo(() => import('./chunks/3-
|
|
16
|
+
__memo(() => import('./chunks/1-CEFNOpUG.js')),
|
|
17
|
+
__memo(() => import('./chunks/2-qGWtN2-9.js')),
|
|
18
|
+
__memo(() => import('./chunks/3-OUU46X3b.js'))
|
|
19
19
|
],
|
|
20
20
|
remotes: {
|
|
21
21
|
|
|
@@ -33,56 +33,56 @@ return {
|
|
|
33
33
|
pattern: /^\/api\/health\/?$/,
|
|
34
34
|
params: [],
|
|
35
35
|
page: null,
|
|
36
|
-
endpoint: __memo(() => import('./chunks/_server.ts-
|
|
36
|
+
endpoint: __memo(() => import('./chunks/_server.ts-DiMlmks0.js'))
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
39
|
id: "/api/sessions",
|
|
40
40
|
pattern: /^\/api\/sessions\/?$/,
|
|
41
41
|
params: [],
|
|
42
42
|
page: null,
|
|
43
|
-
endpoint: __memo(() => import('./chunks/_server.ts-
|
|
43
|
+
endpoint: __memo(() => import('./chunks/_server.ts-D9nBKsq1.js'))
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
id: "/api/sessions/[sessionId]",
|
|
47
47
|
pattern: /^\/api\/sessions\/([^/]+?)\/?$/,
|
|
48
48
|
params: [{"name":"sessionId","optional":false,"rest":false,"chained":false}],
|
|
49
49
|
page: null,
|
|
50
|
-
endpoint: __memo(() => import('./chunks/_server.ts-
|
|
50
|
+
endpoint: __memo(() => import('./chunks/_server.ts-DTGwAmWz.js'))
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
53
|
id: "/api/sessions/[sessionId]/feedback",
|
|
54
54
|
pattern: /^\/api\/sessions\/([^/]+?)\/feedback\/?$/,
|
|
55
55
|
params: [{"name":"sessionId","optional":false,"rest":false,"chained":false}],
|
|
56
56
|
page: null,
|
|
57
|
-
endpoint: __memo(() => import('./chunks/_server.ts-
|
|
57
|
+
endpoint: __memo(() => import('./chunks/_server.ts-BjSxqsHx.js'))
|
|
58
58
|
},
|
|
59
59
|
{
|
|
60
60
|
id: "/api/sessions/[sessionId]/versions",
|
|
61
61
|
pattern: /^\/api\/sessions\/([^/]+?)\/versions\/?$/,
|
|
62
62
|
params: [{"name":"sessionId","optional":false,"rest":false,"chained":false}],
|
|
63
63
|
page: null,
|
|
64
|
-
endpoint: __memo(() => import('./chunks/_server.ts-
|
|
64
|
+
endpoint: __memo(() => import('./chunks/_server.ts-BOWeAYnM.js'))
|
|
65
65
|
},
|
|
66
66
|
{
|
|
67
67
|
id: "/api/sessions/[sessionId]/versions/[version]",
|
|
68
68
|
pattern: /^\/api\/sessions\/([^/]+?)\/versions\/([^/]+?)\/?$/,
|
|
69
69
|
params: [{"name":"sessionId","optional":false,"rest":false,"chained":false},{"name":"version","optional":false,"rest":false,"chained":false}],
|
|
70
70
|
page: null,
|
|
71
|
-
endpoint: __memo(() => import('./chunks/_server.ts-
|
|
71
|
+
endpoint: __memo(() => import('./chunks/_server.ts-BhmTJZsP.js'))
|
|
72
72
|
},
|
|
73
73
|
{
|
|
74
74
|
id: "/api/shutdown",
|
|
75
75
|
pattern: /^\/api\/shutdown\/?$/,
|
|
76
76
|
params: [],
|
|
77
77
|
page: null,
|
|
78
|
-
endpoint: __memo(() => import('./chunks/_server.ts-
|
|
78
|
+
endpoint: __memo(() => import('./chunks/_server.ts-BbMhMik1.js'))
|
|
79
79
|
},
|
|
80
80
|
{
|
|
81
81
|
id: "/api/sse/[sessionId]",
|
|
82
82
|
pattern: /^\/api\/sse\/([^/]+?)\/?$/,
|
|
83
83
|
params: [{"name":"sessionId","optional":false,"rest":false,"chained":false}],
|
|
84
84
|
page: null,
|
|
85
|
-
endpoint: __memo(() => import('./chunks/_server.ts-
|
|
85
|
+
endpoint: __memo(() => import('./chunks/_server.ts-C7d7vtwn.js'))
|
|
86
86
|
},
|
|
87
87
|
{
|
|
88
88
|
id: "/plan/[sessionId]",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","sources":["../../.svelte-kit/adapter-node/manifest.js"],"sourcesContent":["export const manifest = (() => {\nfunction __memo(fn) {\n\tlet value;\n\treturn () => value ??= (value = fn());\n}\n\nreturn {\n\tappDir: \"_app\",\n\tappPath: \"_app\",\n\tassets: new Set([\"favicon.png\"]),\n\tmimeTypes: {\".png\":\"image/png\"},\n\t_: {\n\t\tclient: {start:\"_app/immutable/entry/start.
|
|
1
|
+
{"version":3,"file":"manifest.js","sources":["../../.svelte-kit/adapter-node/manifest.js"],"sourcesContent":["export const manifest = (() => {\nfunction __memo(fn) {\n\tlet value;\n\treturn () => value ??= (value = fn());\n}\n\nreturn {\n\tappDir: \"_app\",\n\tappPath: \"_app\",\n\tassets: new Set([\"favicon.png\"]),\n\tmimeTypes: {\".png\":\"image/png\"},\n\t_: {\n\t\tclient: {start:\"_app/immutable/entry/start.DfbNX0kb.js\",app:\"_app/immutable/entry/app.C_pWXh8R.js\",imports:[\"_app/immutable/entry/start.DfbNX0kb.js\",\"_app/immutable/chunks/C88p_n1l.js\",\"_app/immutable/chunks/CobJHAAW.js\",\"_app/immutable/chunks/DGn8gxMH.js\",\"_app/immutable/entry/app.C_pWXh8R.js\",\"_app/immutable/chunks/Dj-iuGW3.js\",\"_app/immutable/chunks/CobJHAAW.js\",\"_app/immutable/chunks/dRJp6O4P.js\",\"_app/immutable/chunks/BrjAEg64.js\",\"_app/immutable/chunks/DGn8gxMH.js\",\"_app/immutable/chunks/BZQqs639.js\",\"_app/immutable/chunks/C5wtj4WQ.js\"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},\n\t\tnodes: [\n\t\t\t__memo(() => import('./nodes/0.js')),\n\t\t\t__memo(() => import('./nodes/1.js')),\n\t\t\t__memo(() => import('./nodes/2.js')),\n\t\t\t__memo(() => import('./nodes/3.js'))\n\t\t],\n\t\tremotes: {\n\t\t\t\n\t\t},\n\t\troutes: [\n\t\t\t{\n\t\t\t\tid: \"/\",\n\t\t\t\tpattern: /^\\/$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 2 },\n\t\t\t\tendpoint: null\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/health\",\n\t\t\t\tpattern: /^\\/api\\/health\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/health/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[sessionId]\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/?$/,\n\t\t\t\tparams: [{\"name\":\"sessionId\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_sessionId_/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[sessionId]/feedback\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/feedback\\/?$/,\n\t\t\t\tparams: [{\"name\":\"sessionId\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_sessionId_/feedback/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[sessionId]/versions\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/versions\\/?$/,\n\t\t\t\tparams: [{\"name\":\"sessionId\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_sessionId_/versions/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sessions/[sessionId]/versions/[version]\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/versions\\/([^/]+?)\\/?$/,\n\t\t\t\tparams: [{\"name\":\"sessionId\",\"optional\":false,\"rest\":false,\"chained\":false},{\"name\":\"version\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sessions/_sessionId_/versions/_version_/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/shutdown\",\n\t\t\t\tpattern: /^\\/api\\/shutdown\\/?$/,\n\t\t\t\tparams: [],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/shutdown/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/api/sse/[sessionId]\",\n\t\t\t\tpattern: /^\\/api\\/sse\\/([^/]+?)\\/?$/,\n\t\t\t\tparams: [{\"name\":\"sessionId\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: null,\n\t\t\t\tendpoint: __memo(() => import('./entries/endpoints/api/sse/_sessionId_/_server.ts.js'))\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"/plan/[sessionId]\",\n\t\t\t\tpattern: /^\\/plan\\/([^/]+?)\\/?$/,\n\t\t\t\tparams: [{\"name\":\"sessionId\",\"optional\":false,\"rest\":false,\"chained\":false}],\n\t\t\t\tpage: { layouts: [0,], errors: [1,], leaf: 3 },\n\t\t\t\tendpoint: null\n\t\t\t}\n\t\t],\n\t\tprerendered_routes: new Set([]),\n\t\tmatchers: async () => {\n\t\t\t\n\t\t\treturn { };\n\t\t},\n\t\tserver_assets: {}\n\t}\n}\n})();\n\nexport const prerendered = new Set([]);\n\nexport const base = \"\";"],"names":[],"mappings":"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"}
|
|
@@ -17,33 +17,14 @@ async function confirm(message) {
|
|
|
17
17
|
});
|
|
18
18
|
});
|
|
19
19
|
}
|
|
20
|
-
export
|
|
21
|
-
const dir = typeof args.flags.dir === "string"
|
|
22
|
-
? resolve(args.flags.dir)
|
|
23
|
-
: process.cwd();
|
|
24
|
-
const all = args.flags.all === true;
|
|
25
|
-
const dryRun = args.flags["dry-run"] === true;
|
|
26
|
-
const force = args.flags.force === true;
|
|
27
|
-
const olderThanStr = typeof args.flags["older-than"] === "string"
|
|
28
|
-
? args.flags["older-than"]
|
|
29
|
-
: undefined;
|
|
30
|
-
let olderThanMs = null;
|
|
31
|
-
if (olderThanStr) {
|
|
32
|
-
olderThanMs = parseDuration(olderThanStr);
|
|
33
|
-
if (olderThanMs === null) {
|
|
34
|
-
outputError(`Invalid duration: ${olderThanStr}. Use format like 7d, 24h, 2w`, "INVALID_DURATION");
|
|
35
|
-
throw new CliError(`Invalid duration: ${olderThanStr}`);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
const sessions = findSessionDirs(dir);
|
|
39
|
-
const now = Date.now();
|
|
20
|
+
export function selectSessionsToClean(sessions, options, now = Date.now()) {
|
|
40
21
|
const toRemove = [];
|
|
41
22
|
for (const entry of sessions) {
|
|
42
23
|
const meta = entry.meta;
|
|
43
24
|
if (!meta)
|
|
44
25
|
continue;
|
|
45
26
|
// Orphan detection: markdown file no longer exists
|
|
46
|
-
if (!all && !existsSync(meta.markdownPath)) {
|
|
27
|
+
if (!options.all && !existsSync(meta.markdownPath)) {
|
|
47
28
|
toRemove.push({
|
|
48
29
|
sessionId: entry.sessionId,
|
|
49
30
|
sessionDir: entry.sessionDir,
|
|
@@ -52,14 +33,14 @@ export async function clean(args) {
|
|
|
52
33
|
continue;
|
|
53
34
|
}
|
|
54
35
|
// All flag: remove everything
|
|
55
|
-
if (all) {
|
|
56
|
-
if (olderThanMs) {
|
|
36
|
+
if (options.all) {
|
|
37
|
+
if (options.olderThanMs) {
|
|
57
38
|
const updatedAt = new Date(meta.updatedAt).getTime();
|
|
58
|
-
if (now - updatedAt > olderThanMs) {
|
|
39
|
+
if (now - updatedAt > options.olderThanMs) {
|
|
59
40
|
toRemove.push({
|
|
60
41
|
sessionId: entry.sessionId,
|
|
61
42
|
sessionDir: entry.sessionDir,
|
|
62
|
-
reason: `older than ${olderThanStr}`,
|
|
43
|
+
reason: `older than ${options.olderThanStr}`,
|
|
63
44
|
});
|
|
64
45
|
}
|
|
65
46
|
}
|
|
@@ -73,17 +54,39 @@ export async function clean(args) {
|
|
|
73
54
|
continue;
|
|
74
55
|
}
|
|
75
56
|
// Age-based cleanup
|
|
76
|
-
if (olderThanMs) {
|
|
57
|
+
if (options.olderThanMs) {
|
|
77
58
|
const updatedAt = new Date(meta.updatedAt).getTime();
|
|
78
|
-
if (now - updatedAt > olderThanMs) {
|
|
59
|
+
if (now - updatedAt > options.olderThanMs) {
|
|
79
60
|
toRemove.push({
|
|
80
61
|
sessionId: entry.sessionId,
|
|
81
62
|
sessionDir: entry.sessionDir,
|
|
82
|
-
reason: `older than ${olderThanStr}`,
|
|
63
|
+
reason: `older than ${options.olderThanStr}`,
|
|
83
64
|
});
|
|
84
65
|
}
|
|
85
66
|
}
|
|
86
67
|
}
|
|
68
|
+
return toRemove;
|
|
69
|
+
}
|
|
70
|
+
export async function clean(args) {
|
|
71
|
+
const dir = typeof args.flags.dir === "string"
|
|
72
|
+
? resolve(args.flags.dir)
|
|
73
|
+
: process.cwd();
|
|
74
|
+
const all = args.flags.all === true;
|
|
75
|
+
const dryRun = args.flags["dry-run"] === true;
|
|
76
|
+
const force = args.flags.force === true;
|
|
77
|
+
const olderThanStr = typeof args.flags["older-than"] === "string"
|
|
78
|
+
? args.flags["older-than"]
|
|
79
|
+
: undefined;
|
|
80
|
+
let olderThanMs = null;
|
|
81
|
+
if (olderThanStr) {
|
|
82
|
+
olderThanMs = parseDuration(olderThanStr);
|
|
83
|
+
if (olderThanMs === null) {
|
|
84
|
+
outputError(`Invalid duration: ${olderThanStr}. Use format like 7d, 24h, 2w`, "INVALID_DURATION");
|
|
85
|
+
throw new CliError(`Invalid duration: ${olderThanStr}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const sessions = findSessionDirs(dir);
|
|
89
|
+
const toRemove = selectSessionsToClean(sessions, { all, olderThanMs, olderThanStr });
|
|
87
90
|
if (toRemove.length === 0) {
|
|
88
91
|
outputJson({ removed: 0, sessions: [] }, args.flags.pretty === true);
|
|
89
92
|
return;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { writeFileSync } from "node:fs";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { requireSession } from "../session-resolver.js";
|
|
4
4
|
import { readPlan, readFeedback } from "../session-reader.js";
|
|
5
5
|
import { renderPlanToHtml } from "../export-html.js";
|
|
6
6
|
import { outputError } from "../output.js";
|
|
@@ -11,11 +11,7 @@ export async function exportCmd(args) {
|
|
|
11
11
|
outputError("Please provide a session ID or markdown file path", "MISSING_ARG");
|
|
12
12
|
throw new CliError("Missing session ID or file path");
|
|
13
13
|
}
|
|
14
|
-
const resolved =
|
|
15
|
-
if (!resolved) {
|
|
16
|
-
outputError(`Session not found for: ${idOrFile}`, "NOT_FOUND");
|
|
17
|
-
throw new CliError(`Session not found for: ${idOrFile}`);
|
|
18
|
-
}
|
|
14
|
+
const resolved = requireSession(idOrFile);
|
|
19
15
|
const plan = readPlan(resolved.sessionDir);
|
|
20
16
|
if (!plan) {
|
|
21
17
|
outputError("Could not read plan data", "READ_ERROR");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { requireSession } from "../session-resolver.js";
|
|
2
2
|
import { readFeedback } from "../session-reader.js";
|
|
3
3
|
import { outputJson, outputError } from "../output.js";
|
|
4
4
|
import { CliError } from "../errors.js";
|
|
@@ -8,11 +8,7 @@ export async function feedback(args) {
|
|
|
8
8
|
outputError("Please provide a session ID or markdown file path", "MISSING_ARG");
|
|
9
9
|
throw new CliError("Missing session ID or file path");
|
|
10
10
|
}
|
|
11
|
-
const resolved =
|
|
12
|
-
if (!resolved) {
|
|
13
|
-
outputError(`Session not found for: ${idOrFile}`, "NOT_FOUND");
|
|
14
|
-
throw new CliError(`Session not found for: ${idOrFile}`);
|
|
15
|
-
}
|
|
11
|
+
const resolved = requireSession(idOrFile);
|
|
16
12
|
const feedback = readFeedback(resolved.sessionDir);
|
|
17
13
|
if (!feedback) {
|
|
18
14
|
outputError("No feedback found for this session", "NO_FEEDBACK");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { requireSession } from "../session-resolver.js";
|
|
2
2
|
import { readMeta, readFeedback } from "../session-reader.js";
|
|
3
3
|
import { outputJson, outputError } from "../output.js";
|
|
4
4
|
import { parseDuration } from "../utils.js";
|
|
@@ -49,11 +49,7 @@ export async function status(args) {
|
|
|
49
49
|
outputError("Please provide a session ID or markdown file path", "MISSING_ARG");
|
|
50
50
|
throw new CliError("Missing session ID or file path");
|
|
51
51
|
}
|
|
52
|
-
const resolved =
|
|
53
|
-
if (!resolved) {
|
|
54
|
-
outputError(`Session not found for: ${idOrFile}`, "NOT_FOUND");
|
|
55
|
-
throw new CliError(`Session not found for: ${idOrFile}`);
|
|
56
|
-
}
|
|
52
|
+
const resolved = requireSession(idOrFile);
|
|
57
53
|
const meta = readMeta(resolved.sessionDir);
|
|
58
54
|
if (!meta) {
|
|
59
55
|
outputError(`Could not read session metadata`, "READ_ERROR");
|
|
@@ -65,8 +61,8 @@ export async function status(args) {
|
|
|
65
61
|
const timeoutMs = typeof timeoutStr === "string"
|
|
66
62
|
? (parseDuration(timeoutStr) ?? 30 * 60 * 1000)
|
|
67
63
|
: 30 * 60 * 1000; // 30 min default
|
|
68
|
-
await pollFeedbackStatus(resolved.sessionDir, resolved.sessionId, meta, timeoutMs);
|
|
69
|
-
|
|
64
|
+
const exitCode = await pollFeedbackStatus(resolved.sessionDir, resolved.sessionId, meta, timeoutMs);
|
|
65
|
+
throw new CliExitCode(exitCode);
|
|
70
66
|
}
|
|
71
67
|
const rawFeedback = readFeedback(resolved.sessionDir);
|
|
72
68
|
// Discard feedback from a previous plan version (stale cycle)
|
|
@@ -102,7 +98,7 @@ async function pollFeedbackStatus(sessionDir, sessionId, meta, timeoutMs) {
|
|
|
102
98
|
phaseSummary,
|
|
103
99
|
commentSummary,
|
|
104
100
|
});
|
|
105
|
-
|
|
101
|
+
return exitCode;
|
|
106
102
|
}
|
|
107
103
|
// Watch for changes
|
|
108
104
|
const feedbackPath = join(sessionDir, "feedback.json");
|
|
@@ -131,7 +127,7 @@ async function pollFeedbackStatus(sessionDir, sessionId, meta, timeoutMs) {
|
|
|
131
127
|
phaseSummary,
|
|
132
128
|
commentSummary,
|
|
133
129
|
});
|
|
134
|
-
|
|
130
|
+
resolve(exitCode);
|
|
135
131
|
}
|
|
136
132
|
}
|
|
137
133
|
catch {
|
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import { dirname } from "node:path";
|
|
2
|
-
import {
|
|
3
|
-
import { stopServer, checkHealth, DEFAULT_BASE_PORT, MAX_PORT, } from "../server-client.js";
|
|
4
|
-
import { outputJson
|
|
5
|
-
import { CliError } from "../errors.js";
|
|
2
|
+
import { requireSession } from "../session-resolver.js";
|
|
3
|
+
import { stopServer, checkHealth, fetchWithTimeout, clearLock, DEFAULT_BASE_PORT, MAX_PORT, } from "../server-client.js";
|
|
4
|
+
import { outputJson } from "../output.js";
|
|
6
5
|
export async function stop(args) {
|
|
7
6
|
const target = args.positional[0];
|
|
8
7
|
if (target) {
|
|
9
8
|
// Stop server for a specific session
|
|
10
|
-
const session =
|
|
11
|
-
if (!session) {
|
|
12
|
-
outputError(`Session not found: ${target}`, "NOT_FOUND");
|
|
13
|
-
throw new CliError(`Session not found: ${target}`);
|
|
14
|
-
}
|
|
9
|
+
const session = requireSession(target);
|
|
15
10
|
const parentDir = dirname(session.sessionDir);
|
|
16
11
|
const stopped = await stopServer(parentDir);
|
|
17
12
|
if (stopped) {
|
|
@@ -31,13 +26,8 @@ export async function stop(args) {
|
|
|
31
26
|
const health = await checkHealth(port);
|
|
32
27
|
if (health) {
|
|
33
28
|
try {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
await fetch(`http://localhost:${port}/api/shutdown`, {
|
|
37
|
-
method: "POST",
|
|
38
|
-
signal: controller.signal,
|
|
39
|
-
});
|
|
40
|
-
clearTimeout(timeout);
|
|
29
|
+
await fetchWithTimeout(`http://localhost:${port}/api/shutdown`, { method: "POST" }, 2000);
|
|
30
|
+
clearLock(health.sessionDir);
|
|
41
31
|
results.push({ port, sessionDir: health.sessionDir });
|
|
42
32
|
stopped++;
|
|
43
33
|
}
|
|
@@ -45,6 +35,7 @@ export async function stop(args) {
|
|
|
45
35
|
// Try SIGTERM
|
|
46
36
|
try {
|
|
47
37
|
process.kill(health.pid, "SIGTERM");
|
|
38
|
+
clearLock(health.sessionDir);
|
|
48
39
|
results.push({ port, sessionDir: health.sessionDir });
|
|
49
40
|
stopped++;
|
|
50
41
|
}
|
|
@@ -300,14 +300,6 @@ function detectPhaseHeading(section, allSections, sectionIdx, autoNumber, ctx) {
|
|
|
300
300
|
}
|
|
301
301
|
return null;
|
|
302
302
|
}
|
|
303
|
-
if (!phaseMatch && section.level === 3) {
|
|
304
|
-
const h3Match = tryMatchPhaseHeading(section.heading, autoNumber);
|
|
305
|
-
if (h3Match) {
|
|
306
|
-
ctx.warn(`Phase "${section.heading}" uses h3 instead of h2 — accepted but non-canonical`);
|
|
307
|
-
return h3Match;
|
|
308
|
-
}
|
|
309
|
-
return null;
|
|
310
|
-
}
|
|
311
303
|
return phaseMatch;
|
|
312
304
|
}
|
|
313
305
|
// ── Phase content extraction ─────────────────────────────────────
|
|
@@ -2,7 +2,7 @@ import { Lexer } from "marked";
|
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
import { basename } from "node:path";
|
|
4
4
|
import { generatePhaseFlowDiagram } from "./mermaid-gen.js";
|
|
5
|
-
import { createParseContext, splitIntoSections, tokensToMarkdown, findSection, collectSectionsUntilLevel, parseKeyDiscoveries, parseScopeExclusions, parsePhases, parseTestingStrategy, parseReferences,
|
|
5
|
+
import { createParseContext, splitIntoSections, tokensToMarkdown, findSection, collectSectionsUntilLevel, parseKeyDiscoveries, parseScopeExclusions, parsePhases, parseTestingStrategy, parseReferences, } from "./markdown-parser.js";
|
|
6
6
|
export function sessionIdFromPath(absolutePath) {
|
|
7
7
|
return createHash("sha256").update(absolutePath).digest("hex").slice(0, 8);
|
|
8
8
|
}
|
|
@@ -77,46 +77,6 @@ export function parseMarkdownToPlan(markdown, markdownPath, projectDir, version
|
|
|
77
77
|
// References
|
|
78
78
|
const refsSection = findSection(sections, /^References$/i, 2);
|
|
79
79
|
const references = refsSection ? parseReferences(refsSection.tokens) : [];
|
|
80
|
-
// Collect additional (unrecognized) H2 sections
|
|
81
|
-
const knownH2Indices = new Set();
|
|
82
|
-
for (let i = 0; i < sections.length; i++) {
|
|
83
|
-
if (sections[i].level === 1) {
|
|
84
|
-
knownH2Indices.add(i);
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
if (sections[i].level !== 2)
|
|
88
|
-
continue;
|
|
89
|
-
// Check if it's a known section
|
|
90
|
-
if (KNOWN_SECTION_PATTERNS.some((p) => p.test(sections[i].heading))) {
|
|
91
|
-
knownH2Indices.add(i);
|
|
92
|
-
continue;
|
|
93
|
-
}
|
|
94
|
-
// Check if it was parsed as a phase
|
|
95
|
-
if (phases.some((p) => p.name === sections[i].heading ||
|
|
96
|
-
tryMatchPhaseHeading(sections[i].heading, 0))) {
|
|
97
|
-
knownH2Indices.add(i);
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
const additionalSections = [];
|
|
102
|
-
for (let i = 0; i < sections.length; i++) {
|
|
103
|
-
if (sections[i].level !== 2 || knownH2Indices.has(i))
|
|
104
|
-
continue;
|
|
105
|
-
// Double-check it's not a parsed phase
|
|
106
|
-
const isPhase = phases.some((p) => p.name === sections[i].heading ||
|
|
107
|
-
sections[i].heading.match(new RegExp(`Phase\\s+${p.number}`, "i")));
|
|
108
|
-
if (isPhase)
|
|
109
|
-
continue;
|
|
110
|
-
const subs = collectSectionsUntilLevel(sections, i, 2);
|
|
111
|
-
let content = tokensToMarkdown(sections[i].tokens);
|
|
112
|
-
for (const sub of subs) {
|
|
113
|
-
content += `\n\n${"#".repeat(sub.level)} ${sub.heading}\n\n${tokensToMarkdown(sub.tokens)}`;
|
|
114
|
-
}
|
|
115
|
-
additionalSections.push({
|
|
116
|
-
heading: sections[i].heading,
|
|
117
|
-
content: content.trim(),
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
80
|
const now = new Date().toISOString();
|
|
121
81
|
const plan = {
|
|
122
82
|
schemaVersion: 1,
|
|
@@ -139,7 +99,6 @@ export function parseMarkdownToPlan(markdown, markdownPath, projectDir, version
|
|
|
139
99
|
diagrams,
|
|
140
100
|
testingStrategy,
|
|
141
101
|
references,
|
|
142
|
-
...(additionalSections.length > 0 ? { additionalSections } : {}),
|
|
143
102
|
};
|
|
144
103
|
return { plan, warnings: ctx.warnings };
|
|
145
104
|
}
|
|
@@ -9,19 +9,24 @@ import { spawn, execSync } from "node:child_process";
|
|
|
9
9
|
import { createServer } from "node:net";
|
|
10
10
|
export const DEFAULT_BASE_PORT = 5181;
|
|
11
11
|
export const MAX_PORT = 5199;
|
|
12
|
-
export function
|
|
12
|
+
export async function fetchWithTimeout(url, options, timeoutMs) {
|
|
13
|
+
const controller = new AbortController();
|
|
14
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
15
|
+
try {
|
|
16
|
+
return await fetch(url, { ...options, signal: controller.signal });
|
|
17
|
+
}
|
|
18
|
+
finally {
|
|
19
|
+
clearTimeout(timeout);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function getPackageDir() {
|
|
13
23
|
const thisFile = fileURLToPath(import.meta.url);
|
|
14
24
|
// dist/cli/server-client.js -> package root
|
|
15
25
|
return resolve(dirname(thisFile), "../..");
|
|
16
26
|
}
|
|
17
27
|
export async function checkHealth(port) {
|
|
18
28
|
try {
|
|
19
|
-
const
|
|
20
|
-
const timeout = setTimeout(() => controller.abort(), 500);
|
|
21
|
-
const res = await fetch(`http://localhost:${port}/api/health`, {
|
|
22
|
-
signal: controller.signal,
|
|
23
|
-
});
|
|
24
|
-
clearTimeout(timeout);
|
|
29
|
+
const res = await fetchWithTimeout(`http://localhost:${port}/api/health`, {}, 500);
|
|
25
30
|
if (!res.ok)
|
|
26
31
|
return null;
|
|
27
32
|
return (await res.json());
|
|
@@ -48,7 +53,7 @@ function writeLock(sessionDir, port, pid) {
|
|
|
48
53
|
mkdirSync(sessionDir, { recursive: true });
|
|
49
54
|
writeFileSync(lockFilePath(sessionDir), JSON.stringify({ port, pid }));
|
|
50
55
|
}
|
|
51
|
-
function clearLock(sessionDir) {
|
|
56
|
+
export function clearLock(sessionDir) {
|
|
52
57
|
try {
|
|
53
58
|
unlinkSync(lockFilePath(sessionDir));
|
|
54
59
|
}
|
|
@@ -134,12 +139,7 @@ function startServer(sessionDir, port) {
|
|
|
134
139
|
const interval = setInterval(async () => {
|
|
135
140
|
attempts++;
|
|
136
141
|
try {
|
|
137
|
-
const
|
|
138
|
-
const timeout = setTimeout(() => controller.abort(), 1000);
|
|
139
|
-
const res = await fetch(`http://localhost:${port}/api/health`, {
|
|
140
|
-
signal: controller.signal,
|
|
141
|
-
});
|
|
142
|
-
clearTimeout(timeout);
|
|
142
|
+
const res = await fetchWithTimeout(`http://localhost:${port}/api/health`, {}, 1000);
|
|
143
143
|
if (res.ok) {
|
|
144
144
|
clearInterval(interval);
|
|
145
145
|
resolvePromise(pid);
|
|
@@ -166,13 +166,7 @@ export async function stopServer(sessionDir) {
|
|
|
166
166
|
const port = lock?.port;
|
|
167
167
|
if (port) {
|
|
168
168
|
try {
|
|
169
|
-
|
|
170
|
-
const timeout = setTimeout(() => controller.abort(), 2000);
|
|
171
|
-
await fetch(`http://localhost:${port}/api/shutdown`, {
|
|
172
|
-
method: "POST",
|
|
173
|
-
signal: controller.signal,
|
|
174
|
-
});
|
|
175
|
-
clearTimeout(timeout);
|
|
169
|
+
await fetchWithTimeout(`http://localhost:${port}/api/shutdown`, { method: "POST" }, 2000);
|
|
176
170
|
clearLock(sessionDir);
|
|
177
171
|
return true;
|
|
178
172
|
}
|
|
@@ -94,14 +94,18 @@ export async function awaitReviewFeedback(feedbackPath, sessionId, planTitle, md
|
|
|
94
94
|
const fbWatcher = watch(feedbackPath, {
|
|
95
95
|
awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 100 },
|
|
96
96
|
});
|
|
97
|
+
const cleanup = () => {
|
|
98
|
+
fbWatcher.close();
|
|
99
|
+
mdWatcher.close();
|
|
100
|
+
process.removeListener("SIGINT", onSigint);
|
|
101
|
+
};
|
|
97
102
|
const check = async () => {
|
|
98
103
|
try {
|
|
99
104
|
if (!existsSync(feedbackPath))
|
|
100
105
|
return;
|
|
101
106
|
const data = JSON.parse(readFileSync(feedbackPath, "utf-8"));
|
|
102
107
|
if (data.status === "approved" || data.status === "needs-work") {
|
|
103
|
-
|
|
104
|
-
mdWatcher.close();
|
|
108
|
+
cleanup();
|
|
105
109
|
await outputFeedbackResult(data, sessionId, planTitle, sessionDir);
|
|
106
110
|
resolve();
|
|
107
111
|
}
|
|
@@ -110,13 +114,13 @@ export async function awaitReviewFeedback(feedbackPath, sessionId, planTitle, md
|
|
|
110
114
|
/* ignore parse errors during writes */
|
|
111
115
|
}
|
|
112
116
|
};
|
|
117
|
+
const onSigint = () => {
|
|
118
|
+
cleanup();
|
|
119
|
+
console.error("\nStopped watching.");
|
|
120
|
+
throw new CliExitCode(0);
|
|
121
|
+
};
|
|
113
122
|
fbWatcher.on("change", check);
|
|
114
123
|
fbWatcher.on("add", check);
|
|
115
|
-
process.on("SIGINT",
|
|
116
|
-
fbWatcher.close();
|
|
117
|
-
mdWatcher.close();
|
|
118
|
-
console.error("\nStopped watching.");
|
|
119
|
-
process.exit(0);
|
|
120
|
-
});
|
|
124
|
+
process.on("SIGINT", onSigint);
|
|
121
125
|
});
|
|
122
126
|
}
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
import { existsSync } from "node:fs";
|
|
9
9
|
import { resolve, dirname, join } from "node:path";
|
|
10
10
|
import { sessionIdFromPath } from "./markdown-to-plan.js";
|
|
11
|
+
import { outputError } from "./output.js";
|
|
12
|
+
import { CliError } from "./errors.js";
|
|
11
13
|
const SESSION_ID_PATTERN = /^[0-9a-f]{8}$/i;
|
|
12
14
|
export function resolveSession(idOrFile) {
|
|
13
15
|
// Strategy 1: File path
|
|
@@ -36,3 +38,11 @@ export function resolveSession(idOrFile) {
|
|
|
36
38
|
}
|
|
37
39
|
return null;
|
|
38
40
|
}
|
|
41
|
+
export function requireSession(idOrFile) {
|
|
42
|
+
const resolved = resolveSession(idOrFile);
|
|
43
|
+
if (!resolved) {
|
|
44
|
+
outputError(`Session not found for: ${idOrFile}`, "NOT_FOUND");
|
|
45
|
+
throw new CliError(`Session not found for: ${idOrFile}`);
|
|
46
|
+
}
|
|
47
|
+
return resolved;
|
|
48
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync, } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
|
+
import { error } from "@sveltejs/kit";
|
|
4
5
|
/**
|
|
5
6
|
* Session storage root directory.
|
|
6
7
|
*
|
|
@@ -59,6 +60,12 @@ export function listSessions() {
|
|
|
59
60
|
export function getSession(sessionId) {
|
|
60
61
|
return readMeta(getSessionDir(sessionId));
|
|
61
62
|
}
|
|
63
|
+
export function requireSession(sessionId) {
|
|
64
|
+
const session = getSession(sessionId);
|
|
65
|
+
if (!session)
|
|
66
|
+
throw error(404, "Session not found");
|
|
67
|
+
return session;
|
|
68
|
+
}
|
|
62
69
|
export function createSession(sessionId, meta) {
|
|
63
70
|
const dir = getSessionDir(sessionId);
|
|
64
71
|
mkdirSync(dir, { recursive: true });
|
|
@@ -104,13 +111,5 @@ export function updateSessionStatus(sessionId, status) {
|
|
|
104
111
|
writeFileSync(join(getSessionDir(sessionId), "meta.json"), JSON.stringify(updated, null, 2));
|
|
105
112
|
}
|
|
106
113
|
export function getVersion(sessionId, version) {
|
|
107
|
-
|
|
108
|
-
if (!existsSync(versionPath))
|
|
109
|
-
return null;
|
|
110
|
-
try {
|
|
111
|
-
return JSON.parse(readFileSync(versionPath, "utf-8"));
|
|
112
|
-
}
|
|
113
|
-
catch {
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
114
|
+
return readJsonFile(join(getSessionDir(sessionId), "versions", `v${version}.json`));
|
|
116
115
|
}
|