@shawnstack/quickforge 1.3.24 → 1.3.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -14
- package/dist/assets/anthropic-B1_Yrokl.js +39 -0
- package/dist/assets/azure-openai-responses-UMiOBCBd.js +1 -0
- package/dist/assets/google-BLE_Gcd1.js +1 -0
- package/dist/assets/google-shared-Cqjw1plk.js +11 -0
- package/dist/assets/google-vertex-6_sIZLVc.js +1 -0
- package/dist/assets/{icons-DmRYmmql.js → icons-Bs7OG8yi.js} +1 -1
- package/dist/assets/{index-s72bxhrh.js → index-C3bc5C3k.js} +550 -544
- package/dist/assets/index-C7oT9Rdw.css +3 -0
- package/dist/assets/{mistral-DCZ8VphX.js → mistral-DmZEmRkv.js} +1 -1
- package/dist/assets/openai-codex-responses-i_SmQGzQ.js +7 -0
- package/dist/assets/openai-completions-BmmZFDDY.js +5 -0
- package/dist/assets/openai-prompt-cache-CErE62Yt.js +1 -0
- package/dist/assets/openai-responses-C8tPdeE9.js +1 -0
- package/dist/assets/{openai-responses-shared-RzgnIlMf.js → openai-responses-shared-DchtjQNp.js} +1 -1
- package/dist/assets/openrouter-CcTv1G_v.js +1 -0
- package/dist/assets/{react-vendor-BsV2HYbc.js → react-vendor-Cu-7p9CI.js} +1 -1
- package/dist/assets/sanitize-unicode-BhyPmlyt.js +1 -0
- package/dist/assets/transform-messages-Dhj_4OTw.js +1 -0
- package/dist/index.html +4 -4
- package/package.json +3 -3
- package/server/agent-manager.mjs +66 -160
- package/server/ai-http-logger.mjs +20 -5
- package/server/approval-store.mjs +63 -0
- package/server/message-converters.mjs +79 -0
- package/server/routes/agent-profiles.mjs +1 -1
- package/server/routes/filesystem.mjs +18 -2
- package/server/routes/scheduled-tasks.mjs +1 -1
- package/server/routes/storage.mjs +66 -31
- package/server/session-utils.mjs +1 -1
- package/server/storage.mjs +78 -2
- package/server/tool-wiring.mjs +87 -0
- package/server/utils/workspace.mjs +20 -1
- package/dist/assets/anthropic-BrbLtQkg.js +0 -39
- package/dist/assets/azure-openai-responses-q9QFpQk3.js +0 -1
- package/dist/assets/google-Bv6IeSRf.js +0 -1
- package/dist/assets/google-shared-CLc4ziON.js +0 -11
- package/dist/assets/google-vertex-Cwpe8vbn.js +0 -1
- package/dist/assets/index-C4m48ndP.css +0 -3
- package/dist/assets/openai-codex-responses-Bx7iyHzd.js +0 -7
- package/dist/assets/openai-completions-CihVV11E.js +0 -5
- package/dist/assets/openai-responses-BigEdUNS.js +0 -1
- package/dist/assets/transform-messages-CmnxG9RB.js +0 -1
- /package/dist/assets/{hash-Bt1aVMQ3.js → hash-kZ2KD_no.js} +0 -0
- /package/dist/assets/{openai-Cn7eGqwa.js → openai-Bf1npfRy.js} +0 -0
package/dist/assets/{openai-responses-shared-RzgnIlMf.js → openai-responses-shared-DchtjQNp.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{l as e,r as t}from"./index-
|
|
1
|
+
import{l as e,r as t}from"./index-C3bc5C3k.js";import{t as n}from"./sanitize-unicode-BhyPmlyt.js";import{t as r}from"./transform-messages-Dhj_4OTw.js";import{t as i}from"./hash-kZ2KD_no.js";function a(e,t){let n={v:1,id:e};return t&&(n.phase=t),JSON.stringify(n)}function o(e){if(e){if(e.startsWith(`{`))try{let t=JSON.parse(e);if(t.v===1&&typeof t.id==`string`)return t.phase===`commentary`||t.phase===`final_answer`?{id:t.id,phase:t.phase}:{id:t.id}}catch{}return{id:e}}}function s(e,t,a,s){let c=[],l=e=>{let t=e.replace(/[^a-zA-Z0-9_-]/g,`_`);return(t.length>64?t.slice(0,64):t).replace(/_+$/,``)},u=e=>{let t=`fc_${i(e)}`;return t.length>64?t.slice(0,64):t},d=r(t.messages,e,(t,n,r)=>{if(!a.has(e.provider)||!t.includes(`|`))return l(t);let[i,o]=t.split(`|`),s=l(i),c=r.provider!==e.provider||r.api!==e.api?u(o):l(o);return c.startsWith(`fc_`)||(c=l(`fc_${c}`)),`${s}|${c}`});if((s?.includeSystemPrompt??!0)&&t.systemPrompt){let r=e.reasoning?`developer`:`system`;c.push({role:r,content:n(t.systemPrompt)})}let f=0;for(let t of d){if(t.role===`user`)if(typeof t.content==`string`)c.push({role:`user`,content:[{type:`input_text`,text:n(t.content)}]});else{let e=t.content.map(e=>e.type===`text`?{type:`input_text`,text:n(e.text)}:{type:`input_image`,detail:`auto`,image_url:`data:${e.mimeType};base64,${e.data}`});if(e.length===0)continue;c.push({role:`user`,content:e})}else if(t.role===`assistant`){let r=[],a=t,s=a.model!==e.id&&a.provider===e.provider&&a.api===e.api;for(let e of t.content)if(e.type===`thinking`){if(e.thinkingSignature){let t=JSON.parse(e.thinkingSignature);r.push(t)}}else if(e.type===`text`){let t=e,a=o(t.textSignature),s=a?.id;s?s.length>64&&(s=`msg_${i(s)}`):s=`msg_${f}`,r.push({type:`message`,role:`assistant`,content:[{type:`output_text`,text:n(t.text),annotations:[]}],status:`completed`,id:s,phase:a?.phase})}else if(e.type===`toolCall`){let t=e,[n,i]=t.id.split(`|`),a=i;s&&a?.startsWith(`fc_`)&&(a=void 0),r.push({type:`function_call`,id:a,call_id:n,name:t.name,arguments:JSON.stringify(t.arguments)})}if(r.length===0)continue;c.push(...r)}else if(t.role===`toolResult`){let r=t.content.filter(e=>e.type===`text`).map(e=>e.text).join(`
|
|
2
2
|
`),i=t.content.some(e=>e.type===`image`),a=r.length>0,[o]=t.toolCallId.split(`|`),s;if(i&&e.input.includes(`image`)){let e=[];a&&e.push({type:`input_text`,text:n(r)});for(let n of t.content)n.type===`image`&&e.push({type:`input_image`,detail:`auto`,image_url:`data:${n.mimeType};base64,${n.data}`});s=e}else s=n(a?r:`(see attached image)`);c.push({type:`function_call_output`,call_id:o,output:s})}f++}return c}function c(e,t){let n=t?.strict===void 0?!1:t.strict;return e.map(e=>({type:`function`,name:e.name,description:e.description,parameters:e.parameters,strict:n}))}async function l(n,r,i,o,s){let c=null,l=null,d=r.content,f=()=>d.length-1;for await(let d of n)if(d.type===`response.created`)r.responseId=d.response.id;else if(d.type===`response.output_item.added`){let e=d.item;e.type===`reasoning`?(c=e,l={type:`thinking`,thinking:``},r.content.push(l),i.push({type:`thinking_start`,contentIndex:f(),partial:r})):e.type===`message`?(c=e,l={type:`text`,text:``},r.content.push(l),i.push({type:`text_start`,contentIndex:f(),partial:r})):e.type===`function_call`&&(c=e,l={type:`toolCall`,id:`${e.call_id}|${e.id}`,name:e.name,arguments:{},partialJson:e.arguments||``},r.content.push(l),i.push({type:`toolcall_start`,contentIndex:f(),partial:r}))}else if(d.type===`response.reasoning_summary_part.added`)c&&c.type===`reasoning`&&(c.summary=c.summary||[],c.summary.push(d.part));else if(d.type===`response.reasoning_summary_text.delta`){if(c?.type===`reasoning`&&l?.type===`thinking`){c.summary=c.summary||[];let e=c.summary[c.summary.length-1];e&&(l.thinking+=d.delta,e.text+=d.delta,i.push({type:`thinking_delta`,contentIndex:f(),delta:d.delta,partial:r}))}}else if(d.type===`response.reasoning_summary_part.done`){if(c?.type===`reasoning`&&l?.type===`thinking`){c.summary=c.summary||[];let e=c.summary[c.summary.length-1];e&&(l.thinking+=`
|
|
3
3
|
|
|
4
4
|
`,e.text+=`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{d as e}from"./index-C3bc5C3k.js";import{t}from"./headers-5EYI0_pl.js";import{t as n}from"./sanitize-unicode-BhyPmlyt.js";import{n as r}from"./openai-Bf1npfRy.js";var i=async(n,r,i)=>{let c={api:n.api,provider:n.provider,model:n.id,output:[],stopReason:`stop`,timestamp:Date.now()};try{let l=i?.apiKey||e(n.provider);if(!l)throw Error(`No API key available for provider: ${n.provider}`);let u=a(n,l,i?.headers),d=o(n,r),f=await i?.onPayload?.(d,n);f!==void 0&&(d=f);let p={...i?.signal?{signal:i.signal}:{},...i?.timeoutMs===void 0?{}:{timeout:i.timeoutMs},...i?.maxRetries===void 0?{}:{maxRetries:i.maxRetries}},{data:m,response:h}=await u.chat.completions.create(d,p).withResponse();await i?.onResponse?.({status:h.status,headers:t(h.headers)},n);let g=m;c.responseId=g.id,g.usage&&(c.usage=s(g.usage,n));let _=g.choices[0];if(_){let e=_.message.content;typeof e==`string`&&e.length>0&&c.output.push({type:`text`,text:e});for(let e of _.message.images??[]){let t=typeof e.image_url==`string`?e.image_url:e.image_url?.url;if(!t?.startsWith(`data:`))continue;let n=t.match(/^data:([^;]+);base64,(.+)$/);n&&c.output.push({type:`image`,mimeType:n[1],data:n[2]})}}return c}catch(e){return c.stopReason=i?.signal?.aborted?`aborted`:`error`,c.errorMessage=e instanceof Error?e.message:JSON.stringify(e),c}};function a(e,t,n){return new r({apiKey:t,baseURL:e.baseUrl,dangerouslyAllowBrowser:!0,defaultHeaders:{...e.headers,...n}})}function o(e,t){let r=t.input.map(e=>e.type===`text`?{type:`text`,text:n(e.text)}:{type:`image_url`,image_url:{url:`data:${e.mimeType};base64,${e.data}`}});return{model:e.id,messages:[{role:`user`,content:r}],stream:!1,modalities:e.output.includes(`text`)?[`image`,`text`]:[`image`]}}function s(e,t){let n=e.prompt_tokens||0,r=e.prompt_tokens_details?.cached_tokens||0,i=e.prompt_tokens_details?.cache_write_tokens||0,a=i>0?Math.max(0,r-i):r,o=Math.max(0,n-a-i),s=e.completion_tokens||0,c={input:o,output:s,cacheRead:a,cacheWrite:i,totalTokens:o+s+a+i,cost:{input:t.cost.input/1e6*o,output:t.cost.output/1e6*s,cacheRead:t.cost.cacheRead/1e6*a,cacheWrite:t.cost.cacheWrite/1e6*i,total:0}};return c.cost.total=c.cost.input+c.cost.output+c.cost.cacheRead+c.cost.cacheWrite,c}export{i as generateImagesOpenRouter};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{t as e}from"./rolldown-runtime-CkqCuyE9.js";import{Z as t}from"./icons-DmRYmmql.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-CkqCuyE9.js";import{nt as t}from"./icons-Bs7OG8yi.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(`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function e(e){return e.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g,``)}export{e as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function e(e,t,n){return{temperature:t?.temperature,maxTokens:t?.maxTokens,signal:t?.signal,apiKey:n||t?.apiKey,transport:t?.transport,cacheRetention:t?.cacheRetention,sessionId:t?.sessionId,headers:t?.headers,onPayload:t?.onPayload,onResponse:t?.onResponse,timeoutMs:t?.timeoutMs,maxRetries:t?.maxRetries,maxRetryDelayMs:t?.maxRetryDelayMs,metadata:t?.metadata}}function t(e){return e===`xhigh`?`high`:e}function n(e,n,r,i){let a={minimal:1024,low:2048,medium:8192,high:16384,...i}[t(r)],o=e===void 0?n:Math.min(e+a,n);return o<=a&&(a=Math.max(0,o-1024)),{maxTokens:o,thinkingBudget:a}}var r=`(image omitted: model does not support images)`,i=`(tool image omitted: model does not support images)`;function a(e,t){let n=[],r=!1;for(let i of e){if(i.type===`image`){r||n.push({type:`text`,text:t}),r=!0;continue}n.push(i),r=i.text===t}return n}function o(e,t){return t.input.includes(`image`)?e:e.map(e=>e.role===`user`&&Array.isArray(e.content)?{...e,content:a(e.content,r)}:e.role===`toolResult`?{...e,content:a(e.content,i)}:e)}function s(e,t,n){let r=new Map,i=o(e,t).map(e=>{if(e.role===`user`)return e;if(e.role===`toolResult`){let t=r.get(e.toolCallId);return t&&t!==e.toolCallId?{...e,toolCallId:t}:e}if(e.role===`assistant`){let i=e,a=i.provider===t.provider&&i.api===t.api&&i.model===t.id,o=i.content.flatMap(e=>{if(e.type===`thinking`)return e.redacted?a?e:[]:a&&e.thinkingSignature?e:!e.thinking||e.thinking.trim()===``?[]:a?e:{type:`text`,text:e.thinking};if(e.type===`text`)return a?e:{type:`text`,text:e.text};if(e.type===`toolCall`){let o=e,s=o;if(!a&&o.thoughtSignature&&(s={...o},delete s.thoughtSignature),!a&&n){let e=n(o.id,t,i);e!==o.id&&(r.set(o.id,e),s={...s,id:e})}return s}return e});return{...i,content:o}}return e}),a=[],s=[],c=new Set,l=()=>{if(s.length>0){for(let e of s)c.has(e.id)||a.push({role:`toolResult`,toolCallId:e.id,toolName:e.name,content:[{type:`text`,text:`No result provided`}],isError:!0,timestamp:Date.now()});s=[],c=new Set}};for(let e=0;e<i.length;e++){let t=i[e];if(t.role===`assistant`){l();let e=t;if(e.stopReason===`error`||e.stopReason===`aborted`)continue;let n=e.content.filter(e=>e.type===`toolCall`);n.length>0&&(s=n,c=new Set),a.push(t)}else t.role===`toolResult`?(c.add(t.toolCallId),a.push(t)):(t.role===`user`&&l(),a.push(t))}return l(),a}export{n,e as r,s as t};
|
package/dist/index.html
CHANGED
|
@@ -11,13 +11,13 @@
|
|
|
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-
|
|
14
|
+
<script type="module" crossorigin src="/assets/index-C3bc5C3k.js"></script>
|
|
15
15
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-CkqCuyE9.js">
|
|
16
16
|
<link rel="modulepreload" crossorigin href="/assets/lit-vendor-Dr3cpBGF.js">
|
|
17
17
|
<link rel="modulepreload" crossorigin href="/assets/css-utils-rkE68RDy.js">
|
|
18
|
-
<link rel="modulepreload" crossorigin href="/assets/icons-
|
|
19
|
-
<link rel="modulepreload" crossorigin href="/assets/react-vendor-
|
|
20
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
18
|
+
<link rel="modulepreload" crossorigin href="/assets/icons-Bs7OG8yi.js">
|
|
19
|
+
<link rel="modulepreload" crossorigin href="/assets/react-vendor-Cu-7p9CI.js">
|
|
20
|
+
<link rel="stylesheet" crossorigin href="/assets/index-C7oT9Rdw.css">
|
|
21
21
|
</head>
|
|
22
22
|
<body>
|
|
23
23
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shawnstack/quickforge",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.25",
|
|
4
4
|
"description": "AI chat application with YOLO-mode local workspace tools. React + Vite + Tailwind CSS frontend, local Node.js storage server.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"@dnd-kit/core": "^6.3.1",
|
|
46
46
|
"@dnd-kit/sortable": "^10.0.0",
|
|
47
47
|
"@dnd-kit/utilities": "^3.2.2",
|
|
48
|
-
"@
|
|
49
|
-
"@
|
|
48
|
+
"@earendil-works/pi-agent-core": "^0.75.3",
|
|
49
|
+
"@earendil-works/pi-ai": "^0.75.3",
|
|
50
50
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
51
51
|
"ws": "^8.20.1"
|
|
52
52
|
},
|
package/server/agent-manager.mjs
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events'
|
|
2
2
|
import { randomUUID } from 'node:crypto'
|
|
3
|
-
import { Agent } from '@
|
|
3
|
+
import { Agent } from '@earendil-works/pi-agent-core'
|
|
4
4
|
import { streamSimpleWithAiHttpLogging } from './ai-http-logger.mjs'
|
|
5
|
-
import {
|
|
5
|
+
import { loadSkillToolContext, abortRunningCommand } from './tools/index.mjs'
|
|
6
6
|
import { createSkillTools, workspaceTools } from './tools/definitions.mjs'
|
|
7
|
-
import {
|
|
7
|
+
import { createMcpToolDefinitions, isMcpToolName } from './mcp/registry.mjs'
|
|
8
8
|
import {
|
|
9
9
|
composeSubagentSystemPrompt,
|
|
10
10
|
formatSubagentTask,
|
|
11
11
|
} from './subagents.mjs'
|
|
12
12
|
import { agentProfileSnapshot, getAgentProfile } from './agent-profiles.mjs'
|
|
13
13
|
import { projectContextFromId, readProjectConfig } from './project-config.mjs'
|
|
14
|
-
import { readStore, atomicUpdate, readSessionValue, writeSessionValue, deleteSessionValue } from './storage.mjs'
|
|
14
|
+
import { readStore, atomicUpdate, atomicSessionMetadataUpdate, readSessionValue, writeSessionValue, deleteSessionValue } from './storage.mjs'
|
|
15
15
|
import { logger } from './utils/logger.mjs'
|
|
16
16
|
import { buildSystemPrompt, generateAiTitle, generateTitle } from './session-utils.mjs'
|
|
17
17
|
import { restoreReasoningContentInPayload } from './reasoning-cache.mjs'
|
|
@@ -30,70 +30,22 @@ import {
|
|
|
30
30
|
parseInternalCommandInvocation,
|
|
31
31
|
resolveCustomCommandInvocation,
|
|
32
32
|
} from './custom-commands.mjs'
|
|
33
|
+
import { omitDetailsForLlm, serverConvertToLlm, messageText, lastAssistantText } from './message-converters.mjs'
|
|
34
|
+
import { isPlainObject, mergeQuickForgeTiming, wrapToolDefinition, wrapMcpToolDefinition, sessionSkillsContext } from './tool-wiring.mjs'
|
|
35
|
+
import {
|
|
36
|
+
APPROVAL_TIMEOUT_MS,
|
|
37
|
+
commandRestrictedTools,
|
|
38
|
+
safeReadTools,
|
|
39
|
+
pendingApprovals,
|
|
40
|
+
pendingAutoCompactApprovals,
|
|
41
|
+
commandToolPermissionError,
|
|
42
|
+
createCommandToolPermissions,
|
|
43
|
+
} from './approval-store.mjs'
|
|
33
44
|
|
|
34
45
|
// ---------------------------------------------------------------------------
|
|
35
46
|
// Tool definitions (server-side, no REST roundtrip)
|
|
36
47
|
// ---------------------------------------------------------------------------
|
|
37
48
|
|
|
38
|
-
function isPlainObject(value) {
|
|
39
|
-
return Boolean(value && typeof value === 'object' && !Array.isArray(value))
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function mergeQuickForgeTiming(details, timing) {
|
|
43
|
-
if (!isPlainObject(details)) return { quickforgeTiming: timing }
|
|
44
|
-
return { ...details, quickforgeTiming: timing }
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function wrapToolDefinition(definition, context, toolPermissions) {
|
|
48
|
-
const handler = toolHandlers[definition.name]
|
|
49
|
-
if (!handler) throw new Error(`Missing handler for tool: ${definition.name}`)
|
|
50
|
-
return {
|
|
51
|
-
...definition,
|
|
52
|
-
execute: async (_toolCallId, params, signal, onUpdate) => {
|
|
53
|
-
if (toolPermissions) {
|
|
54
|
-
const permissionError = toolPermissions(definition.name)
|
|
55
|
-
if (permissionError) throw new Error(permissionError)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const startedAt = Date.now()
|
|
59
|
-
const startedAtPerf = performance.now()
|
|
60
|
-
const result = await handler(params || {}, context, { signal, onUpdate, toolCallId: _toolCallId })
|
|
61
|
-
const finishedAt = Date.now()
|
|
62
|
-
const durationMs = Math.max(0, Math.round(performance.now() - startedAtPerf))
|
|
63
|
-
const details = mergeQuickForgeTiming(result.details, { startedAt, finishedAt, durationMs })
|
|
64
|
-
return {
|
|
65
|
-
content: [{ type: 'text', text: result.content }],
|
|
66
|
-
details: isPlainObject(details) ? { ...details, toolCallId: _toolCallId } : details,
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function wrapMcpToolDefinition(definition, toolPermissions) {
|
|
73
|
-
return {
|
|
74
|
-
...definition,
|
|
75
|
-
execute: async (_toolCallId, params) => {
|
|
76
|
-
if (toolPermissions) {
|
|
77
|
-
const permissionError = toolPermissions(definition.name)
|
|
78
|
-
if (permissionError) throw new Error(permissionError)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const startedAt = Date.now()
|
|
82
|
-
const startedAtPerf = performance.now()
|
|
83
|
-
const result = await callMcpTool(definition.name, params || {})
|
|
84
|
-
const finishedAt = Date.now()
|
|
85
|
-
const durationMs = Math.max(0, Math.round(performance.now() - startedAtPerf))
|
|
86
|
-
if (result.isError) {
|
|
87
|
-
throw new Error(result.content || `MCP tool failed: ${definition.name}`)
|
|
88
|
-
}
|
|
89
|
-
return {
|
|
90
|
-
content: [{ type: 'text', text: result.content }],
|
|
91
|
-
details: mergeQuickForgeTiming(result.details, { startedAt, finishedAt, durationMs }),
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
49
|
function wrapSubagentToolDefinition(definition, parentSessionId) {
|
|
98
50
|
return {
|
|
99
51
|
...definition,
|
|
@@ -154,13 +106,6 @@ async function createServerTools(projectId, projectContext, skillsContext, inclu
|
|
|
154
106
|
return tools
|
|
155
107
|
}
|
|
156
108
|
|
|
157
|
-
function sessionSkillsContext(session) {
|
|
158
|
-
return {
|
|
159
|
-
globalSkillNames: session.globalSkillNames,
|
|
160
|
-
projectSkillNames: session.projectSkillNames,
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
109
|
async function rebuildSessionTools(session) {
|
|
165
110
|
session.agent.state.tools = await createServerTools(
|
|
166
111
|
session.projectId,
|
|
@@ -181,31 +126,8 @@ const agentSessions = new Map()
|
|
|
181
126
|
/** @typedef {{ agent: Agent, projectContext: object|null, projectId: string|null, yoloMode: boolean, model: object, thinkingLevel: string, scope: string, title: string, createdAt: string, status: string, startedAt: string|null, finishedAt: string|null, listeners: Set<function>, idleTimer: NodeJS.Timeout|null, eventBus: EventEmitter }} AgentSession */
|
|
182
127
|
|
|
183
128
|
const IDLE_TIMEOUT_MS = 30 * 60 * 1000 // 30 minutes
|
|
184
|
-
const APPROVAL_TIMEOUT_MS = 5 * 60 * 1000 // 5 minutes for tool approval
|
|
185
129
|
const SUBAGENT_DEFAULT_TIMEOUT_MS = 30 * 60 * 1000
|
|
186
|
-
const
|
|
187
|
-
const safeReadTools = new Set(['read_file', 'grep_files'])
|
|
188
|
-
const pendingApprovals = new Map() // toolCallId → { resolve, reject, sessionId, toolName, args, source, timeout }
|
|
189
|
-
const pendingAutoCompactApprovals = new Map() // approvalId → { resolve, reject, sessionId, timeout }
|
|
190
|
-
|
|
191
|
-
function commandToolPermissionError(session, toolName) {
|
|
192
|
-
const permissions = session?.activeCommandPermissions
|
|
193
|
-
if (!permissions || !commandRestrictedTools.has(toolName)) return null
|
|
194
|
-
if (toolName === 'run_command' && permissions.allowCommands === false) {
|
|
195
|
-
return `Command /${session.activeCommandName} does not allow running shell commands.`
|
|
196
|
-
}
|
|
197
|
-
if (toolName === 'run_subagent' && permissions.allowCommands === false) {
|
|
198
|
-
return `Command /${session.activeCommandName} does not allow running subagents.`
|
|
199
|
-
}
|
|
200
|
-
if ((toolName === 'write_file' || toolName === 'edit_file') && permissions.allowEdit === false) {
|
|
201
|
-
return `Command /${session.activeCommandName} does not allow editing files.`
|
|
202
|
-
}
|
|
203
|
-
return null
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
function createCommandToolPermissions(session) {
|
|
207
|
-
return (toolName) => commandToolPermissionError(session, toolName)
|
|
208
|
-
}
|
|
130
|
+
const SUBAGENT_TRACE_THROTTLE_MS = 150
|
|
209
131
|
|
|
210
132
|
/**
|
|
211
133
|
* Create a Promise that only resolves when the user accepts or rejects the tool call.
|
|
@@ -224,8 +146,14 @@ function createApprovalPromise(session, toolCallId, toolName, args, source) {
|
|
|
224
146
|
resolve({ block: true, reason: `Approval timeout for ${toolName}` })
|
|
225
147
|
}, APPROVAL_TIMEOUT_MS)
|
|
226
148
|
|
|
149
|
+
let onAbort = null
|
|
150
|
+
|
|
227
151
|
const cleanup = () => {
|
|
228
152
|
clearTimeout(timeout)
|
|
153
|
+
if (onAbort) {
|
|
154
|
+
session.agent.signal?.removeEventListener('abort', onAbort)
|
|
155
|
+
onAbort = null
|
|
156
|
+
}
|
|
229
157
|
if (settled) return
|
|
230
158
|
settled = true
|
|
231
159
|
pendingApprovals.delete(toolCallId)
|
|
@@ -239,7 +167,7 @@ function createApprovalPromise(session, toolCallId, toolName, args, source) {
|
|
|
239
167
|
reject(new Error('Run aborted'))
|
|
240
168
|
return
|
|
241
169
|
}
|
|
242
|
-
|
|
170
|
+
onAbort = () => {
|
|
243
171
|
cleanup()
|
|
244
172
|
reject(new Error('Run aborted'))
|
|
245
173
|
}
|
|
@@ -289,8 +217,14 @@ function createAutoCompactApprovalPromise(session, details = {}) {
|
|
|
289
217
|
resolve(false)
|
|
290
218
|
}, APPROVAL_TIMEOUT_MS)
|
|
291
219
|
|
|
220
|
+
let onAbort = null
|
|
221
|
+
|
|
292
222
|
const cleanup = () => {
|
|
293
223
|
clearTimeout(timeout)
|
|
224
|
+
if (onAbort) {
|
|
225
|
+
session.agent.signal?.removeEventListener('abort', onAbort)
|
|
226
|
+
onAbort = null
|
|
227
|
+
}
|
|
294
228
|
if (settled) return
|
|
295
229
|
settled = true
|
|
296
230
|
pendingAutoCompactApprovals.delete(approvalId)
|
|
@@ -303,7 +237,7 @@ function createAutoCompactApprovalPromise(session, details = {}) {
|
|
|
303
237
|
reject(new Error('Run aborted'))
|
|
304
238
|
return
|
|
305
239
|
}
|
|
306
|
-
|
|
240
|
+
onAbort = () => {
|
|
307
241
|
cleanup()
|
|
308
242
|
reject(new Error('Run aborted'))
|
|
309
243
|
}
|
|
@@ -665,67 +599,6 @@ ${taskText}
|
|
|
665
599
|
</plan_command_invocation>`
|
|
666
600
|
}
|
|
667
601
|
|
|
668
|
-
function omitDetailsForLlm(message) {
|
|
669
|
-
if (!message || typeof message !== 'object' || message.details === undefined) return message
|
|
670
|
-
const copy = { ...message }
|
|
671
|
-
delete copy.details
|
|
672
|
-
return copy
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
/**
|
|
676
|
-
* Convert AgentMessage[] to LLM-compatible Message[].
|
|
677
|
-
* Handles "user-with-attachments" → "user" with multi-modal content blocks.
|
|
678
|
-
* Without this the default pi-agent-core convertToLlm silently drops
|
|
679
|
-
* user-with-attachments messages, so the LLM never sees attachments.
|
|
680
|
-
*/
|
|
681
|
-
function serverConvertToLlm(messages) {
|
|
682
|
-
return messages
|
|
683
|
-
.filter(m => m.role !== 'artifact')
|
|
684
|
-
.map(m => {
|
|
685
|
-
if (m.role === 'user-with-attachments') {
|
|
686
|
-
const textContent = typeof m.content === 'string'
|
|
687
|
-
? [{ type: 'text', text: m.content }]
|
|
688
|
-
: [...m.content]
|
|
689
|
-
if (Array.isArray(m.attachments)) {
|
|
690
|
-
for (const att of m.attachments) {
|
|
691
|
-
if (att.type === 'image' && att.content) {
|
|
692
|
-
textContent.push({ type: 'image', data: att.content, mimeType: att.mimeType })
|
|
693
|
-
} else if (att.type === 'document' && att.extractedText) {
|
|
694
|
-
textContent.push({ type: 'text', text: `\n\n[Document: ${att.fileName}]\n${att.extractedText}` })
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
return omitDetailsForLlm({ ...m, role: 'user', content: textContent })
|
|
699
|
-
}
|
|
700
|
-
if (m.role === 'user' || m.role === 'assistant' || m.role === 'toolResult') return omitDetailsForLlm(m)
|
|
701
|
-
return null
|
|
702
|
-
})
|
|
703
|
-
.filter(Boolean)
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
function messageText(message) {
|
|
707
|
-
const content = message?.content
|
|
708
|
-
if (typeof content === 'string') return content
|
|
709
|
-
if (Array.isArray(content)) {
|
|
710
|
-
return content
|
|
711
|
-
.filter((block) => block?.type === 'text')
|
|
712
|
-
.map((block) => block.text ?? '')
|
|
713
|
-
.join('\n')
|
|
714
|
-
.trim()
|
|
715
|
-
}
|
|
716
|
-
return ''
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
function lastAssistantText(messages) {
|
|
720
|
-
for (let index = messages.length - 1; index >= 0; index--) {
|
|
721
|
-
const message = messages[index]
|
|
722
|
-
if (message?.role !== 'assistant') continue
|
|
723
|
-
const text = messageText(message)
|
|
724
|
-
if (text) return text
|
|
725
|
-
}
|
|
726
|
-
return ''
|
|
727
|
-
}
|
|
728
|
-
|
|
729
602
|
async function runSubagent(parentSession, params, parentSignal, onUpdate) {
|
|
730
603
|
const profile = await getAgentProfile(params?.subagent)
|
|
731
604
|
if (!profile || !profile.enabledAsSubagent) {
|
|
@@ -755,6 +628,9 @@ async function runSubagent(parentSession, params, parentSignal, onUpdate) {
|
|
|
755
628
|
let latestMessages = []
|
|
756
629
|
let latestPendingToolCalls = []
|
|
757
630
|
let toolsForClient = []
|
|
631
|
+
let lastTraceAt = 0
|
|
632
|
+
let tracePending = false
|
|
633
|
+
let traceTimer = null
|
|
758
634
|
|
|
759
635
|
const tools = await createServerTools(
|
|
760
636
|
parentSession.projectId,
|
|
@@ -774,6 +650,12 @@ async function runSubagent(parentSession, params, parentSignal, onUpdate) {
|
|
|
774
650
|
toolsForClient = tools.map(({ execute, prepareArguments, ...tool }) => tool)
|
|
775
651
|
|
|
776
652
|
const emitSubagentTrace = () => {
|
|
653
|
+
if (traceTimer) {
|
|
654
|
+
clearTimeout(traceTimer)
|
|
655
|
+
traceTimer = null
|
|
656
|
+
}
|
|
657
|
+
tracePending = false
|
|
658
|
+
lastTraceAt = Date.now()
|
|
777
659
|
onUpdate?.({
|
|
778
660
|
content: [],
|
|
779
661
|
details: {
|
|
@@ -792,6 +674,19 @@ async function runSubagent(parentSession, params, parentSignal, onUpdate) {
|
|
|
792
674
|
})
|
|
793
675
|
}
|
|
794
676
|
|
|
677
|
+
const emitSubagentTraceThrottled = () => {
|
|
678
|
+
const elapsed = Date.now() - lastTraceAt
|
|
679
|
+
if (elapsed >= SUBAGENT_TRACE_THROTTLE_MS) {
|
|
680
|
+
emitSubagentTrace()
|
|
681
|
+
return
|
|
682
|
+
}
|
|
683
|
+
tracePending = true
|
|
684
|
+
if (traceTimer) return
|
|
685
|
+
traceTimer = setTimeout(() => {
|
|
686
|
+
if (tracePending) emitSubagentTrace()
|
|
687
|
+
}, SUBAGENT_TRACE_THROTTLE_MS - elapsed)
|
|
688
|
+
}
|
|
689
|
+
|
|
795
690
|
const systemPrompt = composeSubagentSystemPrompt({
|
|
796
691
|
definition,
|
|
797
692
|
parentSystemPrompt: parentSession.agent.state.systemPrompt,
|
|
@@ -848,7 +743,11 @@ async function runSubagent(parentSession, params, parentSignal, onUpdate) {
|
|
|
848
743
|
latestMessages = [...latestMessages, event.message]
|
|
849
744
|
}
|
|
850
745
|
}
|
|
851
|
-
|
|
746
|
+
if (event.type === 'tool_execution_start' || event.type === 'tool_execution_end' || event.type === 'message_end') {
|
|
747
|
+
emitSubagentTrace()
|
|
748
|
+
} else {
|
|
749
|
+
emitSubagentTraceThrottled()
|
|
750
|
+
}
|
|
852
751
|
})
|
|
853
752
|
|
|
854
753
|
let timedOut = false
|
|
@@ -866,6 +765,7 @@ async function runSubagent(parentSession, params, parentSignal, onUpdate) {
|
|
|
866
765
|
} finally {
|
|
867
766
|
clearTimeout(timeout)
|
|
868
767
|
parentSignal?.removeEventListener?.('abort', onParentAbort)
|
|
768
|
+
emitSubagentTrace()
|
|
869
769
|
}
|
|
870
770
|
|
|
871
771
|
const content = lastAssistantText(subagent.state.messages) || `Subagent ${definition.name} completed without a text response.`
|
|
@@ -1181,6 +1081,7 @@ export async function createAgent(sessionId, config = {}) {
|
|
|
1181
1081
|
if (event.type === 'agent_end') {
|
|
1182
1082
|
session.status = session.agent.state.errorMessage ? 'error' : 'idle'
|
|
1183
1083
|
session.finishedAt = new Date().toISOString()
|
|
1084
|
+
session.toolTimings?.clear()
|
|
1184
1085
|
resetIdleTimer(session)
|
|
1185
1086
|
|
|
1186
1087
|
// Persist after run ends
|
|
@@ -1237,7 +1138,7 @@ async function persistSession(session) {
|
|
|
1237
1138
|
if (messages.length === 0) {
|
|
1238
1139
|
try {
|
|
1239
1140
|
await deleteSessionValue(sessionId)
|
|
1240
|
-
await
|
|
1141
|
+
await atomicSessionMetadataUpdate(scope, projectId, (data) => {
|
|
1241
1142
|
delete data[sessionId]
|
|
1242
1143
|
return data
|
|
1243
1144
|
})
|
|
@@ -1324,7 +1225,7 @@ async function persistSession(session) {
|
|
|
1324
1225
|
// Write to storage atomically (read-modify-write within queue)
|
|
1325
1226
|
try {
|
|
1326
1227
|
await writeSessionValue(sessionId, sessionData)
|
|
1327
|
-
await
|
|
1228
|
+
await atomicSessionMetadataUpdate(scope, projectId, (data) => {
|
|
1328
1229
|
data[sessionId] = {
|
|
1329
1230
|
...metadata,
|
|
1330
1231
|
pinnedAt: data[sessionId]?.pinnedAt,
|
|
@@ -1426,6 +1327,10 @@ export async function runPrompt(sessionId, message) {
|
|
|
1426
1327
|
throw Object.assign(new Error('Session not found'), { statusCode: 404 })
|
|
1427
1328
|
}
|
|
1428
1329
|
|
|
1330
|
+
if (session.agent.state.isStreaming) {
|
|
1331
|
+
throw Object.assign(new Error('Generation is still running. Stop it or wait until it finishes.'), { statusCode: 409 })
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1429
1334
|
resetIdleTimer(session)
|
|
1430
1335
|
|
|
1431
1336
|
// Build user message
|
|
@@ -1701,6 +1606,7 @@ export async function destroyAgent(sessionId) {
|
|
|
1701
1606
|
logger.info(`Destroying session ${sessionId} (status: ${session.status})`, { sessionId, status: session.status })
|
|
1702
1607
|
|
|
1703
1608
|
if (session.idleTimer) clearTimeout(session.idleTimer)
|
|
1609
|
+
session.toolTimings?.clear()
|
|
1704
1610
|
|
|
1705
1611
|
try {
|
|
1706
1612
|
session.agent.abort()
|
|
@@ -2,7 +2,7 @@ import fs from 'node:fs'
|
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
4
4
|
import { randomUUID } from 'node:crypto'
|
|
5
|
-
import { streamSimple } from '@
|
|
5
|
+
import { streamSimple } from '@earendil-works/pi-ai'
|
|
6
6
|
import { logsDir } from './storage.mjs'
|
|
7
7
|
|
|
8
8
|
const PATCH_MARKER = Symbol.for('quickforge.aiHttpLogger.fetchPatched')
|
|
@@ -16,16 +16,31 @@ function currentLogFile() {
|
|
|
16
16
|
return path.join(logsDir, `ai-http-${date}.jsonl`)
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
let logsDirEnsured = false
|
|
20
|
+
|
|
21
|
+
async function ensureLogsDir() {
|
|
22
|
+
if (logsDirEnsured) return
|
|
21
23
|
try {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
const { promises: fsp } = await import('node:fs')
|
|
25
|
+
await fsp.mkdir(logsDir, { recursive: true })
|
|
26
|
+
logsDirEnsured = true
|
|
24
27
|
} catch {
|
|
25
28
|
// Keep AI calls working even when diagnostic logging fails.
|
|
26
29
|
}
|
|
27
30
|
}
|
|
28
31
|
|
|
32
|
+
function writeAiHttpRecord(record) {
|
|
33
|
+
if (!aiHttpLogEnabled) return
|
|
34
|
+
// Schedule async write — never blocks the event loop
|
|
35
|
+
void ensureLogsDir().then(() => {
|
|
36
|
+
try {
|
|
37
|
+
fs.appendFile(currentLogFile(), `${JSON.stringify({ ts: new Date().toISOString(), ...record })}\n`, () => {})
|
|
38
|
+
} catch {
|
|
39
|
+
// Keep AI calls working even when diagnostic logging fails.
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
29
44
|
function headersToRecord(headers) {
|
|
30
45
|
const result = {}
|
|
31
46
|
if (!headers) return result
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool approval store — shared state and permission helpers.
|
|
3
|
+
*
|
|
4
|
+
* Manages the pending approval queues and command-tool permission checks.
|
|
5
|
+
* The Promise-based approval functions (createApprovalPromise,
|
|
6
|
+
* createAutoCompactApprovalPromise) remain in agent-manager.mjs because
|
|
7
|
+
* they depend on the agent event buses.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Constants
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
export const APPROVAL_TIMEOUT_MS = 5 * 60 * 1000 // 5 minutes for tool approval
|
|
15
|
+
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Tool categories
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
export const commandRestrictedTools = new Set([
|
|
21
|
+
'write_file',
|
|
22
|
+
'edit_file',
|
|
23
|
+
'run_command',
|
|
24
|
+
'run_subagent',
|
|
25
|
+
])
|
|
26
|
+
|
|
27
|
+
export const safeReadTools = new Set([
|
|
28
|
+
'read_file',
|
|
29
|
+
'grep_files',
|
|
30
|
+
])
|
|
31
|
+
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// Pending approval queues
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
/** toolCallId → { resolve, reject, sessionId, toolName, args, source, timeout } */
|
|
37
|
+
export const pendingApprovals = new Map()
|
|
38
|
+
|
|
39
|
+
/** approvalId → { resolve, reject, sessionId, timeout } */
|
|
40
|
+
export const pendingAutoCompactApprovals = new Map()
|
|
41
|
+
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// Permission helpers
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
export function commandToolPermissionError(session, toolName) {
|
|
47
|
+
const permissions = session?.activeCommandPermissions
|
|
48
|
+
if (!permissions || !commandRestrictedTools.has(toolName)) return null
|
|
49
|
+
if (toolName === 'run_command' && permissions.allowCommands === false) {
|
|
50
|
+
return `Command /${session.activeCommandName} does not allow running shell commands.`
|
|
51
|
+
}
|
|
52
|
+
if (toolName === 'run_subagent' && permissions.allowCommands === false) {
|
|
53
|
+
return `Command /${session.activeCommandName} does not allow running subagents.`
|
|
54
|
+
}
|
|
55
|
+
if ((toolName === 'write_file' || toolName === 'edit_file') && permissions.allowEdit === false) {
|
|
56
|
+
return `Command /${session.activeCommandName} does not allow editing files.`
|
|
57
|
+
}
|
|
58
|
+
return null
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function createCommandToolPermissions(session) {
|
|
62
|
+
return (toolName) => commandToolPermissionError(session, toolName)
|
|
63
|
+
}
|