@shawnstack/quickforge 1.3.25 → 1.3.26
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 +20 -14
- package/dist/assets/{anthropic-B1_Yrokl.js → anthropic-BcnDL7hi.js} +1 -1
- package/dist/assets/{azure-openai-responses-UMiOBCBd.js → azure-openai-responses-BEfdv0qd.js} +1 -1
- package/dist/assets/{google-BLE_Gcd1.js → google-C2y985rW.js} +1 -1
- package/dist/assets/{google-vertex-6_sIZLVc.js → google-vertex-Jf9zNsCF.js} +1 -1
- package/dist/assets/{icons-Bs7OG8yi.js → icons-BVM5--R9.js} +1 -1
- package/dist/assets/{index-C3bc5C3k.js → index-8Q1Ovled.js} +595 -547
- package/dist/assets/index-ZYbEKGUp.css +3 -0
- package/dist/assets/{mistral-DmZEmRkv.js → mistral-qYbgRY3z.js} +1 -1
- package/dist/assets/{openai-codex-responses-i_SmQGzQ.js → openai-codex-responses--aAgyYJM.js} +1 -1
- package/dist/assets/{openai-completions-BmmZFDDY.js → openai-completions-CHDluyXM.js} +1 -1
- package/dist/assets/{openai-responses-C8tPdeE9.js → openai-responses-UtRriBXu.js} +1 -1
- package/dist/assets/{openai-responses-shared-DchtjQNp.js → openai-responses-shared-G6WDDqJ8.js} +1 -1
- package/dist/assets/{openrouter-CcTv1G_v.js → openrouter-Dz9zwzUG.js} +1 -1
- package/dist/assets/{react-vendor-Cu-7p9CI.js → react-vendor-DAoL5p8_.js} +1 -1
- package/dist/index.html +4 -4
- package/package.json +2 -1
- package/server/agent-manager.mjs +102 -22
- package/server/approval-store.mjs +1 -1
- package/server/custom-commands.mjs +67 -9
- package/server/index.mjs +7 -0
- package/server/plugins/loader.mjs +56 -0
- package/server/plugins/manifest.mjs +174 -0
- package/server/plugins/registry.mjs +304 -0
- package/server/project-config.mjs +53 -4
- package/server/routes/agent.mjs +1 -16
- package/server/routes/plugins.mjs +63 -0
- package/server/routes/project.mjs +2 -0
- package/server/routes/tools.mjs +12 -1
- package/server/skills.mjs +64 -5
- package/server/storage.mjs +13 -6
- package/server/system-prompt.mjs +27 -5
- package/server/tool-wiring.mjs +26 -0
- package/dist/assets/index-C7oT9Rdw.css +0 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as e,d as t,u as n}from"./index-
|
|
1
|
+
import{c as e,d as t,u as n}from"./index-8Q1Ovled.js";import{t as r}from"./headers-5EYI0_pl.js";import{i,n as a,r as o,t as s}from"./github-copilot-headers-CMb2BbzT.js";import{r as c}from"./transform-messages-Dhj_4OTw.js";import{n as l}from"./openai-Bf1npfRy.js";import{t as u}from"./openai-prompt-cache-CErE62Yt.js";import{n as d,r as f,t as p}from"./openai-responses-shared-G6WDDqJ8.js";var m=new Set([`openai`,`openai-codex`,`opencode`]);function h(e){return e||(typeof process<`u`&&{}.PI_CACHE_RETENTION===`long`?`long`:`short`)}function g(e){return{sendSessionIdHeader:e.compat?.sendSessionIdHeader??!0,supportsLongCacheRetention:e.compat?.supportsLongCacheRetention??!0}}function _(e,t){return t===`long`&&e.supportsLongCacheRetention?`24h`:void 0}function v(e){if(e instanceof Error){let t=e.status,n=typeof t==`number`?t:void 0;return n===void 0?e.message:`OpenAI API error (${n}): ${e.message}`}try{return JSON.stringify(e)}catch{return String(e)}}var y=(n,i,a)=>{let o=new e;return(async()=>{let e={role:`assistant`,content:[],api:n.api,provider:n.provider,model:n.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:`stop`,timestamp:Date.now()};try{let s=a?.apiKey||t(n.provider)||``,c=h(a?.cacheRetention)===`none`?void 0:a?.sessionId,l=x(n,i,s,a?.headers,c),u=S(n,i,a),d=await a?.onPayload?.(u,n);d!==void 0&&(u=d);let p={...a?.signal?{signal:a.signal}:{},...a?.timeoutMs===void 0?{}:{timeout:a.timeoutMs},...a?.maxRetries===void 0?{}:{maxRetries:a.maxRetries}},{data:m,response:g}=await l.responses.create(u,p).withResponse();if(await a?.onResponse?.({status:g.status,headers:r(g.headers)},n),o.push({type:`start`,partial:e}),await f(m,e,o,n,{serviceTier:a?.serviceTier,applyServiceTierPricing:(e,t)=>w(e,t,n)}),a?.signal?.aborted)throw Error(`Request was aborted`);if(e.stopReason===`aborted`||e.stopReason===`error`)throw Error(`An unknown error occurred`);o.push({type:`done`,reason:e.stopReason,message:e}),o.end()}catch(t){for(let t of e.content)delete t.index,delete t.partialJson;e.stopReason=a?.signal?.aborted?`aborted`:`error`,e.errorMessage=v(t),o.push({type:`error`,reason:e.stopReason,error:e}),o.end()}})(),o},b=(e,r,i)=>{let a=i?.apiKey||t(e.provider);if(!a)throw Error(`No API key for provider: ${e.provider}`);let o=c(e,i,a),s=i?.reasoning?n(e,i.reasoning):void 0,l=s===`off`?void 0:s;return y(e,r,{...o,reasoningEffort:l})};function x(e,t,n,r,c){if(!n){if(!{}.OPENAI_API_KEY)throw Error(`OpenAI API key is required. Set OPENAI_API_KEY environment variable or pass it as an argument.`);n={}.OPENAI_API_KEY}let u=g(e),d={...e.headers};if(e.provider===`github-copilot`){let e=a(t.messages),n=s({messages:t.messages,hasImages:e});Object.assign(d,n)}c&&(u.sendSessionIdHeader&&(d.session_id=c),d[`x-client-request-id`]=c),r&&Object.assign(d,r);let f=e.provider===`cloudflare-ai-gateway`?{...d,Authorization:d.Authorization??null,"cf-aig-authorization":`Bearer ${n}`}:d;return new l({apiKey:n,baseURL:o(e.provider)?i(e):e.baseUrl,dangerouslyAllowBrowser:!0,defaultHeaders:f})}function S(e,t,n){let r=p(e,t,m),i=h(n?.cacheRetention),a=g(e),o={model:e.id,input:r,stream:!0,prompt_cache_key:i===`none`?void 0:u(n?.sessionId),prompt_cache_retention:_(a,i),store:!1};return n?.maxTokens&&(o.max_output_tokens=n?.maxTokens),n?.temperature!==void 0&&(o.temperature=n?.temperature),n?.serviceTier!==void 0&&(o.service_tier=n.serviceTier),t.tools&&t.tools.length>0&&(o.tools=d(t.tools)),e.reasoning&&(n?.reasoningEffort||n?.reasoningSummary?(o.reasoning={effort:n?.reasoningEffort?e.thinkingLevelMap?.[n.reasoningEffort]??n.reasoningEffort:`medium`,summary:n?.reasoningSummary||`auto`},o.include=[`reasoning.encrypted_content`]):e.provider!==`github-copilot`&&e.thinkingLevelMap?.off!==null&&(o.reasoning={effort:e.thinkingLevelMap?.off??`none`})),o}function C(e,t){switch(t){case`flex`:return .5;case`priority`:return e.id===`gpt-5.5`?2.5:2;default:return 1}}function w(e,t,n){let r=C(n,t);r!==1&&(e.cost.input*=r,e.cost.output*=r,e.cost.cacheRead*=r,e.cost.cacheWrite*=r,e.cost.total=e.cost.input+e.cost.output+e.cost.cacheRead+e.cost.cacheWrite)}export{y as streamOpenAIResponses,b as streamSimpleOpenAIResponses};
|
package/dist/assets/{openai-responses-shared-DchtjQNp.js → openai-responses-shared-G6WDDqJ8.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-8Q1Ovled.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+=`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{d as e}from"./index-
|
|
1
|
+
import{d as e}from"./index-8Q1Ovled.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{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(`
|
|
1
|
+
import{t as e}from"./rolldown-runtime-CkqCuyE9.js";import{it as t}from"./icons-BVM5--R9.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,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-8Q1Ovled.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-BVM5--R9.js">
|
|
19
|
+
<link rel="modulepreload" crossorigin href="/assets/react-vendor-DAoL5p8_.js">
|
|
20
|
+
<link rel="stylesheet" crossorigin href="/assets/index-ZYbEKGUp.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.26",
|
|
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",
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"bin",
|
|
37
37
|
"server",
|
|
38
38
|
"skills",
|
|
39
|
+
"plugins",
|
|
39
40
|
"dist",
|
|
40
41
|
"README.md",
|
|
41
42
|
"LICENSE",
|
package/server/agent-manager.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import { streamSimpleWithAiHttpLogging } from './ai-http-logger.mjs'
|
|
|
5
5
|
import { loadSkillToolContext, abortRunningCommand } from './tools/index.mjs'
|
|
6
6
|
import { createSkillTools, workspaceTools } from './tools/definitions.mjs'
|
|
7
7
|
import { createMcpToolDefinitions, isMcpToolName } from './mcp/registry.mjs'
|
|
8
|
+
import { createPluginToolDefinitions, isPluginToolName } from './plugins/registry.mjs'
|
|
8
9
|
import {
|
|
9
10
|
composeSubagentSystemPrompt,
|
|
10
11
|
formatSubagentTask,
|
|
@@ -31,7 +32,7 @@ import {
|
|
|
31
32
|
resolveCustomCommandInvocation,
|
|
32
33
|
} from './custom-commands.mjs'
|
|
33
34
|
import { omitDetailsForLlm, serverConvertToLlm, messageText, lastAssistantText } from './message-converters.mjs'
|
|
34
|
-
import { isPlainObject, mergeQuickForgeTiming, wrapToolDefinition, wrapMcpToolDefinition, sessionSkillsContext } from './tool-wiring.mjs'
|
|
35
|
+
import { isPlainObject, mergeQuickForgeTiming, wrapToolDefinition, wrapMcpToolDefinition, wrapPluginToolDefinition, sessionSkillsContext } from './tool-wiring.mjs'
|
|
35
36
|
import {
|
|
36
37
|
APPROVAL_TIMEOUT_MS,
|
|
37
38
|
commandRestrictedTools,
|
|
@@ -71,6 +72,7 @@ async function createServerTools(projectId, projectContext, skillsContext, inclu
|
|
|
71
72
|
allowedToolNames = null,
|
|
72
73
|
includeSubagentTool = true,
|
|
73
74
|
includeMcpTools = true,
|
|
75
|
+
includePluginTools = true,
|
|
74
76
|
parentSessionId = null,
|
|
75
77
|
} = options
|
|
76
78
|
const allowedTools = allowedToolNames ? new Set(allowedToolNames) : null
|
|
@@ -103,6 +105,11 @@ async function createServerTools(projectId, projectContext, skillsContext, inclu
|
|
|
103
105
|
tools.push(...mcpTools.filter(isAllowed).map((definition) => wrapMcpToolDefinition(definition, toolPermissions)))
|
|
104
106
|
}
|
|
105
107
|
|
|
108
|
+
if (includePluginTools) {
|
|
109
|
+
const pluginTools = await createPluginToolDefinitions(projectContext)
|
|
110
|
+
tools.push(...pluginTools.filter(isAllowed).map((definition) => wrapPluginToolDefinition(definition, toolContext, toolPermissions)))
|
|
111
|
+
}
|
|
112
|
+
|
|
106
113
|
return tools
|
|
107
114
|
}
|
|
108
115
|
|
|
@@ -553,6 +560,14 @@ async function resolveCommandState(session, userMessage) {
|
|
|
553
560
|
commandName: 'plan',
|
|
554
561
|
}
|
|
555
562
|
}
|
|
563
|
+
if (internalResponse?.review) {
|
|
564
|
+
return {
|
|
565
|
+
userMessage,
|
|
566
|
+
commandPrompt: formatReviewCommandPrompt(internalResponse.args),
|
|
567
|
+
permissions: { allowEdit: false, allowCommands: true, allowSubagents: false },
|
|
568
|
+
commandName: 'review',
|
|
569
|
+
}
|
|
570
|
+
}
|
|
556
571
|
|
|
557
572
|
if (!session.projectContext?.workspaceRoot) return { userMessage }
|
|
558
573
|
|
|
@@ -599,6 +614,33 @@ ${taskText}
|
|
|
599
614
|
</plan_command_invocation>`
|
|
600
615
|
}
|
|
601
616
|
|
|
617
|
+
function formatReviewCommandPrompt(scope) {
|
|
618
|
+
const scopeText = String(scope || '').trim() || '(none; review the repository changes that appear relevant for a pre-commit check)'
|
|
619
|
+
return `<review_command_invocation name="review">
|
|
620
|
+
This /review command applies only to the current user request. Perform a pre-commit self-review of the code that is about to be committed.
|
|
621
|
+
|
|
622
|
+
Rules for this turn:
|
|
623
|
+
- Do not modify files.
|
|
624
|
+
- Do not create files.
|
|
625
|
+
- Do not stage, unstage, commit, tag, push, publish, or otherwise change repository state.
|
|
626
|
+
- Do not use write_file or edit_file.
|
|
627
|
+
- You may use read-only tools and shell commands to inspect the workspace and run validation checks.
|
|
628
|
+
- Do not use subagents; perform the review directly in this turn.
|
|
629
|
+
- Prefer safe inspection commands such as git status, git diff, git diff --cached, and targeted lint/build/test commands.
|
|
630
|
+
- Treat command output as evidence; distinguish confirmed issues from risks or suggestions.
|
|
631
|
+
|
|
632
|
+
Review checklist:
|
|
633
|
+
1. Identify the changes under review, prioritizing staged changes when present and otherwise unstaged working tree changes.
|
|
634
|
+
2. Look for correctness bugs, regressions, edge cases, missing error handling, security or privacy risks, and unintended side effects.
|
|
635
|
+
3. Check whether tests, lint/build validation, or documentation/wiki updates are needed.
|
|
636
|
+
4. Call out any risky commands that should not be run automatically.
|
|
637
|
+
5. Output a concise review with severity, file/area, evidence, and recommended next steps. If no blocking issues are found, say so clearly.
|
|
638
|
+
|
|
639
|
+
User review scope or focus:
|
|
640
|
+
${scopeText}
|
|
641
|
+
</review_command_invocation>`
|
|
642
|
+
}
|
|
643
|
+
|
|
602
644
|
async function runSubagent(parentSession, params, parentSignal, onUpdate) {
|
|
603
645
|
const profile = await getAgentProfile(params?.subagent)
|
|
604
646
|
if (!profile || !profile.enabledAsSubagent) {
|
|
@@ -805,6 +847,57 @@ function applyActiveCommandPrompt(messages, commandPrompt) {
|
|
|
805
847
|
return messages
|
|
806
848
|
}
|
|
807
849
|
|
|
850
|
+
function textFromMessageContent(content) {
|
|
851
|
+
if (typeof content === 'string') return content
|
|
852
|
+
if (Array.isArray(content)) {
|
|
853
|
+
return content.filter((block) => block?.type === 'text').map((block) => block.text ?? '').join('\n')
|
|
854
|
+
}
|
|
855
|
+
return ''
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
function selectedCapabilityPrompt(capabilities) {
|
|
859
|
+
if (!Array.isArray(capabilities) || capabilities.length === 0) return null
|
|
860
|
+
const normalized = capabilities
|
|
861
|
+
.filter((capability) => capability && typeof capability === 'object')
|
|
862
|
+
.map((capability) => ({
|
|
863
|
+
type: String(capability.type || '').slice(0, 32),
|
|
864
|
+
pluginName: String(capability.pluginName || '').slice(0, 120),
|
|
865
|
+
name: String(capability.name || '').slice(0, 120),
|
|
866
|
+
label: String(capability.label || capability.name || '').slice(0, 160),
|
|
867
|
+
description: String(capability.description || '').slice(0, 400),
|
|
868
|
+
}))
|
|
869
|
+
.filter((capability) => capability.type && capability.pluginName && capability.name)
|
|
870
|
+
.slice(0, 4)
|
|
871
|
+
if (normalized.length === 0) return null
|
|
872
|
+
|
|
873
|
+
const lines = normalized.map((capability) => {
|
|
874
|
+
const toolHint = capability.type === 'tool' ? ` Tool name: plugin__${capability.pluginName}__${capability.name}.` : ''
|
|
875
|
+
const description = capability.description ? ` Description: ${capability.description}` : ''
|
|
876
|
+
return `- ${capability.label} (${capability.type}, plugin: ${capability.pluginName}, name: ${capability.name}).${toolHint}${description}`
|
|
877
|
+
}).join('\n')
|
|
878
|
+
|
|
879
|
+
return `The user selected the following QuickForge plugin capability mentions for this turn. Treat them as an explicit preference for routing and context. Use the selected capability when relevant, but do not force it if it is unrelated to the actual request.\n\n${lines}`
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
function applyActiveCapabilityPrompt(messages, capabilityPrompt) {
|
|
883
|
+
if (!capabilityPrompt) return messages
|
|
884
|
+
|
|
885
|
+
for (let index = messages.length - 1; index >= 0; index--) {
|
|
886
|
+
const message = messages[index]
|
|
887
|
+
if (message?.role !== 'user' && message?.role !== 'user-with-attachments') continue
|
|
888
|
+
|
|
889
|
+
const visibleText = textFromMessageContent(message.content)
|
|
890
|
+
const transformed = messages.slice()
|
|
891
|
+
transformed[index] = {
|
|
892
|
+
...message,
|
|
893
|
+
content: `${capabilityPrompt}\n\nUser request:\n${visibleText}`,
|
|
894
|
+
}
|
|
895
|
+
return transformed
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
return messages
|
|
899
|
+
}
|
|
900
|
+
|
|
808
901
|
function compactSummaryIndex(messages) {
|
|
809
902
|
for (let index = messages.length - 1; index >= 0; index--) {
|
|
810
903
|
const message = messages[index]
|
|
@@ -843,7 +936,10 @@ async function transformSessionContext(session, messages, signal) {
|
|
|
843
936
|
}
|
|
844
937
|
const transformedMessages = buildAutoCompactLoopMessages(session, messages)
|
|
845
938
|
session.lastTransformedContextMessages = transformedMessages
|
|
846
|
-
return
|
|
939
|
+
return applyActiveCapabilityPrompt(
|
|
940
|
+
applyActiveCommandPrompt(compactedContextMessages(transformedMessages), session?.activeCommandPrompt),
|
|
941
|
+
session?.activeCapabilityPrompt,
|
|
942
|
+
)
|
|
847
943
|
}
|
|
848
944
|
|
|
849
945
|
export const agentEvents = new EventEmitter()
|
|
@@ -998,7 +1094,7 @@ export async function createAgent(sessionId, config = {}) {
|
|
|
998
1094
|
if (isSkillTool) return undefined
|
|
999
1095
|
if (profileToolNames && !profileToolNames.includes(toolName)) return { block: true, reason: `Agent profile ${agentProfile.name} is not allowed to use ${toolName}.` }
|
|
1000
1096
|
if (toolName === 'run_subagent') return undefined
|
|
1001
|
-
if (isMcpToolName(toolName)) {
|
|
1097
|
+
if (isMcpToolName(toolName) || isPluginToolName(toolName)) {
|
|
1002
1098
|
if (!currentSession?.yoloMode) return createApprovalPromise(currentSession, toolCallId, toolName, context.args)
|
|
1003
1099
|
return undefined
|
|
1004
1100
|
}
|
|
@@ -1296,29 +1392,11 @@ export async function rollbackSessionMessages(sessionId, rollbackMessageIndex) {
|
|
|
1296
1392
|
return { session: getSessionState(sessionId), rollbackIndex }
|
|
1297
1393
|
}
|
|
1298
1394
|
|
|
1299
|
-
export async function replaceSessionMessages(sessionId, messages) {
|
|
1300
|
-
const session = agentSessions.get(sessionId)
|
|
1301
|
-
if (!session) return null
|
|
1302
|
-
if (session.agent.state.isStreaming) {
|
|
1303
|
-
throw Object.assign(new Error('Generation is still running. Stop it or wait until it finishes before rolling back.'), { statusCode: 409 })
|
|
1304
|
-
}
|
|
1305
|
-
updateSessionMessages(session, Array.isArray(messages) ? messages : [])
|
|
1306
|
-
resetSessionCompaction(session)
|
|
1307
|
-
session.status = 'idle'
|
|
1308
|
-
session.finishedAt = new Date().toISOString()
|
|
1309
|
-
await persistSession(session)
|
|
1310
|
-
const nextMessages = session.agent.state.messages
|
|
1311
|
-
const contextUsage = getSessionContextUsage(session)
|
|
1312
|
-
emitSessionEvent(session, { type: 'message_end', messages: nextMessages, contextUsage })
|
|
1313
|
-
emitSessionEvent(session, { type: 'agent_end', messages: nextMessages, contextUsage })
|
|
1314
|
-
return getSessionState(sessionId)
|
|
1315
|
-
}
|
|
1316
|
-
|
|
1317
1395
|
/**
|
|
1318
1396
|
* Send a user message to the agent and start the agent loop.
|
|
1319
1397
|
* Returns immediately; events are streamed via the event bus.
|
|
1320
1398
|
*/
|
|
1321
|
-
export async function runPrompt(sessionId, message) {
|
|
1399
|
+
export async function runPrompt(sessionId, message, selectedCapabilities = []) {
|
|
1322
1400
|
let session = agentSessions.get(sessionId)
|
|
1323
1401
|
if (!session) {
|
|
1324
1402
|
session = await restoreAgent(sessionId)
|
|
@@ -1384,6 +1462,7 @@ export async function runPrompt(sessionId, message) {
|
|
|
1384
1462
|
session.activeCommandName = commandState.commandName ?? null
|
|
1385
1463
|
session.activeCommandPermissions = commandState.permissions ?? null
|
|
1386
1464
|
session.activeCommandPrompt = commandState.commandPrompt ?? null
|
|
1465
|
+
session.activeCapabilityPrompt = selectedCapabilityPrompt(selectedCapabilities)
|
|
1387
1466
|
|
|
1388
1467
|
// Fire and forget — events come through eventBus
|
|
1389
1468
|
session.agent.prompt(userMessage).catch((err) => {
|
|
@@ -1397,6 +1476,7 @@ export async function runPrompt(sessionId, message) {
|
|
|
1397
1476
|
session.activeCommandName = null
|
|
1398
1477
|
session.activeCommandPermissions = null
|
|
1399
1478
|
session.activeCommandPrompt = null
|
|
1479
|
+
session.activeCapabilityPrompt = null
|
|
1400
1480
|
})
|
|
1401
1481
|
|
|
1402
1482
|
return { sessionId, status: session.status }
|
|
@@ -49,7 +49,7 @@ export function commandToolPermissionError(session, toolName) {
|
|
|
49
49
|
if (toolName === 'run_command' && permissions.allowCommands === false) {
|
|
50
50
|
return `Command /${session.activeCommandName} does not allow running shell commands.`
|
|
51
51
|
}
|
|
52
|
-
if (toolName === 'run_subagent' && permissions.allowCommands === false) {
|
|
52
|
+
if (toolName === 'run_subagent' && (permissions.allowSubagents === false || permissions.allowCommands === false)) {
|
|
53
53
|
return `Command /${session.activeCommandName} does not allow running subagents.`
|
|
54
54
|
}
|
|
55
55
|
if ((toolName === 'write_file' || toolName === 'edit_file') && permissions.allowEdit === false) {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { promises as fs } from 'node:fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
|
+
import { getEnabledPluginCommandSources } from './plugins/registry.mjs'
|
|
3
4
|
|
|
5
|
+
const commandsRelativeDirs = ['.claude/commands', '.opencode/commands', '.ai/commands']
|
|
4
6
|
const commandsRelativeDir = '.ai/commands'
|
|
5
7
|
const commandNamePattern = /^(?!.*--)[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/
|
|
6
8
|
|
|
@@ -23,10 +25,9 @@ function configuredCommandDirectories(workspaceRoot, commandDir) {
|
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
function commandDirectories(workspaceRoot, commandDir) {
|
|
26
|
-
|
|
27
|
-
if (!defaultDir) return []
|
|
28
|
+
if (!workspaceRoot) return []
|
|
28
29
|
|
|
29
|
-
const dirs =
|
|
30
|
+
const dirs = commandsRelativeDirs.map((dir) => path.join(path.resolve(workspaceRoot), dir))
|
|
30
31
|
for (const configuredDir of configuredCommandDirectories(workspaceRoot, commandDir)) {
|
|
31
32
|
if (!dirs.some((dir) => path.resolve(dir) === path.resolve(configuredDir))) {
|
|
32
33
|
dirs.push(configuredDir)
|
|
@@ -102,7 +103,7 @@ function firstOptionalBoolean(...values) {
|
|
|
102
103
|
return undefined
|
|
103
104
|
}
|
|
104
105
|
|
|
105
|
-
function commandFromFile(file, text) {
|
|
106
|
+
function commandFromFile(file, text, options = {}) {
|
|
106
107
|
const parsed = parseFrontmatter(text)
|
|
107
108
|
if (!parsed.body) return null
|
|
108
109
|
|
|
@@ -127,7 +128,9 @@ function commandFromFile(file, text) {
|
|
|
127
128
|
),
|
|
128
129
|
body: parsed.body,
|
|
129
130
|
filePath: file,
|
|
130
|
-
relativePath: path.relative(path.dirname(path.dirname(file)), file).replace(/\\/g, '/'),
|
|
131
|
+
relativePath: options.relativePath || path.relative(path.dirname(path.dirname(file)), file).replace(/\\/g, '/'),
|
|
132
|
+
source: options.source,
|
|
133
|
+
pluginName: options.pluginName,
|
|
131
134
|
}
|
|
132
135
|
}
|
|
133
136
|
|
|
@@ -159,7 +162,7 @@ export function textFromUserMessage(message) {
|
|
|
159
162
|
.join('\n')
|
|
160
163
|
}
|
|
161
164
|
|
|
162
|
-
async function listCommandsFromDirectory(dir) {
|
|
165
|
+
async function listCommandsFromDirectory(dir, options = {}) {
|
|
163
166
|
let entries
|
|
164
167
|
try {
|
|
165
168
|
entries = await fs.readdir(dir, { withFileTypes: true })
|
|
@@ -173,7 +176,14 @@ async function listCommandsFromDirectory(dir) {
|
|
|
173
176
|
if (!entry.isFile() || !entry.name.toLowerCase().endsWith('.md')) continue
|
|
174
177
|
const file = path.join(dir, entry.name)
|
|
175
178
|
try {
|
|
176
|
-
const
|
|
179
|
+
const relativePath = options.relativeRoot
|
|
180
|
+
? `${options.relativeRoot}/${entry.name}`.replace(/\\/g, '/')
|
|
181
|
+
: undefined
|
|
182
|
+
const command = commandFromFile(file, await fs.readFile(file, 'utf8'), {
|
|
183
|
+
source: options.source,
|
|
184
|
+
pluginName: options.pluginName,
|
|
185
|
+
relativePath,
|
|
186
|
+
})
|
|
177
187
|
if (command) commands.push(command)
|
|
178
188
|
} catch (error) {
|
|
179
189
|
console.warn(`Failed to load custom command ${file}:`, error.message || error)
|
|
@@ -183,9 +193,49 @@ async function listCommandsFromDirectory(dir) {
|
|
|
183
193
|
return commands
|
|
184
194
|
}
|
|
185
195
|
|
|
196
|
+
async function listCommandsFromFile(file, options = {}) {
|
|
197
|
+
if (!file.toLowerCase().endsWith('.md')) return []
|
|
198
|
+
try {
|
|
199
|
+
const command = commandFromFile(file, await fs.readFile(file, 'utf8'), options)
|
|
200
|
+
return command ? [command] : []
|
|
201
|
+
} catch (error) {
|
|
202
|
+
if (error?.code === 'ENOENT' || error?.code === 'ENOTDIR' || error?.code === 'EACCES' || error?.code === 'EPERM') return []
|
|
203
|
+
console.warn(`Failed to load custom command ${file}:`, error.message || error)
|
|
204
|
+
return []
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
async function listCommandsFromPluginSource(source) {
|
|
209
|
+
const stat = await fs.stat(source.path).catch(() => null)
|
|
210
|
+
if (!stat) return []
|
|
211
|
+
const options = {
|
|
212
|
+
source: source.source,
|
|
213
|
+
pluginName: source.pluginName,
|
|
214
|
+
relativePath: source.relativePath,
|
|
215
|
+
relativeRoot: source.relativePath,
|
|
216
|
+
}
|
|
217
|
+
if (stat.isFile()) return listCommandsFromFile(source.path, options)
|
|
218
|
+
if (stat.isDirectory()) return listCommandsFromDirectory(source.path, options)
|
|
219
|
+
return []
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
async function listPluginCommands(workspaceRoot) {
|
|
223
|
+
if (!workspaceRoot) return []
|
|
224
|
+
const sources = await getEnabledPluginCommandSources({ workspaceRoot })
|
|
225
|
+
const commands = []
|
|
226
|
+
for (const source of sources) {
|
|
227
|
+
commands.push(...await listCommandsFromPluginSource(source))
|
|
228
|
+
}
|
|
229
|
+
return commands
|
|
230
|
+
}
|
|
231
|
+
|
|
186
232
|
export async function listProjectCommands(workspaceRoot, commandDir) {
|
|
187
233
|
const byName = new Map()
|
|
188
234
|
|
|
235
|
+
for (const command of (await listPluginCommands(workspaceRoot)).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
236
|
+
byName.set(command.name, command)
|
|
237
|
+
}
|
|
238
|
+
|
|
189
239
|
for (const dir of commandDirectories(workspaceRoot, commandDir)) {
|
|
190
240
|
const commands = await listCommandsFromDirectory(dir)
|
|
191
241
|
for (const command of commands.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
@@ -254,6 +304,9 @@ export function parseInternalCommandInvocation(message) {
|
|
|
254
304
|
const planMatch = text.match(/^\/plan(?:\s+([\s\S]*))?$/i)
|
|
255
305
|
if (planMatch) return { type: 'plan', args: (planMatch[1] || '').trim() }
|
|
256
306
|
|
|
307
|
+
const reviewMatch = text.match(/^\/review(?:\s+([\s\S]*))?$/i)
|
|
308
|
+
if (reviewMatch) return { type: 'review', args: (reviewMatch[1] || '').trim() }
|
|
309
|
+
|
|
257
310
|
const compactMatch = text.match(/^\/compact(?:\s+([\s\S]*))?$/i)
|
|
258
311
|
if (compactMatch) return { type: 'compact', args: (compactMatch[1] || '').trim() }
|
|
259
312
|
|
|
@@ -278,6 +331,11 @@ export async function handleInternalCommand(invocation, workspaceRoot, commandDi
|
|
|
278
331
|
return { plan: true, args: invocation.args }
|
|
279
332
|
}
|
|
280
333
|
|
|
334
|
+
if (invocation.type === 'review') {
|
|
335
|
+
if (!workspaceRoot) return 'Review requires an active project chat.'
|
|
336
|
+
return { review: true, args: invocation.args || '' }
|
|
337
|
+
}
|
|
338
|
+
|
|
281
339
|
if (invocation.type === 'clear') {
|
|
282
340
|
return { clear: true }
|
|
283
341
|
}
|
|
@@ -319,7 +377,7 @@ function formatCommandList(commands) {
|
|
|
319
377
|
'/command new review',
|
|
320
378
|
'```',
|
|
321
379
|
'',
|
|
322
|
-
'Or add Markdown files under `.ai/commands/`, for example `.ai/commands/review.md`.',
|
|
380
|
+
'Or add Markdown files under `.claude/commands/`, `.opencode/commands/`, or `.ai/commands/`, for example `.ai/commands/review.md`.',
|
|
323
381
|
].join('\n')
|
|
324
382
|
}
|
|
325
383
|
|
|
@@ -335,7 +393,7 @@ function formatCommandList(commands) {
|
|
|
335
393
|
'',
|
|
336
394
|
...rows,
|
|
337
395
|
'',
|
|
338
|
-
'Command files live in `.
|
|
396
|
+
'Command files live in `.claude/commands/*.md`, `.opencode/commands/*.md`, `.ai/commands/*.md`, or configured directories. Use `$ARGUMENTS` inside a command file to insert invocation arguments.',
|
|
339
397
|
].join('\n')
|
|
340
398
|
}
|
|
341
399
|
|
package/server/index.mjs
CHANGED
|
@@ -24,6 +24,7 @@ import { handleSharesApi } from './routes/shares.mjs'
|
|
|
24
24
|
import { handleSharedConversationApi } from './routes/shared-conversation.mjs'
|
|
25
25
|
import { handleLanAccessApi, renderLanUnlockPage } from './routes/lan-access.mjs'
|
|
26
26
|
import { handleMcpApi } from './routes/mcp.mjs'
|
|
27
|
+
import { handlePluginsApi } from './routes/plugins.mjs'
|
|
27
28
|
import { handleWorkspaceApi, handleGitApi } from './routes/workspace.mjs'
|
|
28
29
|
import { handleTerminalApi, handleTerminalUpgrade } from './routes/terminal.mjs'
|
|
29
30
|
import { serveStatic } from './routes/static.mjs'
|
|
@@ -227,6 +228,12 @@ async function handleApi(req, res, url) {
|
|
|
227
228
|
return
|
|
228
229
|
}
|
|
229
230
|
|
|
231
|
+
// Plugins
|
|
232
|
+
if (pathname === '/api/plugins' || pathname.startsWith('/api/plugins/')) {
|
|
233
|
+
await handlePluginsApi(req, res, url)
|
|
234
|
+
return
|
|
235
|
+
}
|
|
236
|
+
|
|
230
237
|
// Project routes
|
|
231
238
|
if (pathname === '/api/project' || pathname.startsWith('/api/project/')) {
|
|
232
239
|
await handleProjectApi(req, res, url)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { pathToFileURL } from 'node:url'
|
|
2
|
+
|
|
3
|
+
function isPlainObject(value) {
|
|
4
|
+
return Boolean(value && typeof value === 'object' && !Array.isArray(value))
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function contentToText(result) {
|
|
8
|
+
if (typeof result === 'string') return result
|
|
9
|
+
if (Array.isArray(result?.content)) {
|
|
10
|
+
return result.content.map((item) => {
|
|
11
|
+
if (typeof item === 'string') return item
|
|
12
|
+
if (item?.type === 'text') return item.text || ''
|
|
13
|
+
return JSON.stringify(item)
|
|
14
|
+
}).join('\n')
|
|
15
|
+
}
|
|
16
|
+
if (Object.prototype.hasOwnProperty.call(result || {}, 'content')) return String(result.content ?? '')
|
|
17
|
+
return JSON.stringify(result ?? null, null, 2)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function loadPlugin(manifest, context = {}) {
|
|
21
|
+
const mainPath = new URL(manifest.main, pathToFileURL(`${manifest.dir}/`))
|
|
22
|
+
const moduleUrl = `${mainPath.href}?quickforgePluginReload=${Date.now()}`
|
|
23
|
+
const module = await import(moduleUrl)
|
|
24
|
+
const factory = module.createPlugin || module.default
|
|
25
|
+
if (typeof factory !== 'function') {
|
|
26
|
+
throw new Error(`Plugin ${manifest.name} must export createPlugin(context) or a default factory function.`)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const plugin = await factory({
|
|
30
|
+
...context,
|
|
31
|
+
plugin: {
|
|
32
|
+
name: manifest.name,
|
|
33
|
+
displayName: manifest.displayName,
|
|
34
|
+
version: manifest.version,
|
|
35
|
+
dir: manifest.dir,
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
if (!isPlainObject(plugin)) {
|
|
40
|
+
throw new Error(`Plugin ${manifest.name} factory must return an object.`)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const tools = isPlainObject(plugin.tools) ? plugin.tools : {}
|
|
44
|
+
return {
|
|
45
|
+
async callTool(toolName, params = {}, toolContext = {}) {
|
|
46
|
+
const handler = tools[toolName]
|
|
47
|
+
if (typeof handler !== 'function') throw new Error(`Plugin ${manifest.name} did not provide handler for tool ${toolName}.`)
|
|
48
|
+
const result = await handler(params || {}, toolContext)
|
|
49
|
+
return {
|
|
50
|
+
content: contentToText(result),
|
|
51
|
+
details: isPlainObject(result?.details) ? result.details : undefined,
|
|
52
|
+
isError: Boolean(result?.isError),
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
}
|