@shawnstack/quickforge 1.5.1 → 1.5.3

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 (45) hide show
  1. package/README.md +10 -10
  2. package/dist/assets/AgentProfilesPage-BToo_R3Y.js +1 -0
  3. package/dist/assets/ChatPanelHost-BTqhhkWK.js +242 -0
  4. package/dist/assets/{PluginsPage-kRzB5k8J.js → PluginsPage-DwzV2vQ4.js} +1 -1
  5. package/dist/assets/ScheduledTasksPage-Cbm6LVk3.js +2 -0
  6. package/dist/assets/{SharedConversationPage-EQdZgWCM.js → SharedConversationPage-CHE9qABz.js} +1 -1
  7. package/dist/assets/TerminalDock-Loi8A4pJ.js +2 -0
  8. package/dist/assets/WorkspaceInspector-Nf5xELW7.js +3 -0
  9. package/dist/assets/{WorkspaceReaderDialog-BwzZ8Tgv.js → WorkspaceReaderDialog-Bai7v3V0.js} +1 -1
  10. package/dist/assets/{diff-line-counts-CeZC7b0z.js → diff-line-counts-CCPYa_e0.js} +1 -1
  11. package/dist/assets/icons-DzxBk7tb.js +1 -0
  12. package/dist/assets/index-Bt_dRvdG.js +1476 -0
  13. package/dist/assets/{index-DuTUuAMk.css → index-BzaZg9Br.css} +1 -1
  14. package/dist/assets/{monaco-CNEfYIy1.js → monaco-dMY7_GLO.js} +1 -1
  15. package/dist/assets/{react-vendor-CZCcjpSR.js → react-vendor-DsAeMFcm.js} +1 -1
  16. package/dist/index.html +4 -4
  17. package/package.json +1 -1
  18. package/server/acp/server.mjs +1 -0
  19. package/server/agent-manager.mjs +6 -6
  20. package/server/agent-profile-files.mjs +2 -1
  21. package/server/channels/process-channel.mjs +1 -0
  22. package/server/channels/providers/wechat.mjs +1 -0
  23. package/server/custom-commands.mjs +4 -3
  24. package/server/mcp/config.mjs +20 -20
  25. package/server/plugins/registry.mjs +1 -1
  26. package/server/project-config.mjs +2 -2
  27. package/server/routes/agent.mjs +0 -1
  28. package/server/routes/backup.mjs +84 -20
  29. package/server/routes/project.mjs +3 -2
  30. package/server/routes/scheduled-tasks.mjs +13 -121
  31. package/server/routes/static.mjs +1 -1
  32. package/server/routes/storage.mjs +13 -7
  33. package/server/session-utils.mjs +2 -1
  34. package/server/skills.mjs +3 -2
  35. package/server/storage.mjs +182 -49
  36. package/server/utils/logger.mjs +0 -1
  37. package/server/utils/package-update.mjs +2 -2
  38. package/server/utils/scheduled-tasks.mjs +127 -0
  39. package/dist/assets/AgentProfilesPage-BIwd5Nzg.js +0 -1
  40. package/dist/assets/ChatPanelHost-De-DMjx5.js +0 -242
  41. package/dist/assets/ScheduledTasksPage-ZnjohaPS.js +0 -2
  42. package/dist/assets/TerminalDock-P2pJH_tx.js +0 -2
  43. package/dist/assets/WorkspaceInspector-CkLAqYQ6.js +0 -3
  44. package/dist/assets/icons-DJqt-rnw.js +0 -1
  45. package/dist/assets/index-CcGy4TXo.js +0 -1354
