plan-assistant 1.3.4 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/build/client/_app/immutable/chunks/{BJs6I7qC.js → 10ZXP06Q.js} +1 -1
  2. package/build/client/_app/immutable/chunks/{ChJyFfSj.js → 1eL0zcBS.js} +1 -1
  3. package/build/client/_app/immutable/chunks/74GYr5Jz.js +3 -0
  4. package/build/client/_app/immutable/chunks/{B2fFwvWw.js → B-HTmPy1.js} +1 -1
  5. package/build/client/_app/immutable/chunks/{RIGBV7Ip.js → B2hVYoEJ.js} +1 -1
  6. package/build/client/_app/immutable/chunks/{DVXd8vwC.js → B628eJGB.js} +1 -1
  7. package/build/client/_app/immutable/chunks/{CpucjHJL.js → B80ongyB.js} +1 -1
  8. package/build/client/_app/immutable/chunks/{BXCtgyOT.js → B8FhIQG1.js} +1 -1
  9. package/build/client/_app/immutable/chunks/{DoIz7SoC.js → BCgSWfby.js} +1 -1
  10. package/build/client/_app/immutable/chunks/{B-25Ue8o.js → BFl4ofgi.js} +4 -4
  11. package/build/client/_app/immutable/chunks/{DK1zqZrn.js → BIKGXasq.js} +1 -1
  12. package/build/client/_app/immutable/chunks/{DlbZX2EZ.js → BNv9nR-i.js} +1 -1
  13. package/build/client/_app/immutable/chunks/{CeIvvAVV.js → BOjlNXC_.js} +1 -1
  14. package/build/client/_app/immutable/chunks/{a5eoTq-5.js → BRBMkxQw.js} +1 -1
  15. package/build/client/_app/immutable/chunks/{_2rlQOMN.js → BT3ImTYg.js} +1 -1
  16. package/build/client/_app/immutable/chunks/{BJxAjYQA.js → BUu_XsOv.js} +1 -1
  17. package/build/client/_app/immutable/chunks/{B9WViv7H.js → BVq6bo_n.js} +1 -1
  18. package/build/client/_app/immutable/chunks/{DteI5BLO.js → BZQqs639.js} +1 -1
  19. package/build/client/_app/immutable/chunks/{nFhgrnCT.js → BZTb6H6F.js} +1 -1
  20. package/build/client/_app/immutable/chunks/{Dl-inTne.js → BrjAEg64.js} +1 -1
  21. package/build/client/_app/immutable/chunks/{DSIQf7-a.js → Bt3MWn7w.js} +26 -26
  22. package/build/client/_app/immutable/chunks/{Dnz2r_pS.js → BvzznBFq.js} +1 -1
  23. package/build/client/_app/immutable/chunks/{DshYkidx.js → C4gCk_ik.js} +1 -1
  24. package/build/client/_app/immutable/chunks/{2wZlHG5k.js → C5wtj4WQ.js} +1 -1
  25. package/build/client/_app/immutable/chunks/{Dvli4fnO.js → CEqaJ7Yk.js} +1 -1
  26. package/build/client/_app/immutable/chunks/{3E04qp8C.js → CIGAXayx.js} +1 -1
  27. package/build/client/_app/immutable/chunks/COggdvXA.js +1 -0
  28. package/build/client/_app/immutable/chunks/{C47KpwkC.js → CYQe9sJG.js} +1 -1
  29. package/build/client/_app/immutable/chunks/{BrX0OiHa.js → CYxrEvMN.js} +1 -1
  30. package/build/client/_app/immutable/chunks/{CUqNPCjK.js → CaLUaLKT.js} +1 -1
  31. package/build/client/_app/immutable/chunks/{Cwd5DdSa.js → CdHvJ4_w.js} +1 -1
  32. package/build/client/_app/immutable/chunks/{CJ-lpX9h.js → Ckyou5Od.js} +1 -1
  33. package/build/client/_app/immutable/chunks/{C1YAjCKh.js → CmrXQ7MQ.js} +1 -1
  34. package/build/client/_app/immutable/chunks/{BWYga5zO.js → Cn53TYFN.js} +1 -1
  35. package/build/client/_app/immutable/chunks/{CD_kQCcy.js → CobJHAAW.js} +1 -1
  36. package/build/client/_app/immutable/chunks/{B51GwAfL.js → CpHaxpYy.js} +1 -1
  37. package/build/client/_app/immutable/chunks/{BdoKnygS.js → CuD0M7ml.js} +2 -2
  38. package/build/client/_app/immutable/chunks/{BfABZbDO.js → DGn8gxMH.js} +1 -1
  39. package/build/client/_app/immutable/chunks/{CbTVVa30.js → DJ4TnckQ.js} +1 -1
  40. package/build/client/_app/immutable/chunks/{C_qF9Ll1.js → DL-S4jBj.js} +1 -1
  41. package/build/client/_app/immutable/chunks/{ioQlYLW1.js → DLTGIy2S.js} +1 -1
  42. package/build/client/_app/immutable/chunks/{EodvFm9d.js → DcaEnsuI.js} +1 -1
  43. package/build/client/_app/immutable/chunks/{CH1RPLU9.js → DhPQR3Px.js} +1 -1
  44. package/build/client/_app/immutable/chunks/{gzN3DgKu.js → Dik5m9U4.js} +1 -1
  45. package/build/client/_app/immutable/chunks/{DSQnKfn-.js → Dj-iuGW3.js} +1 -1
  46. package/build/client/_app/immutable/chunks/{DePvhy8M.js → MQLxN4-w.js} +1 -1
  47. package/build/client/_app/immutable/chunks/{SbhBQTvy.js → N5edR_wk.js} +1 -1
  48. package/build/client/_app/immutable/chunks/{k7j8NQjk.js → NMQ8yb5B.js} +1 -1
  49. package/build/client/_app/immutable/chunks/{DJe5QTzh.js → S5LArjpJ.js} +1 -1
  50. package/build/client/_app/immutable/chunks/{CgJVu5ra.js → SsCjYNSL.js} +1 -1
  51. package/build/client/_app/immutable/chunks/UguYSyR_.js +1 -0
  52. package/build/client/_app/immutable/chunks/{CkIr3n4I.js → aOKoOpNt.js} +1 -1
  53. package/build/client/_app/immutable/chunks/{wOfVBGZS.js → dRJp6O4P.js} +1 -1
  54. package/build/client/_app/immutable/chunks/{CJ4vuw4Q.js → nlEqX7_u.js} +1 -1
  55. package/build/client/_app/immutable/chunks/{lFo8pWTB.js → q-tJjDlp.js} +1 -1
  56. package/build/client/_app/immutable/entry/{app.xXlXisbW.js → app.BR7HPYnZ.js} +2 -2
  57. package/build/client/_app/immutable/entry/start.DbhlkFfd.js +1 -0
  58. package/build/client/_app/immutable/nodes/0.BDKx-zUI.js +1 -0
  59. package/build/client/_app/immutable/nodes/{1.CduF9YQo.js → 1.B_9JaBUL.js} +1 -1
  60. package/build/client/_app/immutable/nodes/{2.ZFWOqsMm.js → 2.D_8Y7w6T.js} +1 -1
  61. package/build/client/_app/immutable/nodes/3.sgWOIIcg.js +1 -0
  62. package/build/client/_app/version.json +1 -1
  63. package/build/server/chunks/{0-F8UDIQlw.js → 0-C94QRPbG.js} +2 -2
  64. package/build/server/chunks/{0-F8UDIQlw.js.map → 0-C94QRPbG.js.map} +1 -1
  65. package/build/server/chunks/1-G6vwI4Kc.js +9 -0
  66. package/build/server/chunks/{1-YUd-zKqx.js.map → 1-G6vwI4Kc.js.map} +1 -1
  67. package/build/server/chunks/{2-tND4IT0j.js → 2-Cy9PX2zK.js} +2 -2
  68. package/build/server/chunks/{2-tND4IT0j.js.map → 2-Cy9PX2zK.js.map} +1 -1
  69. package/build/server/chunks/{3-DzwYMPfw.js → 3-CxxgkGJa.js} +3 -3
  70. package/build/server/chunks/{3-DzwYMPfw.js.map → 3-CxxgkGJa.js.map} +1 -1
  71. package/build/server/chunks/{_page.svelte-BXgDoamA.js → _page.svelte-DdQY1QqH.js} +62 -3
  72. package/build/server/chunks/_page.svelte-DdQY1QqH.js.map +1 -0
  73. package/build/server/chunks/_server.ts-CEtvrNT1.js +13 -0
  74. package/build/server/chunks/_server.ts-CEtvrNT1.js.map +1 -0
  75. package/build/server/chunks/{_server.ts-p_sHg72N.js → _server.ts-sRxHDQa9.js} +2 -2
  76. package/build/server/chunks/{_server.ts-p_sHg72N.js.map → _server.ts-sRxHDQa9.js.map} +1 -1
  77. package/build/server/chunks/{hooks.server-CeNxBnIX.js → hooks.server-sBuk2932.js} +12 -2
  78. package/build/server/chunks/hooks.server-sBuk2932.js.map +1 -0
  79. package/build/server/chunks/idle-timer-CouFy_WF.js +49 -0
  80. package/build/server/chunks/idle-timer-CouFy_WF.js.map +1 -0
  81. package/build/server/chunks/{sse-manager-DpUiK2jt.js → sse-manager-C9ZLI_Nx.js} +13 -2
  82. package/build/server/chunks/sse-manager-C9ZLI_Nx.js.map +1 -0
  83. package/build/server/index.js +22 -3
  84. package/build/server/index.js.map +1 -1
  85. package/build/server/manifest.js +13 -6
  86. package/build/server/manifest.js.map +1 -1
  87. package/dist/cli/commands/review.js +34 -233
  88. package/dist/cli/commands/stop.js +64 -0
  89. package/dist/cli/index.js +7 -0
  90. package/dist/cli/server-client.js +209 -0
  91. package/dist/cli/session-reader.js +70 -1
  92. package/package.json +1 -1
  93. package/build/client/_app/immutable/chunks/BHAhR-ZH.js +0 -3
  94. package/build/client/_app/immutable/chunks/BPkIOP5x.js +0 -1
  95. package/build/client/_app/immutable/chunks/QMxLvN9k.js +0 -1
  96. package/build/client/_app/immutable/entry/start.C6hZEWOp.js +0 -1
  97. package/build/client/_app/immutable/nodes/0.BZ6p9IRV.js +0 -1
  98. package/build/client/_app/immutable/nodes/3.CfL49yTp.js +0 -1
  99. package/build/server/chunks/1-YUd-zKqx.js +0 -9
  100. package/build/server/chunks/_page.svelte-BXgDoamA.js.map +0 -1
  101. package/build/server/chunks/hooks.server-CeNxBnIX.js.map +0 -1
  102. package/build/server/chunks/sse-manager-DpUiK2jt.js.map +0 -1
