pi-forge 1.2.3 → 1.2.4

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 (61) hide show
  1. package/README.md +1 -1
  2. package/dist/client/assets/{CodeMirrorEditor-1gu-DS9k.js → CodeMirrorEditor-M7HIAKX2.js} +2 -2
  3. package/dist/client/assets/{CodeMirrorEditor-1gu-DS9k.js.map → CodeMirrorEditor-M7HIAKX2.js.map} +1 -1
  4. package/dist/client/assets/index-DFDpaYie.css +1 -0
  5. package/dist/client/assets/index-DjYKKZRm.js +363 -0
  6. package/dist/client/assets/index-DjYKKZRm.js.map +1 -0
  7. package/dist/client/index.html +2 -2
  8. package/dist/client/sw.js +1 -1
  9. package/dist/client/sw.js.map +1 -1
  10. package/dist/server/ask-user-question/envelope.js +56 -0
  11. package/dist/server/ask-user-question/envelope.js.map +1 -0
  12. package/dist/server/ask-user-question/prompt-strings.js +44 -0
  13. package/dist/server/ask-user-question/prompt-strings.js.map +1 -0
  14. package/dist/server/ask-user-question/registry.js +157 -0
  15. package/dist/server/ask-user-question/registry.js.map +1 -0
  16. package/dist/server/ask-user-question/tool.js +115 -0
  17. package/dist/server/ask-user-question/tool.js.map +1 -0
  18. package/dist/server/ask-user-question/types.js +27 -0
  19. package/dist/server/ask-user-question/types.js.map +1 -0
  20. package/dist/server/ask-user-question/validate.js +135 -0
  21. package/dist/server/ask-user-question/validate.js.map +1 -0
  22. package/dist/server/config.js +10 -0
  23. package/dist/server/config.js.map +1 -1
  24. package/dist/server/index.js +13 -0
  25. package/dist/server/index.js.map +1 -1
  26. package/dist/server/quick-actions.js +141 -0
  27. package/dist/server/quick-actions.js.map +1 -0
  28. package/dist/server/routes/ask-user-question.js +129 -0
  29. package/dist/server/routes/ask-user-question.js.map +1 -0
  30. package/dist/server/routes/config.js +7 -0
  31. package/dist/server/routes/config.js.map +1 -1
  32. package/dist/server/routes/quick-actions.js +384 -0
  33. package/dist/server/routes/quick-actions.js.map +1 -0
  34. package/dist/server/routes/todos.js +67 -0
  35. package/dist/server/routes/todos.js.map +1 -0
  36. package/dist/server/session-registry.js +52 -4
  37. package/dist/server/session-registry.js.map +1 -1
  38. package/dist/server/sse-bridge.js +84 -0
  39. package/dist/server/sse-bridge.js.map +1 -1
  40. package/dist/server/todo/envelope.js +87 -0
  41. package/dist/server/todo/envelope.js.map +1 -0
  42. package/dist/server/todo/invariants.js +21 -0
  43. package/dist/server/todo/invariants.js.map +1 -0
  44. package/dist/server/todo/prompt-strings.js +29 -0
  45. package/dist/server/todo/prompt-strings.js.map +1 -0
  46. package/dist/server/todo/reducer.js +189 -0
  47. package/dist/server/todo/reducer.js.map +1 -0
  48. package/dist/server/todo/replay.js +45 -0
  49. package/dist/server/todo/replay.js.map +1 -0
  50. package/dist/server/todo/store.js +92 -0
  51. package/dist/server/todo/store.js.map +1 -0
  52. package/dist/server/todo/task-graph.js +60 -0
  53. package/dist/server/todo/task-graph.js.map +1 -0
  54. package/dist/server/todo/tool.js +95 -0
  55. package/dist/server/todo/tool.js.map +1 -0
  56. package/dist/server/todo/types.js +23 -0
  57. package/dist/server/todo/types.js.map +1 -0
  58. package/package.json +1 -1
  59. package/dist/client/assets/index-BxZV6ddv.js +0 -359
  60. package/dist/client/assets/index-BxZV6ddv.js.map +0 -1
  61. package/dist/client/assets/index-KUhxvBxw.css +0 -1
@@ -26,8 +26,8 @@
26
26
  <link rel="apple-touch-icon" sizes="192x192" href="/icons/icon-192.png" />
27
27
  <link rel="apple-touch-icon" sizes="512x512" href="/icons/icon-512.png" />
28
28
  <title>pi-forge</title>
29
- <script type="module" crossorigin src="/assets/index-BxZV6ddv.js"></script>
30
- <link rel="stylesheet" crossorigin href="/assets/index-KUhxvBxw.css">
29
+ <script type="module" crossorigin src="/assets/index-DjYKKZRm.js"></script>
30
+ <link rel="stylesheet" crossorigin href="/assets/index-DFDpaYie.css">
31
31
  <link rel="manifest" href="/manifest.webmanifest"></head>
32
32
  <body class="bg-neutral-950 text-neutral-100 antialiased">
33
33
  <div id="root"></div>