@@ -1,4 +1,4 @@
1
- import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{Ct as t}from"./icons-DJqt-rnw.js";function n(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function r(e){if(Array.isArray(e))return e}function i(e,t,n){return(t=p(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=e==null?null:typeof Symbol<`u`&&e[Symbol.iterator]||e[`@@iterator`];if(n!=null){var r,i,a,o,s=[],c=!0,l=!1;try{if(a=(n=n.call(e)).next,t!==0)for(;!(c=(r=a.call(n)).done)&&(s.push(r.value),s.length!==t);c=!0);}catch(e){l=!0,i=e}finally{try{if(!c&&n.return!=null&&(o=n.return(),Object(o)!==o))return}finally{if(l)throw i}}return s}}function o(){throw TypeError(`Invalid attempt to destructure non-iterable instance.
1
+ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{wt as t}from"./icons-DzxBk7tb.js";function n(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function r(e){if(Array.isArray(e))return e}function i(e,t,n){return(t=p(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=e==null?null:typeof Symbol<`u`&&e[Symbol.iterator]||e[`@@iterator`];if(n!=null){var r,i,a,o,s=[],c=!0,l=!1;try{if(a=(n=n.call(e)).next,t!==0)for(;!(c=(r=a.call(n)).done)&&(s.push(r.value),s.length!==t);c=!0);}catch(e){l=!0,i=e}finally{try{if(!c&&n.return!=null&&(o=n.return(),Object(o)!==o))return}finally{if(l)throw i}}return s}}function o(){throw TypeError(`Invalid attempt to destructure non-iterable instance.
2
2
  In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function s(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function c(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?s(Object(n),!0).forEach(function(t){i(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):s(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}function l(e,t){if(e==null)return{};var n,r,i=u(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)===-1&&{}.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function u(e,t){if(e==null)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.indexOf(r)!==-1)continue;n[r]=e[r]}return n}function d(e,t){return r(e)||a(e,t)||m(e,t)||o()}function f(e,t){if(typeof e!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t);if(typeof r!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function p(e){var t=f(e,`string`);return typeof t==`symbol`?t:t+``}function m(e,t){if(e){if(typeof e==`string`)return n(e,t);var r={}.toString.call(e).slice(8,-1);return r===`Object`&&e.constructor&&(r=e.constructor.name),r===`Map`||r===`Set`?Array.from(e):r===`Arguments`||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?n(e,t):void 0}}function h(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function g(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function _(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?g(Object(n),!0).forEach(function(t){h(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):g(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}function v(){var e=[...arguments];return function(t){return e.reduceRight(function(e,t){return t(e)},t)}}function y(e){return function t(){var n=this,r=[...arguments];return r.length>=e.length?e.apply(this,r):function(){var e=[...arguments];return t.apply(n,[].concat(r,e))}}}function b(e){return{}.toString.call(e).includes(`Object`)}function x(e){return!Object.keys(e).length}function S(e){return typeof e==`function`}function C(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function w(e,t){return b(t)||k(`changeType`),Object.keys(t).some(function(t){return!C(e,t)})&&k(`changeField`),t}function T(e){S(e)||k(`selectorType`)}function E(e){S(e)||b(e)||k(`handlerType`),b(e)&&Object.values(e).some(function(e){return!S(e)})&&k(`handlersType`)}function D(e){e||k(`initialIsRequired`),b(e)||k(`initialType`),x(e)&&k(`initialContent`)}function O(e,t){throw Error(e[t]||e.default)}var k=y(O)({initialIsRequired:`initial state is required`,initialType:`initial state should be an object`,initialContent:`initial state shouldn't be an empty object`,handlerType:`handler should be an object or a function`,handlersType:`all handlers should be a functions`,selectorType:`selector should be a function`,changeType:`provided value of changes should be an object`,changeField:`it seams you want to change a field in the state which is not specified in the "initial" state`,default:"an unknown error accured in `state-local` package"}),A={changes:w,selector:T,handler:E,initial:D};function j(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};A.initial(e),A.handler(t);var n={current:e},r=y(P)(n,t),i=y(N)(n),a=y(A.changes)(e),o=y(M)(n);function s(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:function(e){return e};return A.selector(e),e(n.current)}function c(e){v(r,i,a,o)(e)}return[s,c]}function M(e,t){return S(t)?t(e.current):t}function N(e,t){return e.current=_(_({},e.current),t),t}function P(e,t,n){return S(t)?t(e.current):Object.keys(n).forEach(function(n){return t[n]?.call(t,e.current[n])}),n}var F={create:j},I={paths:{vs:`https://cdn.jsdelivr.net/npm/monaco-editor@0.55.1/min/vs`}};function ee(e){return function t(){var n=this,r=[...arguments];return r.length>=e.length?e.apply(this,r):function(){var e=[...arguments];return t.apply(n,[].concat(r,e))}}}function te(e){return{}.toString.call(e).includes(`Object`)}function ne(e){return e||R(`configIsRequired`),te(e)||R(`configType`),e.urls?(re(),{paths:{vs:e.urls.monacoBase}}):e}function re(){console.warn(L.deprecation)}function ie(e,t){throw Error(e[t]||e.default)}var L={configIsRequired:`the configuration object is required`,configType:`the configuration object should be an object`,default:"an unknown error accured in `@monaco-editor/loader` package",deprecation:`Deprecation warning!
3
3
  You are using deprecated way of configuration.
4
4
 
@@ -1,4 +1,4 @@
1
- import{t as e}from"./rolldown-runtime-DWdDZTNf.js";import{Ct as t}from"./icons-DJqt-rnw.js";var n=e((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0<n;){var r=n-1>>>1,a=e[r];if(0<i(a,t))e[r]=t,e[n]=a,n=r;else break a}}function n(e){return e.length===0?null:e[0]}function r(e){if(e.length===0)return null;var t=e[0],n=e.pop();if(n!==t){e[0]=n;a:for(var r=0,a=e.length,o=a>>>1;r<o;){var s=2*(r+1)-1,c=e[s],l=s+1,u=e[l];if(0>i(c,n))l<a&&0>i(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(l<a&&0>i(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m)if(n(c)!==null)m=!0,S||(S=!0,D());else{var t=n(l);t!==null&&A(x,t.startTime-e)}}var S=!1,C=-1,ee=5,w=-1;function T(){return g?!0:!(e.unstable_now()-w<ee)}function E(){if(g=!1,S){var t=e.unstable_now();w=t;var i=!0;try{a:{m=!1,h&&(h=!1,v(C),C=-1),p=!0;var a=f;try{b:{for(b(t),d=n(c);d!==null&&!(d.expirationTime>t&&T());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&A(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}i=void 0}}finally{i?D():S=!1}}}var D;if(typeof y==`function`)D=function(){y(E)};else if(typeof MessageChannel<`u`){var O=new MessageChannel,k=O.port2;O.port1.onmessage=E,D=function(){k.postMessage(null)}}else D=function(){_(E,0)};function A(t,n){C=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125<e?console.error(`forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported`):ee=0<e?Math.floor(1e3/e):5},e.unstable_getCurrentPriorityLevel=function(){return f},e.unstable_next=function(e){switch(f){case 1:case 2:case 3:var t=3;break;default:t=f}var n=f;f=t;try{return e()}finally{f=n}},e.unstable_requestPaint=function(){g=!0},e.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=f;f=e;try{return t()}finally{f=n}},e.unstable_scheduleCallback=function(r,i,a){var o=e.unstable_now();switch(typeof a==`object`&&a?(a=a.delay,a=typeof a==`number`&&0<a?o+a:o):a=o,r){case 1:var s=-1;break;case 2:s=250;break;case 5:s=1073741823;break;case 4:s=1e4;break;default:s=5e3}return s=a+s,r={id:u++,callback:i,priorityLevel:r,startTime:a,expirationTime:s,sortIndex:-1},a>o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(C),C=-1):h=!0,A(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,S||(S=!0,D()))),r},e.unstable_shouldYield=T,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),r=e(((e,t)=>{t.exports=n()})),i=e((e=>{var n=t();function r(e){var t=`https://react.dev/errors/`+e;if(1<arguments.length){t+=`?args[]=`+encodeURIComponent(arguments[1]);for(var n=2;n<arguments.length;n++)t+=`&args[]=`+encodeURIComponent(arguments[n])}return`Minified React error #`+e+`; visit `+t+` for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`}function i(){}var a={d:{f:i,r:function(){throw Error(r(522))},D:i,C:i,L:i,m:i,X:i,S:i,M:i},p:0,findDOMNode:null},o=Symbol.for(`react.portal`);function s(e,t,n){var r=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null;return{$$typeof:o,key:r==null?null:``+r,children:e,containerInfo:t,implementation:n}}var c=n.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;function l(e,t){if(e===`font`)return``;if(typeof t==`string`)return t===`use-credentials`?t:``}e.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=a,e.createPortal=function(e,t){var n=2<arguments.length&&arguments[2]!==void 0?arguments[2]:null;if(!t||t.nodeType!==1&&t.nodeType!==9&&t.nodeType!==11)throw Error(r(299));return s(e,t,null,n)},e.flushSync=function(e){var t=c.T,n=a.p;try{if(c.T=null,a.p=2,e)return e()}finally{c.T=t,a.p=n,a.d.f()}},e.preconnect=function(e,t){typeof e==`string`&&(t?(t=t.crossOrigin,t=typeof t==`string`?t===`use-credentials`?t:``:void 0):t=null,a.d.C(e,t))},e.prefetchDNS=function(e){typeof e==`string`&&a.d.D(e)},e.preinit=function(e,t){if(typeof e==`string`&&t&&typeof t.as==`string`){var n=t.as,r=l(n,t.crossOrigin),i=typeof t.integrity==`string`?t.integrity:void 0,o=typeof t.fetchPriority==`string`?t.fetchPriority:void 0;n===`style`?a.d.S(e,typeof t.precedence==`string`?t.precedence:void 0,{crossOrigin:r,integrity:i,fetchPriority:o}):n===`script`&&a.d.X(e,{crossOrigin:r,integrity:i,fetchPriority:o,nonce:typeof t.nonce==`string`?t.nonce:void 0})}},e.preinitModule=function(e,t){if(typeof e==`string`)if(typeof t==`object`&&t){if(t.as==null||t.as===`script`){var n=l(t.as,t.crossOrigin);a.d.M(e,{crossOrigin:n,integrity:typeof t.integrity==`string`?t.integrity:void 0,nonce:typeof t.nonce==`string`?t.nonce:void 0})}}else t??a.d.M(e)},e.preload=function(e,t){if(typeof e==`string`&&typeof t==`object`&&t&&typeof t.as==`string`){var n=t.as,r=l(n,t.crossOrigin);a.d.L(e,n,{crossOrigin:r,integrity:typeof t.integrity==`string`?t.integrity:void 0,nonce:typeof t.nonce==`string`?t.nonce:void 0,type:typeof t.type==`string`?t.type:void 0,fetchPriority:typeof t.fetchPriority==`string`?t.fetchPriority:void 0,referrerPolicy:typeof t.referrerPolicy==`string`?t.referrerPolicy:void 0,imageSrcSet:typeof t.imageSrcSet==`string`?t.imageSrcSet:void 0,imageSizes:typeof t.imageSizes==`string`?t.imageSizes:void 0,media:typeof t.media==`string`?t.media:void 0})}},e.preloadModule=function(e,t){if(typeof e==`string`)if(t){var n=l(t.as,t.crossOrigin);a.d.m(e,{as:typeof t.as==`string`&&t.as!==`script`?t.as:void 0,crossOrigin:n,integrity:typeof t.integrity==`string`?t.integrity:void 0})}else a.d.m(e)},e.requestFormReset=function(e){a.d.r(e)},e.unstable_batchedUpdates=function(e,t){return e(t)},e.useFormState=function(e,t,n){return c.H.useFormState(e,t,n)},e.useFormStatus=function(){return c.H.useHostTransitionStatus()},e.version=`19.2.5`})),a=e(((e,t)=>{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=i()})),o=e((e=>{var n=r(),i=t(),o=a();function s(e){var t=`https://react.dev/errors/`+e;if(1<arguments.length){t+=`?args[]=`+encodeURIComponent(arguments[1]);for(var n=2;n<arguments.length;n++)t+=`&args[]=`+encodeURIComponent(arguments[n])}return`Minified React error #`+e+`; visit `+t+` for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`}function c(e){return!(!e||e.nodeType!==1&&e.nodeType!==9&&e.nodeType!==11)}function l(e){var t=e,n=e;if(e.alternate)for(;t.return;)t=t.return;else{e=t;do t=e,t.flags&4098&&(n=t.return),e=t.return;while(e)}return t.tag===3?n:null}function u(e){if(e.tag===13){var t=e.memoizedState;if(t===null&&(e=e.alternate,e!==null&&(t=e.memoizedState)),t!==null)return t.dehydrated}return null}function d(e){if(e.tag===31){var t=e.memoizedState;if(t===null&&(e=e.alternate,e!==null&&(t=e.memoizedState)),t!==null)return t.dehydrated}return null}function f(e){if(l(e)!==e)throw Error(s(188))}function p(e){var t=e.alternate;if(!t){if(t=l(e),t===null)throw Error(s(188));return t===e?e:null}for(var n=e,r=t;;){var i=n.return;if(i===null)break;var a=i.alternate;if(a===null){if(r=i.return,r!==null){n=r;continue}break}if(i.child===a.child){for(a=i.child;a;){if(a===n)return f(i),e;if(a===r)return f(i),t;a=a.sibling}throw Error(s(188))}if(n.return!==r.return)n=i,r=a;else{for(var o=!1,c=i.child;c;){if(c===n){o=!0,n=i,r=a;break}if(c===r){o=!0,r=i,n=a;break}c=c.sibling}if(!o){for(c=a.child;c;){if(c===n){o=!0,n=a,r=i;break}if(c===r){o=!0,r=a,n=i;break}c=c.sibling}if(!o)throw Error(s(189))}}if(n.alternate!==r)throw Error(s(190))}if(n.tag!==3)throw Error(s(188));return n.stateNode.current===n?e:t}function m(e){var t=e.tag;if(t===5||t===26||t===27||t===6)return e;for(e=e.child;e!==null;){if(t=m(e),t!==null)return t;e=e.sibling}return null}var h=Object.assign,g=Symbol.for(`react.element`),_=Symbol.for(`react.transitional.element`),v=Symbol.for(`react.portal`),y=Symbol.for(`react.fragment`),b=Symbol.for(`react.strict_mode`),x=Symbol.for(`react.profiler`),S=Symbol.for(`react.consumer`),C=Symbol.for(`react.context`),ee=Symbol.for(`react.forward_ref`),w=Symbol.for(`react.suspense`),T=Symbol.for(`react.suspense_list`),E=Symbol.for(`react.memo`),D=Symbol.for(`react.lazy`),O=Symbol.for(`react.activity`),k=Symbol.for(`react.memo_cache_sentinel`),A=Symbol.iterator;function te(e){return typeof e!=`object`||!e?null:(e=A&&e[A]||e[`@@iterator`],typeof e==`function`?e:null)}var j=Symbol.for(`react.client.reference`);function M(e){if(e==null)return null;if(typeof e==`function`)return e.$$typeof===j?null:e.displayName||e.name||null;if(typeof e==`string`)return e;switch(e){case y:return`Fragment`;case x:return`Profiler`;case b:return`StrictMode`;case w:return`Suspense`;case T:return`SuspenseList`;case O:return`Activity`}if(typeof e==`object`)switch(e.$$typeof){case v:return`Portal`;case C:return e.displayName||`Context`;case S:return(e._context.displayName||`Context`)+`.Consumer`;case ee:var t=e.render;return e=e.displayName,e||=(e=t.displayName||t.name||``,e===``?`ForwardRef`:`ForwardRef(`+e+`)`),e;case E:return t=e.displayName||null,t===null?M(e.type)||`Memo`:t;case D:t=e._payload,e=e._init;try{return M(e(t))}catch{}}return null}var N=Array.isArray,P=i.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,F=o.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,ne={pending:!1,data:null,method:null,action:null},I=[],L=-1;function re(e){return{current:e}}function R(e){0>L||(e.current=I[L],I[L]=null,L--)}function z(e,t){L++,I[L]=e.current,e.current=t}var B=re(null),ie=re(null),ae=re(null),oe=re(null);function se(e,t){switch(z(ae,t),z(ie,e),z(B,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Vd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Vd(t),e=Hd(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}R(B),z(B,e)}function ce(){R(B),R(ie),R(ae)}function V(e){e.memoizedState!==null&&z(oe,e);var t=B.current,n=Hd(t,e.type);t!==n&&(z(ie,e),z(B,n))}function le(e){ie.current===e&&(R(B),R(ie)),oe.current===e&&(R(oe),Qf._currentValue=ne)}var H,ue;function de(e){if(H===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);H=t&&t[1]||``,ue=-1<e.stack.indexOf(`
1
+ import{t as e}from"./rolldown-runtime-DWdDZTNf.js";import{wt as t}from"./icons-DzxBk7tb.js";var n=e((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0<n;){var r=n-1>>>1,a=e[r];if(0<i(a,t))e[r]=t,e[n]=a,n=r;else break a}}function n(e){return e.length===0?null:e[0]}function r(e){if(e.length===0)return null;var t=e[0],n=e.pop();if(n!==t){e[0]=n;a:for(var r=0,a=e.length,o=a>>>1;r<o;){var s=2*(r+1)-1,c=e[s],l=s+1,u=e[l];if(0>i(c,n))l<a&&0>i(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(l<a&&0>i(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m)if(n(c)!==null)m=!0,S||(S=!0,D());else{var t=n(l);t!==null&&A(x,t.startTime-e)}}var S=!1,C=-1,ee=5,w=-1;function T(){return g?!0:!(e.unstable_now()-w<ee)}function E(){if(g=!1,S){var t=e.unstable_now();w=t;var i=!0;try{a:{m=!1,h&&(h=!1,v(C),C=-1),p=!0;var a=f;try{b:{for(b(t),d=n(c);d!==null&&!(d.expirationTime>t&&T());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&A(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}i=void 0}}finally{i?D():S=!1}}}var D;if(typeof y==`function`)D=function(){y(E)};else if(typeof MessageChannel<`u`){var O=new MessageChannel,k=O.port2;O.port1.onmessage=E,D=function(){k.postMessage(null)}}else D=function(){_(E,0)};function A(t,n){C=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125<e?console.error(`forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported`):ee=0<e?Math.floor(1e3/e):5},e.unstable_getCurrentPriorityLevel=function(){return f},e.unstable_next=function(e){switch(f){case 1:case 2:case 3:var t=3;break;default:t=f}var n=f;f=t;try{return e()}finally{f=n}},e.unstable_requestPaint=function(){g=!0},e.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=f;f=e;try{return t()}finally{f=n}},e.unstable_scheduleCallback=function(r,i,a){var o=e.unstable_now();switch(typeof a==`object`&&a?(a=a.delay,a=typeof a==`number`&&0<a?o+a:o):a=o,r){case 1:var s=-1;break;case 2:s=250;break;case 5:s=1073741823;break;case 4:s=1e4;break;default:s=5e3}return s=a+s,r={id:u++,callback:i,priorityLevel:r,startTime:a,expirationTime:s,sortIndex:-1},a>o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(C),C=-1):h=!0,A(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,S||(S=!0,D()))),r},e.unstable_shouldYield=T,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),r=e(((e,t)=>{t.exports=n()})),i=e((e=>{var n=t();function r(e){var t=`https://react.dev/errors/`+e;if(1<arguments.length){t+=`?args[]=`+encodeURIComponent(arguments[1]);for(var n=2;n<arguments.length;n++)t+=`&args[]=`+encodeURIComponent(arguments[n])}return`Minified React error #`+e+`; visit `+t+` for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`}function i(){}var a={d:{f:i,r:function(){throw Error(r(522))},D:i,C:i,L:i,m:i,X:i,S:i,M:i},p:0,findDOMNode:null},o=Symbol.for(`react.portal`);function s(e,t,n){var r=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null;return{$$typeof:o,key:r==null?null:``+r,children:e,containerInfo:t,implementation:n}}var c=n.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;function l(e,t){if(e===`font`)return``;if(typeof t==`string`)return t===`use-credentials`?t:``}e.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=a,e.createPortal=function(e,t){var n=2<arguments.length&&arguments[2]!==void 0?arguments[2]:null;if(!t||t.nodeType!==1&&t.nodeType!==9&&t.nodeType!==11)throw Error(r(299));return s(e,t,null,n)},e.flushSync=function(e){var t=c.T,n=a.p;try{if(c.T=null,a.p=2,e)return e()}finally{c.T=t,a.p=n,a.d.f()}},e.preconnect=function(e,t){typeof e==`string`&&(t?(t=t.crossOrigin,t=typeof t==`string`?t===`use-credentials`?t:``:void 0):t=null,a.d.C(e,t))},e.prefetchDNS=function(e){typeof e==`string`&&a.d.D(e)},e.preinit=function(e,t){if(typeof e==`string`&&t&&typeof t.as==`string`){var n=t.as,r=l(n,t.crossOrigin),i=typeof t.integrity==`string`?t.integrity:void 0,o=typeof t.fetchPriority==`string`?t.fetchPriority:void 0;n===`style`?a.d.S(e,typeof t.precedence==`string`?t.precedence:void 0,{crossOrigin:r,integrity:i,fetchPriority:o}):n===`script`&&a.d.X(e,{crossOrigin:r,integrity:i,fetchPriority:o,nonce:typeof t.nonce==`string`?t.nonce:void 0})}},e.preinitModule=function(e,t){if(typeof e==`string`)if(typeof t==`object`&&t){if(t.as==null||t.as===`script`){var n=l(t.as,t.crossOrigin);a.d.M(e,{crossOrigin:n,integrity:typeof t.integrity==`string`?t.integrity:void 0,nonce:typeof t.nonce==`string`?t.nonce:void 0})}}else t??a.d.M(e)},e.preload=function(e,t){if(typeof e==`string`&&typeof t==`object`&&t&&typeof t.as==`string`){var n=t.as,r=l(n,t.crossOrigin);a.d.L(e,n,{crossOrigin:r,integrity:typeof t.integrity==`string`?t.integrity:void 0,nonce:typeof t.nonce==`string`?t.nonce:void 0,type:typeof t.type==`string`?t.type:void 0,fetchPriority:typeof t.fetchPriority==`string`?t.fetchPriority:void 0,referrerPolicy:typeof t.referrerPolicy==`string`?t.referrerPolicy:void 0,imageSrcSet:typeof t.imageSrcSet==`string`?t.imageSrcSet:void 0,imageSizes:typeof t.imageSizes==`string`?t.imageSizes:void 0,media:typeof t.media==`string`?t.media:void 0})}},e.preloadModule=function(e,t){if(typeof e==`string`)if(t){var n=l(t.as,t.crossOrigin);a.d.m(e,{as:typeof t.as==`string`&&t.as!==`script`?t.as:void 0,crossOrigin:n,integrity:typeof t.integrity==`string`?t.integrity:void 0})}else a.d.m(e)},e.requestFormReset=function(e){a.d.r(e)},e.unstable_batchedUpdates=function(e,t){return e(t)},e.useFormState=function(e,t,n){return c.H.useFormState(e,t,n)},e.useFormStatus=function(){return c.H.useHostTransitionStatus()},e.version=`19.2.5`})),a=e(((e,t)=>{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=i()})),o=e((e=>{var n=r(),i=t(),o=a();function s(e){var t=`https://react.dev/errors/`+e;if(1<arguments.length){t+=`?args[]=`+encodeURIComponent(arguments[1]);for(var n=2;n<arguments.length;n++)t+=`&args[]=`+encodeURIComponent(arguments[n])}return`Minified React error #`+e+`; visit `+t+` for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`}function c(e){return!(!e||e.nodeType!==1&&e.nodeType!==9&&e.nodeType!==11)}function l(e){var t=e,n=e;if(e.alternate)for(;t.return;)t=t.return;else{e=t;do t=e,t.flags&4098&&(n=t.return),e=t.return;while(e)}return t.tag===3?n:null}function u(e){if(e.tag===13){var t=e.memoizedState;if(t===null&&(e=e.alternate,e!==null&&(t=e.memoizedState)),t!==null)return t.dehydrated}return null}function d(e){if(e.tag===31){var t=e.memoizedState;if(t===null&&(e=e.alternate,e!==null&&(t=e.memoizedState)),t!==null)return t.dehydrated}return null}function f(e){if(l(e)!==e)throw Error(s(188))}function p(e){var t=e.alternate;if(!t){if(t=l(e),t===null)throw Error(s(188));return t===e?e:null}for(var n=e,r=t;;){var i=n.return;if(i===null)break;var a=i.alternate;if(a===null){if(r=i.return,r!==null){n=r;continue}break}if(i.child===a.child){for(a=i.child;a;){if(a===n)return f(i),e;if(a===r)return f(i),t;a=a.sibling}throw Error(s(188))}if(n.return!==r.return)n=i,r=a;else{for(var o=!1,c=i.child;c;){if(c===n){o=!0,n=i,r=a;break}if(c===r){o=!0,r=i,n=a;break}c=c.sibling}if(!o){for(c=a.child;c;){if(c===n){o=!0,n=a,r=i;break}if(c===r){o=!0,r=a,n=i;break}c=c.sibling}if(!o)throw Error(s(189))}}if(n.alternate!==r)throw Error(s(190))}if(n.tag!==3)throw Error(s(188));return n.stateNode.current===n?e:t}function m(e){var t=e.tag;if(t===5||t===26||t===27||t===6)return e;for(e=e.child;e!==null;){if(t=m(e),t!==null)return t;e=e.sibling}return null}var h=Object.assign,g=Symbol.for(`react.element`),_=Symbol.for(`react.transitional.element`),v=Symbol.for(`react.portal`),y=Symbol.for(`react.fragment`),b=Symbol.for(`react.strict_mode`),x=Symbol.for(`react.profiler`),S=Symbol.for(`react.consumer`),C=Symbol.for(`react.context`),ee=Symbol.for(`react.forward_ref`),w=Symbol.for(`react.suspense`),T=Symbol.for(`react.suspense_list`),E=Symbol.for(`react.memo`),D=Symbol.for(`react.lazy`),O=Symbol.for(`react.activity`),k=Symbol.for(`react.memo_cache_sentinel`),A=Symbol.iterator;function te(e){return typeof e!=`object`||!e?null:(e=A&&e[A]||e[`@@iterator`],typeof e==`function`?e:null)}var j=Symbol.for(`react.client.reference`);function M(e){if(e==null)return null;if(typeof e==`function`)return e.$$typeof===j?null:e.displayName||e.name||null;if(typeof e==`string`)return e;switch(e){case y:return`Fragment`;case x:return`Profiler`;case b:return`StrictMode`;case w:return`Suspense`;case T:return`SuspenseList`;case O:return`Activity`}if(typeof e==`object`)switch(e.$$typeof){case v:return`Portal`;case C:return e.displayName||`Context`;case S:return(e._context.displayName||`Context`)+`.Consumer`;case ee:var t=e.render;return e=e.displayName,e||=(e=t.displayName||t.name||``,e===``?`ForwardRef`:`ForwardRef(`+e+`)`),e;case E:return t=e.displayName||null,t===null?M(e.type)||`Memo`:t;case D:t=e._payload,e=e._init;try{return M(e(t))}catch{}}return null}var N=Array.isArray,P=i.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,F=o.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,ne={pending:!1,data:null,method:null,action:null},I=[],L=-1;function re(e){return{current:e}}function R(e){0>L||(e.current=I[L],I[L]=null,L--)}function z(e,t){L++,I[L]=e.current,e.current=t}var B=re(null),ie=re(null),ae=re(null),oe=re(null);function se(e,t){switch(z(ae,t),z(ie,e),z(B,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Vd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Vd(t),e=Hd(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}R(B),z(B,e)}function ce(){R(B),R(ie),R(ae)}function V(e){e.memoizedState!==null&&z(oe,e);var t=B.current,n=Hd(t,e.type);t!==n&&(z(ie,e),z(B,n))}function le(e){ie.current===e&&(R(B),R(ie)),oe.current===e&&(R(oe),Qf._currentValue=ne)}var H,ue;function de(e){if(H===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);H=t&&t[1]||``,ue=-1<e.stack.indexOf(`
2
2
  at`)?` (<anonymous>)`:-1<e.stack.indexOf(`@`)?`@unknown:0:0`:``}return`
3
3
  `+H+e+ue}var fe=!1;function pe(e,t){if(!e||fe)return``;fe=!0;var n=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{var r={DetermineComponentFrameRoot:function(){try{if(t){var n=function(){throw Error()};if(Object.defineProperty(n.prototype,`props`,{set:function(){throw Error()}}),typeof Reflect==`object`&&Reflect.construct){try{Reflect.construct(n,[])}catch(e){var r=e}Reflect.construct(e,[],n)}else{try{n.call()}catch(e){r=e}e.call(n.prototype)}}else{try{throw Error()}catch(e){r=e}(n=e())&&typeof n.catch==`function`&&n.catch(function(){})}}catch(e){if(e&&r&&typeof e.stack==`string`)return[e.stack,r.stack]}return[null,null]}};r.DetermineComponentFrameRoot.displayName=`DetermineComponentFrameRoot`;var i=Object.getOwnPropertyDescriptor(r.DetermineComponentFrameRoot,`name`);i&&i.configurable&&Object.defineProperty(r.DetermineComponentFrameRoot,`name`,{value:`DetermineComponentFrameRoot`});var a=r.DetermineComponentFrameRoot(),o=a[0],s=a[1];if(o&&s){var c=o.split(`
4
4
  `),l=s.split(`
package/dist/index.html CHANGED
@@ -11,16 +11,16 @@
11
11
  <meta name="apple-mobile-web-app-title" content="QuickForge" />
12
12
  <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
13
13
  <title>速构 QuickForge</title>
14
- <script type="module" crossorigin src="/assets/index-CcGy4TXo.js"></script>
14
+ <script type="module" crossorigin src="/assets/index-Bt_dRvdG.js"></script>
15
15
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-DWdDZTNf.js">
16
16
  <link rel="modulepreload" crossorigin href="/assets/pi-ai-Cx633yhb.js">
17
17
  <link rel="modulepreload" crossorigin href="/assets/lit-vendor-Dr3cpBGF.js">
18
18
  <link rel="modulepreload" crossorigin href="/assets/pi-web-ui-CBet4bMl.js">
19
19
  <link rel="modulepreload" crossorigin href="/assets/css-utils-rkE68RDy.js">
20
- <link rel="modulepreload" crossorigin href="/assets/icons-DJqt-rnw.js">
21
- <link rel="modulepreload" crossorigin href="/assets/react-vendor-CZCcjpSR.js">
20
+ <link rel="modulepreload" crossorigin href="/assets/icons-DzxBk7tb.js">
21
+ <link rel="modulepreload" crossorigin href="/assets/react-vendor-DsAeMFcm.js">
22
22
  <link rel="modulepreload" crossorigin href="/assets/logger-B65Akg8A.js">
23
- <link rel="stylesheet" crossorigin href="/assets/index-DuTUuAMk.css">
23
+ <link rel="stylesheet" crossorigin href="/assets/index-BzaZg9Br.css">
24
24
  </head>
25
25
  <body>
26
26
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shawnstack/quickforge",
3
- "version": "1.5.1",
3
+ "version": "1.5.3",
4
4
  "description": "AI chat application with Agent access modes for local workspace tools. React + Vite + Tailwind CSS frontend, local Node.js storage server.",
5
5
  "keywords": [
6
6
  "ai",
@@ -889,6 +889,7 @@ export async function createQuickForgeAcpAgent() {
889
889
  }
890
890
  }
891
891
 
892
+ /* eslint-disable no-console -- ACP stdio mode redirects console.log away from stdout protocol traffic. */
892
893
  export async function runQuickForgeAcpStdio() {
893
894
  const originalConsoleLog = console.log
894
895
  console.log = (...args) => console.error(...args)
@@ -34,8 +34,8 @@ import {
34
34
  parseInternalCommandInvocation,
35
35
  resolveCustomCommandInvocation,
36
36
  } from './custom-commands.mjs'
37
- import { omitDetailsForLlm, serverConvertToLlm, messageText, lastAssistantText } from './message-converters.mjs'
38
- import { isPlainObject, mergeQuickForgeTiming, wrapToolDefinition, wrapMcpToolDefinition, wrapPluginToolDefinition, sessionSkillsContext } from './tool-wiring.mjs'
37
+ import { serverConvertToLlm, messageText, lastAssistantText } from './message-converters.mjs'
38
+ import { mergeQuickForgeTiming, wrapToolDefinition, wrapMcpToolDefinition, wrapPluginToolDefinition, sessionSkillsContext } from './tool-wiring.mjs'
39
39
  import {
40
40
  APPROVAL_TIMEOUT_MS,
41
41
  safeReadTools,
@@ -866,7 +866,7 @@ async function runSubagent(parentSession, params, parentSignal, onUpdate) {
866
866
  includeMcpTools: false,
867
867
  },
868
868
  )
869
- toolsForClient = tools.map(({ execute, prepareArguments, ...tool }) => tool)
869
+ toolsForClient = tools.map(({ execute: _execute, prepareArguments: _prepareArguments, ...tool }) => tool)
870
870
 
871
871
  const emitSubagentTrace = () => {
872
872
  if (traceTimer) {
@@ -1821,7 +1821,7 @@ export async function abortRun(sessionId) {
1821
1821
  }
1822
1822
 
1823
1823
  // Clean up any pending tool approvals for this session
1824
- for (const [toolCallId, approval] of pendingApprovals) {
1824
+ for (const [_toolCallId, approval] of pendingApprovals) {
1825
1825
  if (approval.sessionId === sessionId) {
1826
1826
  approval.reject(new Error('Run aborted'))
1827
1827
  }
@@ -2014,10 +2014,10 @@ export async function destroyAgent(sessionId) {
2014
2014
  }
2015
2015
 
2016
2016
  // Clean up any pending approvals for this session before removing it.
2017
- for (const [toolCallId, approval] of pendingApprovals) {
2017
+ for (const [_toolCallId, approval] of pendingApprovals) {
2018
2018
  if (approval.sessionId === sessionId) approval.reject(new Error('Session destroyed'))
2019
2019
  }
2020
- for (const [approvalId, approval] of pendingAutoCompactApprovals) {
2020
+ for (const [_approvalId, approval] of pendingAutoCompactApprovals) {
2021
2021
  if (approval.sessionId === sessionId) approval.reject(new Error('Session destroyed'))
2022
2022
  }
2023
2023
 
@@ -2,6 +2,7 @@ import { existsSync, promises as fs } from 'node:fs'
2
2
  import os from 'node:os'
3
3
  import path from 'node:path'
4
4
  import { dataDir } from './storage.mjs'
5
+ import { logger } from './utils/logger.mjs'
5
6
  import { firstOptionalBoolean, firstString, parseFrontmatter, splitDelimitedList } from './frontmatter.mjs'
6
7
 
7
8
  const DEFAULT_MAX_RUNTIME_MS = 30 * 60 * 1000
@@ -123,7 +124,7 @@ async function listAgentFilesFromDirectory(dir, options = {}) {
123
124
  })
124
125
  if (profile) profiles.push(profile)
125
126
  } catch (error) {
126
- console.warn(`Failed to load agent profile ${file}:`, error.message || error)
127
+ logger.warn(`Failed to load agent profile ${file}:`, error.message || error)
127
128
  }
128
129
  }
129
130
  return profiles
@@ -1,3 +1,4 @@
1
+ /* eslint-disable no-control-regex -- ANSI escape matching intentionally includes ESC. */
1
2
  import { spawn } from 'node:child_process'
2
3
  import { EventEmitter } from 'node:events'
3
4
  import { setTimeout as delay } from 'node:timers/promises'
@@ -1,3 +1,4 @@
1
+ /* eslint-disable no-control-regex -- URL extraction intentionally treats ESC as a delimiter. */
1
2
  import { spawn } from 'node:child_process'
2
3
  import { promises as fs } from 'node:fs'
3
4
  import path from 'node:path'
@@ -2,6 +2,7 @@ import { promises as fs } from 'node:fs'
2
2
  import path from 'node:path'
3
3
  import { getEnabledPluginCommandSources } from './plugins/registry.mjs'
4
4
  import { userCommandsDir } from './storage.mjs'
5
+ import { logger } from './utils/logger.mjs'
5
6
 
6
7
  const commandsRelativeDirs = ['.claude/commands', '.opencode/commands', '.ai/commands']
7
8
  const commandsRelativeDir = '.ai/commands'
@@ -239,7 +240,7 @@ async function listCommandsFromDirectory(dir, options = {}) {
239
240
  })
240
241
  if (command) commands.push(command)
241
242
  } catch (error) {
242
- console.warn(`Failed to load custom command ${file}:`, error.message || error)
243
+ logger.warn(`Failed to load custom command ${file}:`, error.message || error)
243
244
  }
244
245
  }
245
246
 
@@ -253,7 +254,7 @@ async function listCommandsFromFile(file, options = {}) {
253
254
  return command ? [command] : []
254
255
  } catch (error) {
255
256
  if (error?.code === 'ENOENT' || error?.code === 'ENOTDIR' || error?.code === 'EACCES' || error?.code === 'EPERM') return []
256
- console.warn(`Failed to load custom command ${file}:`, error.message || error)
257
+ logger.warn(`Failed to load custom command ${file}:`, error.message || error)
257
258
  return []
258
259
  }
259
260
  }
@@ -483,7 +484,7 @@ function formatBuiltinCommandRows() {
483
484
  const aliases = cmd.aliases?.length
484
485
  ? ` (alias: ${cmd.aliases.map((alias) => `/${alias}`).join(', ')})`
485
486
  : ''
486
- const perm = cmd.permissionNote ? ` \[${cmd.permissionNote}\]` : ''
487
+ const perm = cmd.permissionNote ? ` [${cmd.permissionNote}]` : ''
487
488
  return `- \`/${cmd.name}${hint}\`${aliases} — ${cmd.description}${perm}`
488
489
  })
489
490
  }
@@ -163,43 +163,43 @@ export function normalizeMcpServers(value) {
163
163
  }
164
164
 
165
165
  export async function readMcpServers() {
166
- const settings = await readStore('settings')
167
- return normalizeMcpServers(settings?.[MCP_CONFIG_KEY])
166
+ const mcp = await readStore('mcp')
167
+ return normalizeMcpServers(mcp?.[MCP_CONFIG_KEY])
168
168
  }
169
169
 
170
170
  export async function writeMcpServers(servers) {
171
171
  const normalized = normalizeMcpServers(servers)
172
- return atomicUpdate('settings', (settings) => {
173
- settings[MCP_CONFIG_KEY] = normalized.map((server) => ({ ...server, updatedAt: new Date().toISOString() }))
174
- return settings
175
- }).then((settings) => normalizeMcpServers(settings?.[MCP_CONFIG_KEY]))
172
+ return atomicUpdate('mcp', (mcp) => {
173
+ mcp[MCP_CONFIG_KEY] = normalized.map((server) => ({ ...server, updatedAt: new Date().toISOString() }))
174
+ return mcp
175
+ }).then((mcp) => normalizeMcpServers(mcp?.[MCP_CONFIG_KEY]))
176
176
  }
177
177
 
178
178
  export async function upsertMcpServer(server) {
179
179
  const normalized = normalizeMcpServerConfig(server)
180
- return atomicUpdate('settings', (settings) => {
181
- const servers = normalizeMcpServers(settings?.[MCP_CONFIG_KEY])
180
+ return atomicUpdate('mcp', (mcp) => {
181
+ const servers = normalizeMcpServers(mcp?.[MCP_CONFIG_KEY])
182
182
  const index = servers.findIndex((item) => item.name === normalized.name)
183
183
  const next = { ...normalized, updatedAt: new Date().toISOString() }
184
184
  if (index >= 0) servers[index] = next
185
185
  else servers.push(next)
186
- settings[MCP_CONFIG_KEY] = servers
187
- return settings
188
- }).then((settings) => normalizeMcpServers(settings?.[MCP_CONFIG_KEY]))
186
+ mcp[MCP_CONFIG_KEY] = servers
187
+ return mcp
188
+ }).then((mcp) => normalizeMcpServers(mcp?.[MCP_CONFIG_KEY]))
189
189
  }
190
190
 
191
191
  export async function deleteMcpServer(name) {
192
192
  const normalizedName = normalizeName(name)
193
- return atomicUpdate('settings', (settings) => {
194
- settings[MCP_CONFIG_KEY] = normalizeMcpServers(settings?.[MCP_CONFIG_KEY]).filter((server) => server.name !== normalizedName)
195
- return settings
196
- }).then((settings) => normalizeMcpServers(settings?.[MCP_CONFIG_KEY]))
193
+ return atomicUpdate('mcp', (mcp) => {
194
+ mcp[MCP_CONFIG_KEY] = normalizeMcpServers(mcp?.[MCP_CONFIG_KEY]).filter((server) => server.name !== normalizedName)
195
+ return mcp
196
+ }).then((mcp) => normalizeMcpServers(mcp?.[MCP_CONFIG_KEY]))
197
197
  }
198
198
 
199
199
  export async function setMcpServerEnabled(name, enabled) {
200
200
  const normalizedName = normalizeName(name)
201
- return atomicUpdate('settings', (settings) => {
202
- const servers = normalizeMcpServers(settings?.[MCP_CONFIG_KEY])
201
+ return atomicUpdate('mcp', (mcp) => {
202
+ const servers = normalizeMcpServers(mcp?.[MCP_CONFIG_KEY])
203
203
  const index = servers.findIndex((server) => server.name === normalizedName)
204
204
  if (index < 0) {
205
205
  const error = new Error(`MCP server not found: ${normalizedName}`)
@@ -211,7 +211,7 @@ export async function setMcpServerEnabled(name, enabled) {
211
211
  enabled: Boolean(enabled),
212
212
  updatedAt: new Date().toISOString(),
213
213
  }
214
- settings[MCP_CONFIG_KEY] = servers
215
- return settings
216
- }).then((settings) => normalizeMcpServers(settings?.[MCP_CONFIG_KEY]))
214
+ mcp[MCP_CONFIG_KEY] = servers
215
+ return mcp
216
+ }).then((mcp) => normalizeMcpServers(mcp?.[MCP_CONFIG_KEY]))
217
217
  }
@@ -43,7 +43,7 @@ async function readJsonFile(filePath) {
43
43
  }
44
44
 
45
45
  async function listPluginDirs(root) {
46
- let entries = []
46
+ let entries
47
47
  try {
48
48
  entries = await fs.readdir(root, { withFileTypes: true })
49
49
  } catch (error) {
@@ -4,7 +4,7 @@ import { randomUUID } from 'node:crypto'
4
4
  import { spawnSync } from 'node:child_process'
5
5
  import { existsSync, promises as fs } from 'node:fs'
6
6
  import { ensureProjectCache, readProjectConfigData, atomicProjectConfigUpdate, dataDir, readStore, atomicUpdate } from './storage.mjs'
7
- import { setWorkspaceRoot, getWorkspaceRoot, assertDirectory } from './utils/workspace.mjs'
7
+ import { setWorkspaceRoot, assertDirectory } from './utils/workspace.mjs'
8
8
  import { loadSelectedGlobalSkills, loadSelectedProjectSkills, mergeSkills } from './skills.mjs'
9
9
 
10
10
  let defaultWorkspaceRoot = ''
@@ -101,7 +101,7 @@ function terminalShellProfileCandidatesForPlatform(platform = os.platform()) {
101
101
  const profiles = TERMINAL_SHELL_PROFILE_CANDIDATES
102
102
  .filter((profile) => profile.platforms.includes(platform))
103
103
  .filter((profile) => commandExists(profile.command))
104
- .map(({ platforms, ...profile }) => ({ ...profile, builtin: true, detected: true }))
104
+ .map(({ platforms: _platforms, ...profile }) => ({ ...profile, builtin: true, detected: true }))
105
105
 
106
106
  return profiles
107
107
  }
@@ -15,7 +15,6 @@ import {
15
15
  restoreAgent,
16
16
  touchSession,
17
17
  listSessions,
18
- refreshAllSessionTools,
19
18
  updateSessionAccessMode,
20
19
  updateSessionYoloMode,
21
20
  updateSessionModel,
@@ -16,7 +16,13 @@ import { getWorkspaceRoot } from '../utils/workspace.mjs'
16
16
  const BACKUP_VERSION = 1
17
17
  const BACKUP_APP = 'quickforge'
18
18
  const backupScopes = new Set(['all', 'config', 'sessions'])
19
- const restoreSectionIds = new Set(['settings', 'providerKeys', 'customProviders', 'projects', 'scheduledTasks', 'conversations'])
19
+ const restoreSectionIds = new Set(['settings', 'mcp', 'providerKeys', 'customProviders', 'projects', 'scheduledTasks', 'conversations'])
20
+ const restoreModes = new Set(['replace', 'merge'])
21
+
22
+ function normalizeMode(value) {
23
+ const mode = String(value || 'replace')
24
+ return restoreModes.has(mode) ? mode : 'replace'
25
+ }
20
26
 
21
27
  function normalizeScope(value) {
22
28
  const scope = String(value || 'all')
@@ -109,8 +115,9 @@ async function buildBackup(scope = 'all', options = {}) {
109
115
  const data = {}
110
116
 
111
117
  if (includeConfig) {
112
- const [settings, providerKeys, customProviders, projects, scheduledTasks] = await Promise.all([
118
+ const [settings, mcp, providerKeys, customProviders, projects, scheduledTasks] = await Promise.all([
113
119
  readStore('settings'),
120
+ readStore('mcp'),
114
121
  includeSecrets ? readStore('provider-keys') : Promise.resolve(undefined),
115
122
  readStore('custom-providers'),
116
123
  readProjectConfigData(),
@@ -118,6 +125,7 @@ async function buildBackup(scope = 'all', options = {}) {
118
125
  ])
119
126
  Object.assign(data, {
120
127
  settings,
128
+ mcp,
121
129
  customProviders,
122
130
  projects,
123
131
  scheduledTasks,
@@ -160,6 +168,7 @@ function normalizeBackupPayload(payload) {
160
168
 
161
169
  const sections = {
162
170
  settings: section(data, 'settings'),
171
+ mcp: section(data, 'mcp'),
163
172
  providerKeys: section(data, 'providerKeys', 'provider-keys'),
164
173
  customProviders: section(data, 'customProviders', 'custom-providers'),
165
174
  projects: section(data, 'projects'),
@@ -168,6 +177,17 @@ function normalizeBackupPayload(payload) {
168
177
  sessionsMetadata: section(data, 'sessionsMetadata', 'sessions-metadata'),
169
178
  }
170
179
 
180
+ // Backward compat: older backups stored MCP servers inside settings.mcpServers.
181
+ if (
182
+ sections.mcp === undefined &&
183
+ sections.settings && typeof sections.settings === 'object' && !Array.isArray(sections.settings) &&
184
+ Object.prototype.hasOwnProperty.call(sections.settings, 'mcpServers')
185
+ ) {
186
+ const { mcpServers, ...restSettings } = sections.settings
187
+ sections.settings = restSettings
188
+ sections.mcp = { mcpServers: Array.isArray(mcpServers) ? mcpServers : [] }
189
+ }
190
+
171
191
  if (Object.values(sections).every((value) => value === undefined)) {
172
192
  const error = new Error('Backup does not contain any restorable sections')
173
193
  error.statusCode = 400
@@ -197,6 +217,7 @@ function validateBackupPayload(payload) {
197
217
  ...backup,
198
218
  sections: {
199
219
  settings: assertObjectSection(sections.settings, 'settings'),
220
+ mcp: assertObjectSection(sections.mcp, 'mcp'),
200
221
  providerKeys: assertObjectSection(sections.providerKeys, 'providerKeys'),
201
222
  customProviders: assertObjectSection(sections.customProviders, 'customProviders'),
202
223
  projects: assertProjectConfig(sections.projects),
@@ -249,6 +270,7 @@ function filterRestoreSections(sections, selected) {
249
270
  if (!selected) return sections
250
271
  return {
251
272
  settings: selected.has('settings') ? sections.settings : undefined,
273
+ mcp: selected.has('mcp') ? sections.mcp : undefined,
252
274
  providerKeys: selected.has('providerKeys') ? sections.providerKeys : undefined,
253
275
  customProviders: selected.has('customProviders') ? sections.customProviders : undefined,
254
276
  projects: selected.has('projects') ? sections.projects : undefined,
@@ -267,7 +289,8 @@ function parseImportPayload(body) {
267
289
  const backup = validateBackupPayload(payload)
268
290
  const requestedSections = body?.backup && typeof body === 'object' ? body.sections : undefined
269
291
  const selected = normalizeRestoreSections(requestedSections, backup.sections)
270
- return backupWithSelectedSections(backup, selected)
292
+ const mode = normalizeMode(body?.mode)
293
+ return { backup: backupWithSelectedSections(backup, selected), mode }
271
294
  }
272
295
 
273
296
  function countKeys(value) {
@@ -277,6 +300,7 @@ function countKeys(value) {
277
300
  function buildSummary(sections) {
278
301
  const summary = {}
279
302
  if (sections.settings !== undefined) summary.settings = countKeys(sections.settings)
303
+ if (sections.mcp !== undefined) summary.mcp = Array.isArray(sections.mcp?.mcpServers) ? sections.mcp.mcpServers.length : countKeys(sections.mcp)
280
304
  if (sections.providerKeys !== undefined) summary.providerKeys = countKeys(sections.providerKeys)
281
305
  if (sections.customProviders !== undefined) summary.customProviders = countKeys(sections.customProviders)
282
306
  if (sections.projects !== undefined) summary.projects = sections.projects.projects.length
@@ -318,46 +342,86 @@ async function writeSafetyBackup() {
318
342
  return file
319
343
  }
320
344
 
321
- async function restoreValidatedBackup(backup) {
345
+ // Merge two plain-object stores: backup entries override local on key collision,
346
+ // local-only keys are preserved.
347
+ function mergeRecordStore(localValue, backupValue) {
348
+ return { ...(localValue && typeof localValue === 'object' ? localValue : {}), ...backupValue }
349
+ }
350
+
351
+ // Merge projects config: dedupe the projects array by id (backup wins on
352
+ // collision, local-only entries preserved), take activeProjectId / globalSkills
353
+ // from backup.
354
+ function mergeProjectConfig(localConfig, backupConfig) {
355
+ const localProjects = Array.isArray(localConfig?.projects) ? localConfig.projects : []
356
+ const backupProjects = Array.isArray(backupConfig.projects) ? backupConfig.projects : []
357
+ const merged = new Map()
358
+ for (const project of localProjects) {
359
+ if (project && typeof project.id === 'string') merged.set(project.id, project)
360
+ }
361
+ for (const project of backupProjects) {
362
+ if (project && typeof project.id === 'string') merged.set(project.id, project)
363
+ }
364
+ return {
365
+ activeProjectId: typeof backupConfig.activeProjectId === 'string' ? backupConfig.activeProjectId : (localConfig?.activeProjectId ?? null),
366
+ globalSkills: Array.isArray(backupConfig.globalSkills) ? backupConfig.globalSkills : (Array.isArray(localConfig?.globalSkills) ? localConfig.globalSkills : []),
367
+ projects: [...merged.values()],
368
+ }
369
+ }
370
+
371
+ async function restoreValidatedBackup(backup, mode = 'replace') {
372
+ const merge = mode === 'merge'
322
373
  const { sections } = backup
323
374
  const summary = {}
324
375
 
325
376
  if (sections.settings !== undefined) {
326
- await writeStore('settings', sections.settings)
327
- summary.settings = countKeys(sections.settings)
377
+ const value = merge ? mergeRecordStore(await readStore('settings'), sections.settings) : sections.settings
378
+ await writeStore('settings', value)
379
+ summary.settings = countKeys(value)
380
+ }
381
+
382
+ if (sections.mcp !== undefined) {
383
+ const value = merge ? mergeRecordStore(await readStore('mcp'), sections.mcp) : sections.mcp
384
+ await writeStore('mcp', value)
385
+ summary.mcp = Array.isArray(value?.mcpServers) ? value.mcpServers.length : countKeys(value)
328
386
  }
329
387
 
330
388
  if (sections.providerKeys !== undefined) {
331
- await writeStore('provider-keys', sections.providerKeys)
332
- summary.providerKeys = countKeys(sections.providerKeys)
389
+ const value = merge ? mergeRecordStore(await readStore('provider-keys'), sections.providerKeys) : sections.providerKeys
390
+ await writeStore('provider-keys', value)
391
+ summary.providerKeys = countKeys(value)
333
392
  }
334
393
 
335
394
  if (sections.customProviders !== undefined) {
336
- await writeStore('custom-providers', sections.customProviders)
337
- summary.customProviders = countKeys(sections.customProviders)
395
+ const value = merge ? mergeRecordStore(await readStore('custom-providers'), sections.customProviders) : sections.customProviders
396
+ await writeStore('custom-providers', value)
397
+ summary.customProviders = countKeys(value)
338
398
  }
339
399
 
340
400
  if (sections.projects !== undefined) {
341
- await writeProjectConfigData(sections.projects)
401
+ const value = merge ? mergeProjectConfig(await readProjectConfigData(), sections.projects) : sections.projects
402
+ await writeProjectConfigData(value)
342
403
  await initializeActiveProject()
343
404
  setActiveWorkspaceRootForFilesystem(getWorkspaceRoot())
344
- summary.projects = sections.projects.projects.length
405
+ summary.projects = value.projects.length
345
406
  }
346
407
 
347
408
  if (sections.scheduledTasks !== undefined) {
348
- await writeStore('scheduled-tasks', sections.scheduledTasks)
349
- summary.scheduledTasks = countKeys(sections.scheduledTasks)
409
+ const value = merge ? mergeRecordStore(await readStore('scheduled-tasks'), sections.scheduledTasks) : sections.scheduledTasks
410
+ await writeStore('scheduled-tasks', value)
411
+ summary.scheduledTasks = countKeys(value)
350
412
  }
351
413
 
352
414
  if (sections.sessions !== undefined) {
353
415
  const sessions = filterSessionsByMetadata(sections.sessions, sections.sessionsMetadata)
354
- await writeStore('sessions', sessions)
355
- summary.sessions = countKeys(sessions)
416
+ const value = merge ? mergeRecordStore(await readStore('sessions'), sessions) : sessions
417
+ await writeStore('sessions', value)
418
+ summary.sessions = countKeys(value)
356
419
  }
357
420
 
358
421
  if (sections.sessionsMetadata !== undefined) {
359
- await writeStore('sessions-metadata', sections.sessionsMetadata)
360
- summary.sessionsMetadata = countKeys(sections.sessionsMetadata)
422
+ const value = merge ? mergeRecordStore(await readStore('sessions-metadata'), sections.sessionsMetadata) : sections.sessionsMetadata
423
+ await writeStore('sessions-metadata', value)
424
+ summary.sessionsMetadata = countKeys(value)
361
425
  }
362
426
 
363
427
  return summary
@@ -382,9 +446,9 @@ export async function handleBackupApi(req, res, url) {
382
446
  if (req.method === 'POST' && url.pathname === '/api/backup/import') {
383
447
  await ensureStorage()
384
448
  const body = await readJsonBody(req)
385
- const backup = parseImportPayload(body)
449
+ const { backup, mode } = parseImportPayload(body)
386
450
  const safetyBackupPath = await writeSafetyBackup()
387
- const summary = await restoreValidatedBackup(backup)
451
+ const summary = await restoreValidatedBackup(backup, mode)
388
452
  sendJson(res, 200, { ok: true, safetyBackupPath, summary })
389
453
  return
390
454
  }
@@ -1,4 +1,5 @@
1
1
  import { sendJson, readJsonBody, decodeSegment } from '../utils/response.mjs'
2
+ import { logger } from '../utils/logger.mjs'
2
3
  import { getActiveProject, setActiveProjectPath, readProjectConfig, getDefaultWorkspaceRoot } from '../project-config.mjs'
3
4
  import { listProjectCommands, createCommandFile } from '../custom-commands.mjs'
4
5
  import { atomicProjectConfigUpdate } from '../storage.mjs'
@@ -38,9 +39,9 @@ export async function handleProjectApi(req, res, url) {
38
39
  }
39
40
 
40
41
  if (req.method === 'POST' && url.pathname === '/api/project/select-directory') {
41
- console.log('[project] Opening directory picker dialog...')
42
+ logger.info('[project] Opening directory picker dialog...')
42
43
  const selectedPath = await selectDirectoryDialog()
43
- console.log('[project] Directory picker result:', selectedPath ? `"${selectedPath}"` : '(cancelled/empty)')
44
+ logger.info('[project] Directory picker result', { selectedPath: selectedPath || null })
44
45
  if (!selectedPath) {
45
46
  sendJson(res, 200, { cancelled: true, project: getActiveProject(config), projects: config.projects })
46
47
  return