@@ -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.C6hZEWOp.js",app:"_app/immutable/entry/app.xXlXisbW.js",imports:["_app/immutable/entry/start.C6hZEWOp.js","_app/immutable/chunks/BHAhR-ZH.js","_app/immutable/chunks/CD_kQCcy.js","_app/immutable/chunks/BfABZbDO.js","_app/immutable/entry/app.xXlXisbW.js","_app/immutable/chunks/DSQnKfn-.js","_app/immutable/chunks/CD_kQCcy.js","_app/immutable/chunks/wOfVBGZS.js","_app/immutable/chunks/Dl-inTne.js","_app/immutable/chunks/BfABZbDO.js","_app/immutable/chunks/DteI5BLO.js","_app/immutable/chunks/2wZlHG5k.js"],stylesheets:[],fonts:[],uses_env_dynamic_public:false},
13
+ client: {start:"_app/immutable/entry/start.DbhlkFfd.js",app:"_app/immutable/entry/app.BR7HPYnZ.js",imports:["_app/immutable/entry/start.DbhlkFfd.js","_app/immutable/chunks/74GYr5Jz.js","_app/immutable/chunks/CobJHAAW.js","_app/immutable/chunks/DGn8gxMH.js","_app/immutable/entry/app.BR7HPYnZ.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
- __memo(() => import('./chunks/0-F8UDIQlw.js')),
16
- __memo(() => import('./chunks/1-YUd-zKqx.js')),
17
- __memo(() => import('./chunks/2-tND4IT0j.js')),
18
- __memo(() => import('./chunks/3-DzwYMPfw.js'))
15
+ __memo(() => import('./chunks/0-C94QRPbG.js')),
16
+ __memo(() => import('./chunks/1-G6vwI4Kc.js')),
17
+ __memo(() => import('./chunks/2-Cy9PX2zK.js')),
18
+ __memo(() => import('./chunks/3-CxxgkGJa.js'))
19
19
  ],
20
20
  remotes: {
21
21
 
@@ -77,12 +77,19 @@ return {
77
77
  page: null,
78
78
  endpoint: __memo(() => import('./chunks/_server.ts-b4ynvdd4.js'))
79
79
  },
80
+ {
81
+ id: "/api/shutdown",
82
+ pattern: /^\/api\/shutdown\/?$/,
83
+ params: [],
84
+ page: null,
85
+ endpoint: __memo(() => import('./chunks/_server.ts-CEtvrNT1.js'))
86
+ },
80
87
  {
81
88
  id: "/api/sse/[sessionId]",
82
89
  pattern: /^\/api\/sse\/([^/]+?)\/?$/,
83
90
  params: [{"name":"sessionId","optional":false,"rest":false,"chained":false}],
84
91
  page: null,
85
- endpoint: __memo(() => import('./chunks/_server.ts-p_sHg72N.js'))
92
+ endpoint: __memo(() => import('./chunks/_server.ts-sRxHDQa9.js'))
86
93
  },
87
94
  {
88
95
  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.C6hZEWOp.js\",app:\"_app/immutable/entry/app.xXlXisbW.js\",imports:[\"_app/immutable/entry/start.C6hZEWOp.js\",\"_app/immutable/chunks/BHAhR-ZH.js\",\"_app/immutable/chunks/CD_kQCcy.js\",\"_app/immutable/chunks/BfABZbDO.js\",\"_app/immutable/entry/app.xXlXisbW.js\",\"_app/immutable/chunks/DSQnKfn-.js\",\"_app/immutable/chunks/CD_kQCcy.js\",\"_app/immutable/chunks/wOfVBGZS.js\",\"_app/immutable/chunks/Dl-inTne.js\",\"_app/immutable/chunks/BfABZbDO.js\",\"_app/immutable/chunks/DteI5BLO.js\",\"_app/immutable/chunks/2wZlHG5k.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]/approve\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/approve\\/?$/,\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_/approve/_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/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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"}
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.DbhlkFfd.js\",app:\"_app/immutable/entry/app.BR7HPYnZ.js\",imports:[\"_app/immutable/entry/start.DbhlkFfd.js\",\"_app/immutable/chunks/74GYr5Jz.js\",\"_app/immutable/chunks/CobJHAAW.js\",\"_app/immutable/chunks/DGn8gxMH.js\",\"_app/immutable/entry/app.BR7HPYnZ.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]/approve\",\n\t\t\t\tpattern: /^\\/api\\/sessions\\/([^/]+?)\\/approve\\/?$/,\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_/approve/_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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"}
@@ -1,179 +1,10 @@
1
- import { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync } from "node:fs";
1
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync, } from "node:fs";
2
2
  import { resolve, dirname, join } from "node:path";