package/dist/client/sw.js CHANGED
@@ -1,3 +1,3 @@
1
- if(!self.define){let e,i={};const n=(n,s)=>(n=new URL(n+".js",s).href,i[n]||new Promise(i=>{if("document"in self){const e=document.createElement("script");e.src=n,e.onload=i,document.head.appendChild(e)}else e=n,importScripts(n),i()}).then(()=>{let e=i[n];if(!e)throw new Error(`Module ${n} didn’t register its module`);return e}));self.define=(s,o)=>{const c=e||("document"in self?document.currentScript.src:"")||location.href;if(i[c])return;let r={};const f=e=>n(e,c),l={module:{uri:c},exports:r,require:f};i[c]=Promise.all(s.map(e=>l[e]||f(e))).then(e=>(o(...e),r))}}define(["./workbox-6d7155ed"],function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"offline.html",revision:"e4f087b40040ff045a6fd572b5fed726"},{url:"manifest.webmanifest",revision:"aef9cb4935c3fba2754da10580256c9e"},{url:"index.html",revision:"73b11cff5ee1cf2dce9a07e048a34c4c"},{url:"icons/icon.svg",revision:"549b462207e763a57c9dfbae214afc31"},{url:"icons/icon-maskable-512.png",revision:"734c73b2ee3cc3856c67bed196e7557f"},{url:"icons/icon-512.png",revision:"c1b37dbf870c852577dbb4733f45c9c2"},{url:"icons/icon-192.png",revision:"54082a8d4e49f4e5c2ad5646b7fb7551"},{url:"assets/workbox-window.prod.es5-Cch4wiA5.js",revision:null},{url:"assets/index-KUhxvBxw.css",revision:null},{url:"assets/index-BxZV6ddv.js",revision:null},{url:"assets/CodeMirrorEditor-1gu-DS9k.js",revision:null},{url:"offline.html",revision:"e4f087b40040ff045a6fd572b5fed726"},{url:"icons/icon-192.png",revision:"54082a8d4e49f4e5c2ad5646b7fb7551"},{url:"icons/icon-512.png",revision:"c1b37dbf870c852577dbb4733f45c9c2"},{url:"icons/icon-maskable-512.png",revision:"734c73b2ee3cc3856c67bed196e7557f"},{url:"icons/icon.svg",revision:"549b462207e763a57c9dfbae214afc31"},{url:"manifest.webmanifest",revision:"aef9cb4935c3fba2754da10580256c9e"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("/index.html"),{denylist:[/^\/api\//]})),e.registerRoute(({url:e})=>e.pathname.startsWith("/api/v1/"),new e.NetworkOnly,"GET"),e.registerRoute(({request:e})=>"navigate"===e.mode,new e.NetworkFirst({cacheName:"pi-navigation",networkTimeoutSeconds:3,plugins:[new e.PrecacheFallbackPlugin({fallbackURL:"/offline.html"})]}),"GET")});
1
+ if(!self.define){let e,i={};const n=(n,s)=>(n=new URL(n+".js",s).href,i[n]||new Promise(i=>{if("document"in self){const e=document.createElement("script");e.src=n,e.onload=i,document.head.appendChild(e)}else e=n,importScripts(n),i()}).then(()=>{let e=i[n];if(!e)throw new Error(`Module ${n} didn’t register its module`);return e}));self.define=(s,o)=>{const c=e||("document"in self?document.currentScript.src:"")||location.href;if(i[c])return;let r={};const f=e=>n(e,c),l={module:{uri:c},exports:r,require:f};i[c]=Promise.all(s.map(e=>l[e]||f(e))).then(e=>(o(...e),r))}}define(["./workbox-6d7155ed"],function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"offline.html",revision:"e4f087b40040ff045a6fd572b5fed726"},{url:"manifest.webmanifest",revision:"aef9cb4935c3fba2754da10580256c9e"},{url:"index.html",revision:"02c324c8fc4f9b36cfd294f930ee1fcf"},{url:"icons/icon.svg",revision:"549b462207e763a57c9dfbae214afc31"},{url:"icons/icon-maskable-512.png",revision:"734c73b2ee3cc3856c67bed196e7557f"},{url:"icons/icon-512.png",revision:"c1b37dbf870c852577dbb4733f45c9c2"},{url:"icons/icon-192.png",revision:"54082a8d4e49f4e5c2ad5646b7fb7551"},{url:"assets/workbox-window.prod.es5-Cch4wiA5.js",revision:null},{url:"assets/index-DjYKKZRm.js",revision:null},{url:"assets/index-DFDpaYie.css",revision:null},{url:"assets/CodeMirrorEditor-M7HIAKX2.js",revision:null},{url:"offline.html",revision:"e4f087b40040ff045a6fd572b5fed726"},{url:"icons/icon-192.png",revision:"54082a8d4e49f4e5c2ad5646b7fb7551"},{url:"icons/icon-512.png",revision:"c1b37dbf870c852577dbb4733f45c9c2"},{url:"icons/icon-maskable-512.png",revision:"734c73b2ee3cc3856c67bed196e7557f"},{url:"icons/icon.svg",revision:"549b462207e763a57c9dfbae214afc31"},{url:"manifest.webmanifest",revision:"aef9cb4935c3fba2754da10580256c9e"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("/index.html"),{denylist:[/^\/api\//]})),e.registerRoute(({url:e})=>e.pathname.startsWith("/api/v1/"),new e.NetworkOnly,"GET"),e.registerRoute(({request:e})=>"navigate"===e.mode,new e.NetworkFirst({cacheName:"pi-navigation",networkTimeoutSeconds:3,plugins:[new e.PrecacheFallbackPlugin({fallbackURL:"/offline.html"})]}),"GET")});
2
2
  //# sourceMappingURL=sw.js.map
3
3
  //# sourceMappingURL=sw.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sw.js","sources":["../../../../../../../tmp/21776664c681c14477c7dc3a4d32f3a3/sw.js"],"sourcesContent":["import {registerRoute as workbox_routing_registerRoute} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-routing/registerRoute.mjs';\nimport {NetworkOnly as workbox_strategies_NetworkOnly} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-strategies/NetworkOnly.mjs';\nimport {PrecacheFallbackPlugin as workbox_precaching_PrecacheFallbackPlugin} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-precaching/PrecacheFallbackPlugin.mjs';\nimport {NetworkFirst as workbox_strategies_NetworkFirst} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-strategies/NetworkFirst.mjs';\nimport {clientsClaim as workbox_core_clientsClaim} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-core/clientsClaim.mjs';\nimport {precacheAndRoute as workbox_precaching_precacheAndRoute} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-precaching/precacheAndRoute.mjs';\nimport {cleanupOutdatedCaches as workbox_precaching_cleanupOutdatedCaches} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-precaching/cleanupOutdatedCaches.mjs';\nimport {NavigationRoute as workbox_routing_NavigationRoute} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-routing/NavigationRoute.mjs';\nimport {createHandlerBoundToURL as workbox_precaching_createHandlerBoundToURL} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-precaching/createHandlerBoundToURL.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\n\n\nself.skipWaiting();\nworkbox_core_clientsClaim();\n/**\n * The precacheAndRoute() method efficiently caches and responds to\n * requests for URLs in the manifest.\n * See https://goo.gl/S9QRab\n */\nworkbox_precaching_precacheAndRoute([\n {\n \"url\": \"offline.html\",\n \"revision\": \"e4f087b40040ff045a6fd572b5fed726\"\n },\n {\n \"url\": \"manifest.webmanifest\",\n \"revision\": \"aef9cb4935c3fba2754da10580256c9e\"\n },\n {\n \"url\": \"index.html\",\n \"revision\": \"73b11cff5ee1cf2dce9a07e048a34c4c\"\n },\n {\n \"url\": \"icons/icon.svg\",\n \"revision\": \"549b462207e763a57c9dfbae214afc31\"\n },\n {\n \"url\": \"icons/icon-maskable-512.png\",\n \"revision\": \"734c73b2ee3cc3856c67bed196e7557f\"\n },\n {\n \"url\": \"icons/icon-512.png\",\n \"revision\": \"c1b37dbf870c852577dbb4733f45c9c2\"\n },\n {\n \"url\": \"icons/icon-192.png\",\n \"revision\": \"54082a8d4e49f4e5c2ad5646b7fb7551\"\n },\n {\n \"url\": \"assets/workbox-window.prod.es5-Cch4wiA5.js\",\n \"revision\": null\n },\n {\n \"url\": \"assets/index-KUhxvBxw.css\",\n \"revision\": null\n },\n {\n \"url\": \"assets/index-BxZV6ddv.js\",\n \"revision\": null\n },\n {\n \"url\": \"assets/CodeMirrorEditor-1gu-DS9k.js\",\n \"revision\": null\n },\n {\n \"url\": \"offline.html\",\n \"revision\": \"e4f087b40040ff045a6fd572b5fed726\"\n },\n {\n \"url\": \"icons/icon-192.png\",\n \"revision\": \"54082a8d4e49f4e5c2ad5646b7fb7551\"\n },\n {\n \"url\": \"icons/icon-512.png\",\n \"revision\": \"c1b37dbf870c852577dbb4733f45c9c2\"\n },\n {\n \"url\": \"icons/icon-maskable-512.png\",\n \"revision\": \"734c73b2ee3cc3856c67bed196e7557f\"\n },\n {\n \"url\": \"icons/icon.svg\",\n \"revision\": \"549b462207e763a57c9dfbae214afc31\"\n },\n {\n \"url\": \"manifest.webmanifest\",\n \"revision\": \"aef9cb4935c3fba2754da10580256c9e\"\n }\n], {});\nworkbox_precaching_cleanupOutdatedCaches();workbox_routing_registerRoute(new workbox_routing_NavigationRoute(workbox_precaching_createHandlerBoundToURL(\"/index.html\"), {\n denylist: [/^\\/api\\//],}));\nworkbox_routing_registerRoute(({ url }) => url.pathname.startsWith(\"/api/v1/\"), new workbox_strategies_NetworkOnly(), 'GET');\nworkbox_routing_registerRoute(({ request }) => request.mode === \"navigate\", new workbox_strategies_NetworkFirst({ \"cacheName\":\"pi-navigation\",\"networkTimeoutSeconds\":3, plugins: [new workbox_precaching_PrecacheFallbackPlugin({ fallbackURL: '/offline.html' })] }), 'GET');\n\n\n"],"names":["self","skipWaiting","workbox_core_clientsClaim","workbox_precaching_precacheAndRoute","url","revision","workbox_precaching_cleanupOutdatedCaches","workbox_routing_registerRoute","workbox_routing_NavigationRoute","workbox_precaching_createHandlerBoundToURL","denylist","pathname","startsWith","workbox_strategies_NetworkOnly","request","mode","workbox_strategies_NetworkFirst","cacheName","networkTimeoutSeconds","plugins","workbox_precaching_PrecacheFallbackPlugin","fallbackURL"],"mappings":"inBAuBAA,KAAKC,cACLC,EAAAA,eAMAC,EAAAA,iBAAoC,CAClC,CACEC,IAAO,eACPC,SAAY,oCAEd,CACED,IAAO,uBACPC,SAAY,oCAEd,CACED,IAAO,aACPC,SAAY,oCAEd,CACED,IAAO,iBACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,qBACPC,SAAY,oCAEd,CACED,IAAO,qBACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,MAEd,CACED,IAAO,4BACPC,SAAY,MAEd,CACED,IAAO,2BACPC,SAAY,MAEd,CACED,IAAO,sCACPC,SAAY,MAEd,CACED,IAAO,eACPC,SAAY,oCAEd,CACED,IAAO,qBACPC,SAAY,oCAEd,CACED,IAAO,qBACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,iBACPC,SAAY,oCAEd,CACED,IAAO,uBACPC,SAAY,qCAEb,CAAA,GACHC,EAAAA,wBAA2CC,EAAAA,cAA8B,IAAIC,EAAAA,gBAAgCC,0BAA2C,eAAgB,CACpKC,SAAU,CAAC,eACfH,EAAAA,cAA8B,EAAGH,SAAUA,EAAIO,SAASC,WAAW,YAAa,IAAIC,EAAAA,YAAkC,OACtHN,EAAAA,cAA8B,EAAGO,aAA+B,aAAjBA,EAAQC,KAAqB,IAAIC,EAAAA,aAAgC,CAAEC,UAAY,gBAAgBC,sBAAwB,EAAGC,QAAS,CAAC,IAAIC,yBAA0C,CAAEC,YAAa,qBAAwB"}
1
+ {"version":3,"file":"sw.js","sources":["../../../../../../../tmp/643db5744678e787315dd9b46486342f/sw.js"],"sourcesContent":["import {registerRoute as workbox_routing_registerRoute} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-routing/registerRoute.mjs';\nimport {NetworkOnly as workbox_strategies_NetworkOnly} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-strategies/NetworkOnly.mjs';\nimport {PrecacheFallbackPlugin as workbox_precaching_PrecacheFallbackPlugin} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-precaching/PrecacheFallbackPlugin.mjs';\nimport {NetworkFirst as workbox_strategies_NetworkFirst} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-strategies/NetworkFirst.mjs';\nimport {clientsClaim as workbox_core_clientsClaim} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-core/clientsClaim.mjs';\nimport {precacheAndRoute as workbox_precaching_precacheAndRoute} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-precaching/precacheAndRoute.mjs';\nimport {cleanupOutdatedCaches as workbox_precaching_cleanupOutdatedCaches} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-precaching/cleanupOutdatedCaches.mjs';\nimport {NavigationRoute as workbox_routing_NavigationRoute} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-routing/NavigationRoute.mjs';\nimport {createHandlerBoundToURL as workbox_precaching_createHandlerBoundToURL} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-precaching/createHandlerBoundToURL.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\n\n\nself.skipWaiting();\nworkbox_core_clientsClaim();\n/**\n * The precacheAndRoute() method efficiently caches and responds to\n * requests for URLs in the manifest.\n * See https://goo.gl/S9QRab\n */\nworkbox_precaching_precacheAndRoute([\n {\n \"url\": \"offline.html\",\n \"revision\": \"e4f087b40040ff045a6fd572b5fed726\"\n },\n {\n \"url\": \"manifest.webmanifest\",\n \"revision\": \"aef9cb4935c3fba2754da10580256c9e\"\n },\n {\n \"url\": \"index.html\",\n \"revision\": \"02c324c8fc4f9b36cfd294f930ee1fcf\"\n },\n {\n \"url\": \"icons/icon.svg\",\n \"revision\": \"549b462207e763a57c9dfbae214afc31\"\n },\n {\n \"url\": \"icons/icon-maskable-512.png\",\n \"revision\": \"734c73b2ee3cc3856c67bed196e7557f\"\n },\n {\n \"url\": \"icons/icon-512.png\",\n \"revision\": \"c1b37dbf870c852577dbb4733f45c9c2\"\n },\n {\n \"url\": \"icons/icon-192.png\",\n \"revision\": \"54082a8d4e49f4e5c2ad5646b7fb7551\"\n },\n {\n \"url\": \"assets/workbox-window.prod.es5-Cch4wiA5.js\",\n \"revision\": null\n },\n {\n \"url\": \"assets/index-DjYKKZRm.js\",\n \"revision\": null\n },\n {\n \"url\": \"assets/index-DFDpaYie.css\",\n \"revision\": null\n },\n {\n \"url\": \"assets/CodeMirrorEditor-M7HIAKX2.js\",\n \"revision\": null\n },\n {\n \"url\": \"offline.html\",\n \"revision\": \"e4f087b40040ff045a6fd572b5fed726\"\n },\n {\n \"url\": \"icons/icon-192.png\",\n \"revision\": \"54082a8d4e49f4e5c2ad5646b7fb7551\"\n },\n {\n \"url\": \"icons/icon-512.png\",\n \"revision\": \"c1b37dbf870c852577dbb4733f45c9c2\"\n },\n {\n \"url\": \"icons/icon-maskable-512.png\",\n \"revision\": \"734c73b2ee3cc3856c67bed196e7557f\"\n },\n {\n \"url\": \"icons/icon.svg\",\n \"revision\": \"549b462207e763a57c9dfbae214afc31\"\n },\n {\n \"url\": \"manifest.webmanifest\",\n \"revision\": \"aef9cb4935c3fba2754da10580256c9e\"\n }\n], {});\nworkbox_precaching_cleanupOutdatedCaches();workbox_routing_registerRoute(new workbox_routing_NavigationRoute(workbox_precaching_createHandlerBoundToURL(\"/index.html\"), {\n denylist: [/^\\/api\\//],}));\nworkbox_routing_registerRoute(({ url }) => url.pathname.startsWith(\"/api/v1/\"), new workbox_strategies_NetworkOnly(), 'GET');\nworkbox_routing_registerRoute(({ request }) => request.mode === \"navigate\", new workbox_strategies_NetworkFirst({ \"cacheName\":\"pi-navigation\",\"networkTimeoutSeconds\":3, plugins: [new workbox_precaching_PrecacheFallbackPlugin({ fallbackURL: '/offline.html' })] }), 'GET');\n\n\n"],"names":["self","skipWaiting","workbox_core_clientsClaim","workbox_precaching_precacheAndRoute","url","revision","workbox_precaching_cleanupOutdatedCaches","workbox_routing_registerRoute","workbox_routing_NavigationRoute","workbox_precaching_createHandlerBoundToURL","denylist","pathname","startsWith","workbox_strategies_NetworkOnly","request","mode","workbox_strategies_NetworkFirst","cacheName","networkTimeoutSeconds","plugins","workbox_precaching_PrecacheFallbackPlugin","fallbackURL"],"mappings":"inBAuBAA,KAAKC,cACLC,EAAAA,eAMAC,EAAAA,iBAAoC,CAClC,CACEC,IAAO,eACPC,SAAY,oCAEd,CACED,IAAO,uBACPC,SAAY,oCAEd,CACED,IAAO,aACPC,SAAY,oCAEd,CACED,IAAO,iBACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,qBACPC,SAAY,oCAEd,CACED,IAAO,qBACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,MAEd,CACED,IAAO,2BACPC,SAAY,MAEd,CACED,IAAO,4BACPC,SAAY,MAEd,CACED,IAAO,sCACPC,SAAY,MAEd,CACED,IAAO,eACPC,SAAY,oCAEd,CACED,IAAO,qBACPC,SAAY,oCAEd,CACED,IAAO,qBACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,iBACPC,SAAY,oCAEd,CACED,IAAO,uBACPC,SAAY,qCAEb,CAAA,GACHC,EAAAA,wBAA2CC,EAAAA,cAA8B,IAAIC,EAAAA,gBAAgCC,0BAA2C,eAAgB,CACpKC,SAAU,CAAC,eACfH,EAAAA,cAA8B,EAAGH,SAAUA,EAAIO,SAASC,WAAW,YAAa,IAAIC,EAAAA,YAAkC,OACtHN,EAAAA,cAA8B,EAAGO,aAA+B,aAAjBA,EAAQC,KAAqB,IAAIC,EAAAA,aAAgC,CAAEC,UAAY,gBAAgBC,sBAAwB,EAAGC,QAAS,CAAC,IAAIC,yBAA0C,CAAEC,YAAa,qBAAwB"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Build the tool result the agent sees. The shape matches the
3
+ * upstream plugin: a single text content block summarising what
4
+ * happened, plus a `details` object the agent can introspect when
5
+ * it needs the structured answers.
6
+ *
7
+ * The `text` summary is the channel the model actually reads when it
8
+ * continues the conversation — short, neutral phrasing, one line
9
+ * per answered question.
10
+ */
11
+ export function buildResult(answers, opts = {}) {
12
+ const cancelled = opts.cancelled === true;
13
+ const details = { answers, cancelled };
14
+ if (opts.error !== undefined)
15
+ details.error = opts.error;
16
+ const text = renderText(answers, {
17
+ cancelled,
18
+ error: opts.error,
19
+ questionCount: opts.questionCount ?? answers.length,
20
+ });
21
+ return { content: [{ type: "text", text }], details };
22
+ }
23
+ function renderText(answers, ctx) {
24
+ if (ctx.error !== undefined && answers.length === 0) {
25
+ return `Error: ${ctx.error}`;
26
+ }
27
+ if (ctx.cancelled && answers.length === 0) {
28
+ return "User cancelled the questionnaire without answering. Continue in free-form conversation.";
29
+ }
30
+ const lines = [];
31
+ for (const a of answers) {
32
+ lines.push(renderAnswerLine(a));
33
+ }
34
+ if (ctx.cancelled && answers.length < ctx.questionCount) {
35
+ lines.push(`(User cancelled the remaining ${ctx.questionCount - answers.length} question(s); continue with what was answered.)`);
36
+ }
37
+ return lines.join("\n");
38
+ }
39
+ function renderAnswerLine(a) {
40
+ const prefix = `Q${a.questionIndex + 1} "${a.question}"`;
41
+ switch (a.kind) {
42
+ case "option":
43
+ return `${prefix} → ${a.answer ?? ""}${a.notes !== undefined && a.notes.length > 0 ? ` (note: ${a.notes})` : ""}`;
44
+ case "custom": {
45
+ const text = a.answer ?? "(no text provided)";
46
+ return `${prefix} → custom: ${text}`;
47
+ }
48
+ case "chat":
49
+ return `${prefix} → user chose to chat about this`;
50
+ case "multi": {
51
+ const items = (a.selected ?? []).join(", ");
52
+ return `${prefix} → selected: ${items.length > 0 ? items : "(none)"}`;
53
+ }
54
+ }
55
+ }
56
+ //# sourceMappingURL=envelope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelope.js","sourceRoot":"","sources":["../../src/ask-user-question/envelope.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CACzB,OAAyB,EACzB,OAAwE,EAAE;IAE1E,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC;IAC1C,MAAM,OAAO,GAA2B,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;IAC/D,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACzD,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,EAAE;QAC/B,SAAS;QACT,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,OAAO,CAAC,MAAM;KACpD,CAAC,CAAC;IACH,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;AACxD,CAAC;AAED,SAAS,UAAU,CACjB,OAAyB,EACzB,GAA6E;IAE7E,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,OAAO,UAAU,GAAG,CAAC,KAAK,EAAE,CAAC;IAC/B,CAAC;IACD,IAAI,GAAG,CAAC,SAAS,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1C,OAAO,yFAAyF,CAAC;IACnG,CAAC;IACD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IACD,IAAI,GAAG,CAAC,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,GAAG,CAAC,aAAa,EAAE,CAAC;QACxD,KAAK,CAAC,IAAI,CACR,iCAAiC,GAAG,CAAC,aAAa,GAAG,OAAO,CAAC,MAAM,iDAAiD,CACrH,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,gBAAgB,CAAC,CAAiB;IACzC,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,aAAa,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,GAAG,CAAC;IACzD,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;QACf,KAAK,QAAQ;YACX,OAAO,GAAG,MAAM,MAAM,CAAC,CAAC,MAAM,IAAI,EAAE,GAAG,CAAC,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACpH,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,IAAI,oBAAoB,CAAC;YAC9C,OAAO,GAAG,MAAM,cAAc,IAAI,EAAE,CAAC;QACvC,CAAC;QACD,KAAK,MAAM;YACT,OAAO,GAAG,MAAM,kCAAkC,CAAC;QACrD,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5C,OAAO,GAAG,MAAM,gBAAgB,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QACxE,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Prompt snippet + guidelines for the `ask_user_question` tool.
3
+ *
4
+ * ─────────────────────────────────────────────────────────────────────────
5
+ * Adapted from @juicesharp/rpiv-ask-user-question (MIT).
6
+ * Copyright (c) 2026 juicesharp.
7
+ * https://github.com/juicesharp/rpiv-mono/tree/main/packages/rpiv-ask-user-question
8
+ * ─────────────────────────────────────────────────────────────────────────
9
+ *
10
+ * The wording is preserved (with one substitution: "Type something."
11
+ * → "Type something" in places where it's an input affordance, not
12
+ * the sentinel-label text) because it's been tuned against real
13
+ * model behavior. Rewriting from scratch risks worse tool-invocation
14
+ * patterns. The functional implementation in tool.ts, validate.ts,
15
+ * envelope.ts, and the React UI is independent.
16
+ */
17
+ import { MAX_OPTIONS, MAX_QUESTIONS, MIN_OPTIONS } from "./types.js";
18
+ export const PROMPT_SNIPPET = `Ask the user up to ${MAX_QUESTIONS} structured questions (${MIN_OPTIONS}-${MAX_OPTIONS} options each) when requirements are ambiguous`;
19
+ export const PROMPT_GUIDELINES = [
20
+ `Use ask_user_question whenever the user's request is underspecified and you cannot proceed without concrete decisions — you can ask up to ${MAX_QUESTIONS} questions per invocation.`,
21
+ `Each question MUST have ${MIN_OPTIONS}-${MAX_OPTIONS} options. Every option requires a concise label (1-5 words) and a description explaining what the choice means or its trade-offs. The user can additionally type a custom answer ("Type something." row is appended automatically to single-select questions) or pick "Chat about this" to abandon the questionnaire.`,
22
+ `Set multiSelect: true when multiple answers are valid; this suppresses the "Type something." row. Provide an options[].preview markdown string when an option benefits from richer side-by-side context (mockups, code snippets, diagrams, configs) — single-select only. NOTE: any non-empty preview on a single-select question ALSO suppresses the "Type something." row (no room in the side-by-side layout); "Chat about this" remains the escape hatch. If you recommend a specific option, make it the first option and append "(Recommended)" to its label.`,
23
+ "Do not stack multiple ask_user_question calls back-to-back — group all clarifying questions into one invocation.",
24
+ ];
25
+ export const TOOL_DESCRIPTION = `Ask the user one or more structured questions during execution. Use when you need to:
26
+ 1. Gather user preferences or requirements
27
+ 2. Clarify ambiguous instructions
28
+ 3. Get decisions on implementation choices as you work
29
+ 4. Offer choices to the user about what direction to take
30
+
31
+ Usage notes:
32
+ - Users will always be able to type a custom answer ("Type something." row is appended automatically to every single-select question) or pick "Chat about this" to abandon the questionnaire and continue in free-form conversation. Do NOT author "Other" / "Type something." / "Chat about this" labels yourself — duplicates are rejected at runtime.
33
+ - Use multiSelect: true to allow multiple answers to be selected for a question. The "Type something." row is suppressed on multi-select questions, and is ALSO suppressed on single-select questions where any option carries a \`preview\` (the side-by-side layout has no room for inline custom text — "Chat about this" remains as the free-form escape hatch).
34
+ - If you recommend a specific option, make that the first option in the list and add "(Recommended)" at the end of the label.
35
+
36
+ Preview feature:
37
+ Use the optional \`preview\` field on options when presenting concrete artifacts that users need to visually compare:
38
+ - ASCII mockups of UI layouts or components
39
+ - Code snippets showing different implementations
40
+ - Diagram variations
41
+ - Configuration examples
42
+
43
+ Preview content is rendered as markdown in a monospace box. Multi-line text with newlines is supported. When any option has a preview, the UI switches to a side-by-side layout with a vertical option list on the left and preview on the right. Do not use previews for simple preference questions where labels and descriptions suffice. Note: previews are only supported for single-select questions (not multiSelect).`;
44
+ //# sourceMappingURL=prompt-strings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-strings.js","sourceRoot":"","sources":["../../src/ask-user-question/prompt-strings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAErE,MAAM,CAAC,MAAM,cAAc,GAAG,sBAAsB,aAAa,0BAA0B,WAAW,IAAI,WAAW,gDAAgD,CAAC;AAEtK,MAAM,CAAC,MAAM,iBAAiB,GAAa;IACzC,6IAA6I,aAAa,4BAA4B;IACtL,2BAA2B,WAAW,IAAI,WAAW,uTAAuT;IAC5W,qiBAAqiB;IACriB,kHAAkH;CACnH,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;8ZAkB8X,CAAC"}
@@ -0,0 +1,157 @@
1
+ import { randomUUID } from "node:crypto";
2
+ const byRequestId = new Map();
3
+ const bySessionId = new Map();
4
+ const listeners = new Set();
5
+ export function subscribe(fn) {
6
+ listeners.add(fn);
7
+ return () => {
8
+ listeners.delete(fn);
9
+ };
10
+ }
11
+ function notify(event) {
12
+ for (const fn of listeners) {
13
+ try {
14
+ fn(event);
15
+ }
16
+ catch {
17
+ // listener errors must not break the registry — best-effort fanout
18
+ }
19
+ }
20
+ }
21
+ /**
22
+ * Register a pending request. The returned promise resolves when
23
+ * the browser answers, or when the caller's `signal` aborts (in
24
+ * which case the tool result will be a cancelled envelope built by
25
+ * the caller).
26
+ *
27
+ * `signal` is honored: if the agent is aborted (e.g. user hit Stop)
28
+ * the entry is dropped and the promise rejects with an
29
+ * `AbortError`. The caller catches that and returns the cancelled
30
+ * envelope so the agent sees a clean tool result.
31
+ */
32
+ export function registerPending(args) {
33
+ const requestId = randomUUID();
34
+ let resolveFn;
35
+ let rejectFn;
36
+ const result = new Promise((resolve, reject) => {
37
+ resolveFn = resolve;
38
+ rejectFn = reject;
39
+ });
40
+ const entry = {
41
+ requestId,
42
+ sessionId: args.sessionId,
43
+ questions: args.questions,
44
+ createdAt: new Date(),
45
+ resolve: resolveFn,
46
+ };
47
+ byRequestId.set(requestId, entry);
48
+ const set = bySessionId.get(args.sessionId) ?? new Set();
49
+ set.add(requestId);
50
+ bySessionId.set(args.sessionId, set);
51
+ if (args.signal !== undefined) {
52
+ const onAbort = () => {
53
+ // Drop the entry and tell SSE clients to close the modal.
54
+ // The tool's execute() catches the rejection and returns a
55
+ // cancelled envelope to the agent.
56
+ if (byRequestId.has(requestId)) {
57
+ removeEntry(requestId);
58
+ notify({
59
+ type: "ask_user_question_cancelled",
60
+ sessionId: args.sessionId,
61
+ requestId,
62
+ reason: "aborted",
63
+ });
64
+ rejectFn(new Error("aborted"));
65
+ }
66
+ };
67
+ if (args.signal.aborted)
68
+ onAbort();
69
+ else
70
+ args.signal.addEventListener("abort", onAbort, { once: true });
71
+ }
72
+ notify({
73
+ type: "ask_user_question",
74
+ sessionId: args.sessionId,
75
+ requestId,
76
+ questions: args.questions,
77
+ });
78
+ return { requestId, result };
79
+ }
80
+ function removeEntry(requestId) {
81
+ const e = byRequestId.get(requestId);
82
+ if (e === undefined)
83
+ return;
84
+ byRequestId.delete(requestId);
85
+ const set = bySessionId.get(e.sessionId);
86
+ if (set !== undefined) {
87
+ set.delete(requestId);
88
+ if (set.size === 0)
89
+ bySessionId.delete(e.sessionId);
90
+ }
91
+ }
92
+ /**
93
+ * Resolve the pending entry with the user's answers. Idempotent —
94
+ * if the entry was already resolved (e.g. concurrent answer +
95
+ * abort race), this returns `false` rather than throwing so the
96
+ * route layer can decide whether to 200 or 404.
97
+ */
98
+ export function answerPending(requestId, expectedSessionId, result) {
99
+ const e = byRequestId.get(requestId);
100
+ if (e === undefined)
101
+ return false;
102
+ if (e.sessionId !== expectedSessionId)
103
+ return false;
104
+ removeEntry(requestId);
105
+ // SSE clients listen for "the modal should now close" — emit a
106
+ // cancelled event with reason "answered" so the modal tears down
107
+ // on every other browser tab watching the same session.
108
+ notify({
109
+ type: "ask_user_question_cancelled",
110
+ sessionId: e.sessionId,
111
+ requestId,
112
+ reason: "answered",
113
+ });
114
+ e.resolve(result);
115
+ return true;
116
+ }
117
+ /**
118
+ * Explicit cancel from the client side (user clicked "Chat about
119
+ * this" or closed the modal). Same shape as answer, but the
120
+ * caller-supplied envelope carries `cancelled: true` and an
121
+ * empty `answers` array — or partial answers if the user filled
122
+ * some tabs before bailing.
123
+ */
124
+ export function cancelPending(requestId, expectedSessionId, result) {
125
+ // Same path as answerPending — the distinction is in the envelope
126
+ // shape, not the registry mechanics.
127
+ return answerPending(requestId, expectedSessionId, result);
128
+ }
129
+ export function getPendingForSession(sessionId) {
130
+ const ids = bySessionId.get(sessionId);
131
+ if (ids === undefined)
132
+ return [];
133
+ const out = [];
134
+ for (const id of ids) {
135
+ const e = byRequestId.get(id);
136
+ if (e !== undefined) {
137
+ out.push({
138
+ requestId: e.requestId,
139
+ sessionId: e.sessionId,
140
+ questions: e.questions,
141
+ createdAt: e.createdAt,
142
+ });
143
+ }
144
+ }
145
+ return out;
146
+ }
147
+ /**
148
+ * Test-only reset. Clears all pending state without notifying
149
+ * listeners — call between integration test cases to avoid
150
+ * cross-contamination.
151
+ */
152
+ export function _resetForTests() {
153
+ byRequestId.clear();
154
+ bySessionId.clear();
155
+ listeners.clear();
156
+ }
157
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/ask-user-question/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ import { Type } from "typebox";
2
+ import { registerPending } from "./registry.js";
3
+ import { validateQuestionnaire } from "./validate.js";
4
+ import { buildResult } from "./envelope.js";
5
+ import { PROMPT_GUIDELINES, PROMPT_SNIPPET, TOOL_DESCRIPTION } from "./prompt-strings.js";
6
+ import { MAX_HEADER_LENGTH, MAX_LABEL_LENGTH, MAX_OPTIONS, MAX_QUESTIONS, MIN_OPTIONS, } from "./types.js";
7
+ export const ASK_USER_QUESTION_TOOL_NAME = "ask_user_question";
8
+ /**
9
+ * JSON Schema for the tool's params. We hand-write the schema
10
+ * (rather than reaching for TypeBox) so the shape matches what the
11
+ * upstream plugin advertises field-for-field. The structural caps
12
+ * (1..MAX_QUESTIONS, MIN..MAX_OPTIONS, maxLength) act as a fast
13
+ * pre-filter; `validateQuestionnaire` runs after for semantic
14
+ * checks the schema can't express (reserved labels, dupes).
15
+ *
16
+ * Type.Unsafe wraps the raw JSON Schema as a TypeBox schema so it
17
+ * satisfies the ToolDefinition.parameters type without dragging
18
+ * the rest of the TypeBox DSL into our code.
19
+ */
20
+ const inputSchema = {
21
+ type: "object",
22
+ required: ["questions"],
23
+ properties: {
24
+ questions: {
25
+ type: "array",
26
+ minItems: 1,
27
+ maxItems: MAX_QUESTIONS,
28
+ items: {
29
+ type: "object",
30
+ required: ["question", "header", "options"],
31
+ properties: {
32
+ question: { type: "string", minLength: 1 },
33
+ header: { type: "string", minLength: 1, maxLength: MAX_HEADER_LENGTH },
34
+ multiSelect: { type: "boolean" },
35
+ options: {
36
+ type: "array",
37
+ minItems: MIN_OPTIONS,
38
+ maxItems: MAX_OPTIONS,
39
+ items: {
40
+ type: "object",
41
+ required: ["label", "description"],
42
+ properties: {
43
+ label: { type: "string", minLength: 1, maxLength: MAX_LABEL_LENGTH },
44
+ description: { type: "string", minLength: 1 },
45
+ preview: { type: "string" },
46
+ },
47
+ },
48
+ },
49
+ },
50
+ },
51
+ },
52
+ },
53
+ };
54
+ /**
55
+ * Build the per-session `ask_user_question` tool. Bound to one
56
+ * session so `execute()` knows which browser to push the
57
+ * questions to.
58
+ *
59
+ * The tool is contract-compatible with
60
+ * `@juicesharp/rpiv-ask-user-question` — agents prompted to use
61
+ * `ask_user_question` get the same input schema, the same
62
+ * response envelope (`{content:[{type:"text",text}], details:{
63
+ * answers, cancelled, error?}}`), and the same answer-kind
64
+ * vocabulary (`option | custom | chat | multi`). Implementation
65
+ * is independent; the contract is reproduced via the published
66
+ * schema descriptions.
67
+ */
68
+ export function createAskUserQuestionTool(sessionId) {
69
+ return {
70
+ name: ASK_USER_QUESTION_TOOL_NAME,
71
+ label: "Ask User Question",
72
+ description: TOOL_DESCRIPTION,
73
+ promptSnippet: PROMPT_SNIPPET,
74
+ promptGuidelines: PROMPT_GUIDELINES,
75
+ parameters: Type.Unsafe(inputSchema),
76
+ async execute(_toolCallId, params, signal) {
77
+ const validation = validateQuestionnaire(params);
78
+ if (!validation.ok) {
79
+ // Validation failure is communicated to the agent in the
80
+ // same shape the plugin uses — `details.error` carries the
81
+ // discriminated code, `details.cancelled` is true, and the
82
+ // text block summarises so the model has something to read.
83
+ return buildResult([], {
84
+ cancelled: true,
85
+ error: validation.error,
86
+ questionCount: 0,
87
+ });
88
+ }
89
+ const { params: q } = validation;
90
+ try {
91
+ const args = {
92
+ sessionId,
93
+ questions: q.questions,
94
+ };
95
+ if (signal !== undefined)
96
+ args.signal = signal;
97
+ const { result } = registerPending(args);
98
+ return await result;
99
+ }
100
+ catch (err) {
101
+ // Abort path — `registerPending` rejects with Error("aborted")
102
+ // when the agent's signal fires. Return a clean cancelled
103
+ // envelope so the agent sees a tool result rather than an
104
+ // unhandled exception in its loop.
105
+ const message = err instanceof Error ? err.message : String(err);
106
+ return buildResult([], {
107
+ cancelled: true,
108
+ error: message,
109
+ questionCount: q.questions.length,
110
+ });
111
+ }
112
+ },
113
+ };
114
+ }
115
+ //# sourceMappingURL=tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/ask-user-question/tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Shape definitions for the `ask_user_question` tool. The wire schema
3
+ * (questions[1..4] with options[2..4]; header ≤16 chars; label ≤60
4
+ * chars; reserved sentinel labels) is contract-compatible with
5
+ * `@juicesharp/rpiv-ask-user-question` — an agent prompt written
6
+ * against the plugin works against this implementation unchanged.
7
+ *
8
+ * Implementation is independent; constants and validation rules were
9
+ * derived from the plugin's published schema descriptions and test
10
+ * fixtures rather than copied. See `docs/ask-user-question.md` for the
11
+ * cross-reference.
12
+ */
13
+ export const MAX_QUESTIONS = 4;
14
+ export const MIN_OPTIONS = 2;
15
+ export const MAX_OPTIONS = 4;
16
+ export const MAX_HEADER_LENGTH = 16;
17
+ export const MAX_LABEL_LENGTH = 60;
18
+ /**
19
+ * Labels the validator rejects at submit time. The four runtime
20
+ * sentinels ("Type something.", "Chat about this", "Next") are
21
+ * appended by the UI so authoring them would collide; "Other" is
22
+ * reserved for CC-style parity (the model often reaches for "Other"
23
+ * when given the chance — we want the runtime sentinel to be the
24
+ * single source of truth).
25
+ */
26
+ export const RESERVED_LABELS = ["Other", "Type something.", "Chat about this", "Next"];
27
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/ask-user-question/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AAC/B,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC;AAC7B,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC;AAC7B,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AACpC,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAEnC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,CAAU,CAAC"}
@@ -0,0 +1,135 @@
1
+ import { MAX_HEADER_LENGTH, MAX_LABEL_LENGTH, MAX_OPTIONS, MAX_QUESTIONS, MIN_OPTIONS, RESERVED_LABELS, } from "./types.js";
2
+ /**
3
+ * Runtime validation for the agent-supplied questionnaire. Mirrors
4
+ * the upstream plugin's rules without porting code. Each failure
5
+ * returns the same error-code vocabulary the plugin uses so a
6
+ * downstream parser doesn't care which implementation answered.
7
+ *
8
+ * The schema layer (Fastify body validation) catches type/shape
9
+ * errors first; this validator enforces the semantic ones: reserved
10
+ * sentinel labels, duplicate labels, the question / option count
11
+ * caps, and the byte-cap on header and label fields. Byte caps live
12
+ * here too (not just in the schema) so a caller that bypassed the
13
+ * schema — e.g. a future programmatic invocation path — still gets
14
+ * the same enforcement.
15
+ */
16
+ export function validateQuestionnaire(input) {
17
+ if (typeof input !== "object" || input === null) {
18
+ return { ok: false, error: "no_questions", message: "params must be an object" };
19
+ }
20
+ const params = input;
21
+ const questions = params.questions;
22
+ if (!Array.isArray(questions) || questions.length === 0) {
23
+ return {
24
+ ok: false,
25
+ error: "no_questions",
26
+ message: "questions[] must have at least one entry",
27
+ };
28
+ }
29
+ if (questions.length > MAX_QUESTIONS) {
30
+ return {
31
+ ok: false,
32
+ error: "too_many_questions",
33
+ message: `at most ${MAX_QUESTIONS} questions per invocation`,
34
+ };
35
+ }
36
+ const reserved = new Set(RESERVED_LABELS);
37
+ for (let qi = 0; qi < questions.length; qi += 1) {
38
+ const q = questions[qi];
39
+ if (typeof q !== "object" || q === null) {
40
+ return {
41
+ ok: false,
42
+ error: "missing_question_text",
43
+ message: `question[${qi}] is not an object`,
44
+ };
45
+ }
46
+ const question = q.question;
47
+ if (typeof question !== "string" || question.trim().length === 0) {
48
+ return {
49
+ ok: false,
50
+ error: "missing_question_text",
51
+ message: `question[${qi}].question is required`,
52
+ };
53
+ }
54
+ const header = q.header;
55
+ if (typeof header !== "string" || header.length === 0) {
56
+ return { ok: false, error: "missing_header", message: `question[${qi}].header is required` };
57
+ }
58
+ if (header.length > MAX_HEADER_LENGTH) {
59
+ return {
60
+ ok: false,
61
+ error: "header_too_long",
62
+ message: `question[${qi}].header exceeds ${MAX_HEADER_LENGTH} chars`,
63
+ };
64
+ }
65
+ const options = q.options;
66
+ if (!Array.isArray(options) || options.length < MIN_OPTIONS) {
67
+ return {
68
+ ok: false,
69
+ error: "too_few_options",
70
+ message: `question[${qi}] requires at least ${MIN_OPTIONS} options`,
71
+ };
72
+ }
73
+ if (options.length > MAX_OPTIONS) {
74
+ return {
75
+ ok: false,
76
+ error: "too_many_options",
77
+ message: `question[${qi}] allows at most ${MAX_OPTIONS} options`,
78
+ };
79
+ }
80
+ const seenLabels = new Set();
81
+ for (let oi = 0; oi < options.length; oi += 1) {
82
+ const opt = options[oi];
83
+ if (typeof opt !== "object" || opt === null) {
84
+ return {
85
+ ok: false,
86
+ error: "missing_label",
87
+ message: `question[${qi}].options[${oi}] is not an object`,
88
+ };
89
+ }
90
+ const label = opt.label;
91
+ if (typeof label !== "string" || label.length === 0) {
92
+ return {
93
+ ok: false,
94
+ error: "missing_label",
95
+ message: `question[${qi}].options[${oi}].label is required`,
96
+ };
97
+ }
98
+ if (label.length > MAX_LABEL_LENGTH) {
99
+ return {
100
+ ok: false,
101
+ error: "label_too_long",
102
+ message: `question[${qi}].options[${oi}].label exceeds ${MAX_LABEL_LENGTH} chars`,
103
+ };
104
+ }
105
+ // Reserved-label check applies to every kind (multiSelect too)
106
+ // so the runtime sentinels stay the single source of truth even
107
+ // when the UI suppresses them.
108
+ if (reserved.has(label)) {
109
+ return {
110
+ ok: false,
111
+ error: "reserved_label",
112
+ message: `question[${qi}].options[${oi}].label "${label}" is reserved — pick a different label`,
113
+ };
114
+ }
115
+ if (seenLabels.has(label)) {
116
+ return {
117
+ ok: false,
118
+ error: "duplicate_label",
119
+ message: `question[${qi}].options[${oi}].label "${label}" duplicates an earlier option`,
120
+ };
121
+ }
122
+ seenLabels.add(label);
123
+ const description = opt.description;
124
+ if (typeof description !== "string" || description.length === 0) {
125
+ return {
126
+ ok: false,
127
+ error: "missing_description",
128
+ message: `question[${qi}].options[${oi}].description is required`,
129
+ };
130
+ }
131
+ }
132
+ }
133
+ return { ok: true, params: params };
134
+ }
135
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/ask-user-question/validate.ts"],"names":[],"mappings":"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"}