3
- import { fileURLToPath } from "node:url";
4
- import { spawn, execSync } from "node:child_process";
5
- import { createServer } from "node:net";
6
3
  import { watch } from "chokidar";
7
4
  import { parseMarkdownToPlan, sessionIdFromPath } from "../markdown-to-plan.js";
8
5
  import { outputJson } from "../output.js";
9
- const EXIT_APPROVED = 0;
10
- const EXIT_NEEDS_WORK = 3;
11
- const DEFAULT_BASE_PORT = 5181;
12
- const MAX_PORT = 5199;
13
- function getPackageDir() {
14
- const thisFile = fileURLToPath(import.meta.url);
15
- // dist/cli/commands/review.js -> package root
16
- return resolve(dirname(thisFile), "../../..");
17
- }
18
- async function checkHealth(port) {
19
- try {
20
- const controller = new AbortController();
21
- const timeout = setTimeout(() => controller.abort(), 500);
22
- const res = await fetch(`http://localhost:${port}/api/health`, {
23
- signal: controller.signal,
24
- });
25
- clearTimeout(timeout);
26
- if (!res.ok)
27
- return null;
28
- return (await res.json());
29
- }
30
- catch {
31
- return null;
32
- }
33
- }
34
- function lockFilePath(sessionDir) {
35
- return join(sessionDir, ".server-lock.json");
36
- }
37
- function readLock(sessionDir) {
38
- const lockPath = lockFilePath(sessionDir);
39
- if (!existsSync(lockPath))
40
- return null;
41
- try {
42
- return JSON.parse(readFileSync(lockPath, "utf-8"));
43
- }
44
- catch {
45
- return null;
46
- }
47
- }
48
- function writeLock(sessionDir, port, pid) {
49
- mkdirSync(sessionDir, { recursive: true });
50
- writeFileSync(lockFilePath(sessionDir), JSON.stringify({ port, pid }));
51
- }
52
- function clearLock(sessionDir) {
53
- try {
54
- unlinkSync(lockFilePath(sessionDir));
55
- }
56
- catch {
57
- // ignore
58
- }
59
- }
60
- function isPidAlive(pid) {
61
- try {
62
- process.kill(pid, 0);
63
- return true;
64
- }
65
- catch {
66
- return false;
67
- }
68
- }
69
- async function findExistingServer(sessionDir, basePort) {
70
- // Check lock file first (fast path, avoids port scan race)
71
- const lock = readLock(sessionDir);
72
- if (lock) {
73
- if (isPidAlive(lock.pid)) {
74
- const health = await checkHealth(lock.port);
75
- if (health && health.sessionDir === sessionDir) {
76
- return lock.port;
77
- }
78
- }
79
- // Stale lock — remove it
80
- clearLock(sessionDir);
81
- }
82
- // Fallback: scan ports (handles lock-less legacy servers)
83
- for (let port = basePort; port <= MAX_PORT; port++) {
84
- const health = await checkHealth(port);
85
- if (health && health.sessionDir === sessionDir) {
86
- return port;
87
- }
88
- }
89
- return null;
90
- }
91
- function isPortFree(port) {
92
- return new Promise((resolve) => {
93
- const server = createServer();
94
- server.once("error", () => resolve(false));
95
- server.once("listening", () => {
96
- server.close(() => resolve(true));
97
- });
98
- server.listen(port, "127.0.0.1");
99
- });
100
- }
101
- async function findFreePort(basePort) {
102
- for (let port = basePort; port <= MAX_PORT; port++) {
103
- if (await isPortFree(port))
104
- return port;
105
- }
106
- throw new Error(`No free port found in range ${basePort}-${MAX_PORT}`);
107
- }
108
- function startServer(sessionDir, port) {
109
- const packageDir = getPackageDir();
110
- const buildEntry = join(packageDir, "build", "index.js");
111
- if (!existsSync(buildEntry)) {
112
- console.error(`Error: Server build not found at ${buildEntry}\nRun 'npm run build:server' in the plan-assistant package first.`);
113
- process.exit(1);
114
- }
115
- return new Promise((resolvePromise, reject) => {
116
- const child = spawn("node", [buildEntry], {
117
- env: {
118
- ...process.env,
119
- SESSION_DIR: sessionDir,
120
- PORT: String(port),
121
- },
122
- stdio: "ignore",
123
- detached: true,
124
- });
125
- child.unref();
126
- const pid = child.pid;
127
- let attempts = 0;
128
- const maxAttempts = 30;
129
- const interval = setInterval(async () => {
130
- attempts++;
131
- try {
132
- const controller = new AbortController();
133
- const timeout = setTimeout(() => controller.abort(), 1000);
134
- const res = await fetch(`http://localhost:${port}/api/health`, {
135
- signal: controller.signal,
136
- });
137
- clearTimeout(timeout);
138
- if (res.ok) {
139
- clearInterval(interval);
140
- resolvePromise(pid);
141
- }
142
- }
143
- catch {
144
- if (attempts >= maxAttempts) {
145
- clearInterval(interval);
146
- reject(new Error("Server failed to start within 15 seconds"));
147
- }
148
- }
149
- }, 500);
150
- });
151
- }
152
- async function launchServer(sessionDir, port) {
153
- process.stdout.write(`Starting Plan Assistant server on port ${port}...`);
154
- try {
155
- const pid = await startServer(sessionDir, port);
156
- writeLock(sessionDir, port, pid);
157
- console.log(" ready.");
158
- }
159
- catch (err) {
160
- console.error(` failed: ${err}`);
161
- process.exit(1);
162
- }
163
- }
164
- function openBrowser(url) {
165
- try {
166
- const cmd = process.platform === "darwin"
167
- ? "open"
168
- : process.platform === "win32"
169
- ? "start"
170
- : "xdg-open";
171
- execSync(`${cmd} "${url}"`, { stdio: "ignore" });
172
- }
173
- catch {
174
- console.log(`Open in browser: ${url}`);
175
- }
176
- }
6
+ import { waitForFeedback } from "../session-reader.js";
7
+ import { DEFAULT_BASE_PORT, MAX_PORT, findExistingServer, checkHealth, isPortFree, findFreePort, launchServer, openBrowser, } from "../server-client.js";
177
8
  export async function review(args) {
178
9
  const markdownFile = args.positional[0];
179
10
  if (!markdownFile) {
@@ -181,6 +12,11 @@ export async function review(args) {
181
12
  console.error("Usage: plan-assistant review <markdown-file>");
182
13
  process.exit(1);
183
14
  }
15
+ // Parse host configuration (for Docker/remote sandbox environments)
16
+ const hostFlag = args.flags.host;
17
+ const displayHost = (typeof hostFlag === "string" ? hostFlag : null) ??
18
+ process.env.PLAN_ASSISTANT_HOST ??
19
+ "localhost";
184
20
  // Parse port configuration
185
21
  const portFlag = args.flags.port;
186
22
  const envPort = process.env.PLAN_ASSISTANT_PORT;
@@ -274,12 +110,32 @@ Run \`npx plan-assistant init --output <file>\` to generate a correctly-formatte
274
110
  writeFileSync(join(sessionPath, "plan.json"), JSON.stringify(plan, null, 2));
275
111
  writeFileSync(join(sessionPath, "versions", `v${version}.json`), JSON.stringify(plan, null, 2));
276
112
  // Find existing server for this session dir or start a new one
113
+ const reuse = args.flags.reuse === true;
277
114
  const basePort = requestedPort ?? DEFAULT_BASE_PORT;
278
115
  let port = await findExistingServer(sessionDir, basePort);
116
+ if (!port && reuse) {
117
+ // --reuse: find any running plan-assistant server and reuse it
118
+ for (let p = basePort; p <= MAX_PORT; p++) {
119
+ const health = await checkHealth(p);
120
+ if (health) {
121
+ port = p;
122
+ console.error(`Reusing existing server on port ${p}.`);
123
+ break;
124
+ }
125
+ }
126
+ }
279
127
  if (!port) {
280
128
  if (requestedPort) {
281
129
  if (!(await isPortFree(requestedPort))) {
282
- console.error(`Error: Port ${requestedPort} is already in use`);
130
+ // Check if it's a plan-assistant server for a better error message
131
+ const health = await checkHealth(requestedPort);
132
+ if (health) {
133
+ console.error(`Error: Port ${requestedPort} is already used by Plan Assistant (session dir: ${health.sessionDir}).` +
134
+ `\nUse \`plan-assistant stop\` to stop it, or add --reuse to share the server.`);
135
+ }
136
+ else {
137
+ console.error(`Error: Port ${requestedPort} is already in use by another process.`);
138
+ }
283
139
  process.exit(1);
284
140
  }
285
141
  port = requestedPort;
@@ -289,7 +145,7 @@ Run \`npx plan-assistant init --output <file>\` to generate a correctly-formatte
289
145
  }
290
146
  await launchServer(sessionDir, port);
291
147
  }
292
- const url = `http://localhost:${port}/plan/${sessionId}`;
148
+ const url = `http://${displayHost}:${port}/plan/${sessionId}`;
293
149
  const feedbackPath = join(sessionPath, "feedback.json");
294
150
  // Machine-readable ready event on first line
295
151
  outputJson({
@@ -300,7 +156,9 @@ Run \`npx plan-assistant init --output <file>\` to generate a correctly-formatte
300
156
  url,
301
157
  feedbackPath,
302
158
  });
303
- openBrowser(url);
159
+ if (displayHost === "localhost") {
160
+ openBrowser(url);
161
+ }
304
162
  const noWait = args.flags["no-wait"] === true;
305
163
  console.error(`\nPlan Assistant`);
306
164
  console.error(` Review: ${url}`);
@@ -340,7 +198,7 @@ Run \`npx plan-assistant init --output <file>\` to generate a correctly-formatte
340
198
  });
341
199
  // Wait for feedback unless --no-wait
342
200
  if (!noWait) {
343
- await waitForFeedback(feedbackPath, sessionId, plan.meta.title, mdWatcher);
201
+ await waitForFeedback(feedbackPath, sessionId, plan.meta.title, mdWatcher, sessionPath);
344
202
  return;
345
203
  }
346
204
  // Keep process alive (--no-wait mode)
@@ -350,60 +208,3 @@ Run \`npx plan-assistant init --output <file>\` to generate a correctly-formatte
350
208
  process.exit(0);
351
209
  });
352
210
  }
353
- async function waitForFeedback(feedbackPath, sessionId, planTitle, mdWatcher) {
354
- // Check if feedback already submitted
355
- if (existsSync(feedbackPath)) {
356
- try {
357
- const existing = JSON.parse(readFileSync(feedbackPath, "utf-8"));
358
- if (existing.status === "approved" || existing.status === "needs-work") {
359
- mdWatcher.close();
360
- outputFeedbackResult(existing, sessionId, planTitle);
361
- return;
362
- }
363
- }
364
- catch {
365
- /* ignore */
366
- }
367
- }
368
- return new Promise((resolve) => {
369
- const fbWatcher = watch(feedbackPath, {
370
- awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 100 },
371
- });
372
- const check = () => {
373
- try {
374
- if (!existsSync(feedbackPath))
375
- return;
376
- const data = JSON.parse(readFileSync(feedbackPath, "utf-8"));
377
- if (data.status === "approved" || data.status === "needs-work") {
378
- fbWatcher.close();
379
- mdWatcher.close();
380
- outputFeedbackResult(data, sessionId, planTitle);
381
- resolve();
382
- }
383
- }
384
- catch {
385
- /* ignore parse errors during writes */
386
- }
387
- };
388
- fbWatcher.on("change", check);
389
- fbWatcher.on("add", check);
390
- process.on("SIGINT", () => {
391
- fbWatcher.close();
392
- mdWatcher.close();
393
- console.error("\nStopped watching.");
394
- process.exit(0);
395
- });
396
- });
397
- }
398
- function outputFeedbackResult(feedback, sessionId, planTitle) {
399
- const unresolvedComments = feedback.comments.filter((c) => !c.resolved);
400
- outputJson({
401
- event: "feedback",
402
- sessionId,
403
- planTitle,
404
- status: feedback.status,
405
- comments: unresolvedComments,
406
- commentCount: unresolvedComments.length,
407
- });
408
- process.exit(feedback.status === "approved" ? EXIT_APPROVED : EXIT_NEEDS_WORK);
409
- }
@@ -0,0 +1,64 @@
1
+ import { dirname } from "node:path";
2
+ import { resolveSession } from "../session-resolver.js";
3
+ import { stopServer, checkHealth, DEFAULT_BASE_PORT, MAX_PORT, } from "../server-client.js";
4
+ import { outputJson, outputError } from "../output.js";
5
+ export async function stop(args) {
6
+ const target = args.positional[0];
7
+ if (target) {
8
+ // Stop server for a specific session
9
+ const session = resolveSession(target);
10
+ if (!session) {
11
+ outputError(`Session not found: ${target}`, "NOT_FOUND");
12
+ process.exit(1);
13
+ }
14
+ const parentDir = dirname(session.sessionDir);
15
+ const stopped = await stopServer(parentDir);
16
+ if (stopped) {
17
+ outputJson({ event: "server-stopped", sessionDir: parentDir });
18
+ console.error(`Server stopped for session ${session.sessionId}.`);
19
+ }
20
+ else {
21
+ outputJson({ event: "no-server", sessionDir: parentDir });
22
+ console.error(`No running server found for session ${session.sessionId}.`);
23
+ }
24
+ return;
25
+ }
26
+ // No argument: find and stop all plan-assistant servers in port range
27
+ let stopped = 0;
28
+ const results = [];
29
+ for (let port = DEFAULT_BASE_PORT; port <= MAX_PORT; port++) {
30
+ const health = await checkHealth(port);
31
+ if (health) {
32
+ try {
33
+ const controller = new AbortController();
34
+ const timeout = setTimeout(() => controller.abort(), 2000);
35
+ await fetch(`http://localhost:${port}/api/shutdown`, {
36
+ method: "POST",
37
+ signal: controller.signal,
38
+ });
39
+ clearTimeout(timeout);
40
+ results.push({ port, sessionDir: health.sessionDir });
41
+ stopped++;
42
+ }
43
+ catch {
44
+ // Try SIGTERM
45
+ try {
46
+ process.kill(health.pid, "SIGTERM");
47
+ results.push({ port, sessionDir: health.sessionDir });
48
+ stopped++;
49
+ }
50
+ catch {
51
+ // ignore
52
+ }
53
+ }
54
+ }
55
+ }
56
+ if (stopped === 0) {
57
+ outputJson({ event: "no-servers", stopped: 0 });
58
+ console.error("No running Plan Assistant servers found.");
59
+ }
60
+ else {
61
+ outputJson({ event: "servers-stopped", stopped, servers: results });
62
+ console.error(`Stopped ${stopped} server(s).`);
63
+ }
64
+ }
package/dist/cli/index.js CHANGED
@@ -54,6 +54,7 @@ Commands:
54
54
  plan-assistant status <session-id-or-file> Check review status
55
55
  plan-assistant feedback <session-id-or-file> Read feedback JSON
56
56
  plan-assistant list [--dir <path>] List all sessions
57
+ plan-assistant stop [<session-id-or-file>] Stop running server(s)
57
58
  plan-assistant clean [--all] [--older-than <dur>] Remove old sessions
58
59
  plan-assistant export <session-id-or-file> Export as HTML
59
60
  plan-assistant help format Show the required plan format
@@ -62,7 +63,9 @@ Commands:
62
63
  Flags:
63
64
  --pretty Human-readable output (default: JSON)
64
65
  --port <N> Port for review server (review command)
66
+ --host <H> Hostname for browser URL, e.g. host IP when running in Docker (review command)
65
67
  --no-wait Don't wait for feedback, just start server (review command)
68
+ --reuse Reuse an already-running server on another session (review command)
66
69
  --wait Block until feedback is submitted (status command)
67
70
 
68
71
  TIP: Always start with \`plan-assistant init\` to get a correctly-formatted template.
@@ -150,6 +153,10 @@ export async function main(args) {
150
153
  const { init } = await import("./commands/init.js");
151
154
  return init(parsed);
152
155
  }
156
+ case "stop": {
157
+ const { stop } = await import("./commands/stop.js");
158
+ return stop(parsed);
159
+ }
153
160
  case "clean": {
154
161
  const { clean } = await import("./commands/clean.js");
155
162
  return clean(parsed);