@qfei-design/make-ai-assistant 0.2.8 → 0.2.10
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/PUBLIC_API.md +20 -27
- package/README.md +16 -29
- package/capabilities.json +36 -9
- package/dist/conversation-CZfbgCXd.js +1111 -0
- package/dist/conversation-Cvh-IVRV.cjs +1 -0
- package/dist/core/conversation-management.d.ts +212 -0
- package/dist/core/conversation.d.ts +34 -2
- package/dist/core/index.d.ts +2 -0
- package/dist/core/response-state.d.ts +8 -0
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +4 -4
- package/dist/make-app/protocol.d.ts +27 -0
- package/dist/make-app/stream.d.ts +20 -0
- package/dist/make-app.cjs +1 -1
- package/dist/make-app.d.ts +46 -11
- package/dist/make-app.mjs +698 -259
- package/dist/make-console.cjs +1 -1
- package/dist/make-console.mjs +1 -1
- package/dist/react/conversation-controls.d.ts +15 -0
- package/dist/react/theme.d.ts +1 -1
- package/dist/react/use-attachments.d.ts +26 -0
- package/dist/react/use-conversation-manager.d.ts +35 -0
- package/dist/react.cjs +4 -4
- package/dist/react.mjs +1712 -747
- package/dist/sse.cjs +1 -1
- package/dist/sse.mjs +1 -1
- package/dist/styles.css +61 -10
- package/docs/backend-contract.md +8 -21
- package/docs/make-app-integration.md +80 -0
- package/examples/make-app/README.md +11 -0
- package/examples/make-app/index.html +5 -0
- package/examples/make-app/main.tsx +34 -0
- package/examples/make-app/style.css +4 -0
- package/examples/make-app/transport.ts +163 -0
- package/examples/make-app/vite.config.ts +7 -0
- package/package.json +10 -2
- package/recipes.json +36 -13
- package/dist/conversation-B7eGUXi-.js +0 -727
- package/dist/conversation-Cv1wdvCR.cjs +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";const O=(t,e)=>{let r=0;for(const n of t)if(r+=1,r>e)break;return r};const m={actions:10,comparisonItems:24,jsonCharacters:1e6,jsonDepth:64,jsonNodes:1e4,rankingItems:50,recordColumns:20,recordListRecords:100,recordValues:100,textCharacters:2e4,trendPointsPerSeries:120,trendSeries:8,validationIssues:100},l={artifactsPerRun:50,assistantMessagesPerRun:20,historyArtifacts:500,historyCharacters:1e6,historyMessages:200,identifierCharacters:1e3,messageCharacters:1e5,progressCharactersPerRun:2e4,progressStepsPerRun:50},H=["metric","comparison","trend","ranking","record-list","notice"],K=()=>({success:!1,issues:[{path:"",message:"could not be safely inspected"}]}),st=new Set(["navigate","open-record","open-list","invoke"]),nt=new Set(["decimal","currency","percent"]);class U extends Array{push(...e){const r=m.validationIssues-this.length;return r>0?super.push(...e.slice(0,r)):this.length}}const h=t=>(()=>{if(typeof t!="object"||t===null||Array.isArray(t))return!1;const e=Object.getPrototypeOf(t);return e===Object.prototype||e===null})(),G=t=>typeof t=="string"&&t.trim().length>0,V=(t,e)=>{let r=0;for(const n of t)if(r+=1,r>e)return r;return r},C=t=>typeof t=="string"&&V(t,m.textCharacters)<=m.textCharacters,$=t=>typeof t=="number"&&Number.isFinite(t),at=t=>t.length<=120?t:`${t.slice(0,117)}...`,b=(t,e,r)=>{G(t)?C(t)||r.push({path:e,message:`must contain at most ${m.textCharacters} characters`}):r.push({path:e,message:"must be a non-empty string"})},_=(t,e,r)=>{t!==void 0&&typeof t!="string"?r.push({path:e,message:"must be a string"}):typeof t=="string"&&!C(t)&&r.push({path:e,message:`must contain at most ${m.textCharacters} characters`})},I=(t,e,r,n)=>{for(const a in t)if(Object.prototype.hasOwnProperty.call(t,a)){if(n.length>=m.validationIssues)break;e.has(a)||n.push({path:at(r?`${r}.${a}`:a),message:"is not supported"})}},T=(t,e,r,n)=>t.length>e?(n.push({path:r,message:`must contain at most ${e} items`}),!0):!1,x=(t,e,r)=>{for(let n=0;n<t.length;n+=1)if(!Object.prototype.hasOwnProperty.call(t,n))return r.push({path:e,message:"must not contain empty array slots"}),!0;return!1},M=(t,e,r,n)=>{const a=new Set;t.forEach((s,o)=>{if(!h(s)||typeof s[e]!="string")return;const d=s[e];a.has(d)?n.push({path:`${r}[${o}].${e}`,message:"must be unique within the collection"}):a.add(d)})},ot=new Set(["schemaVersion","id","kind","title","summary","presentation","actions","meta","data"]),it=new Set(["template","density"]),ct=new Set(["style","currency","precision","unit"]),dt=new Set(["id","label","intent","target","appearance"]),pt=new Set(["value","format","delta","context"]),mt=new Set(["value","format","direction","label"]),X=new Set(["items"]),lt=new Set(["id","label","value","format","hint"]),ft=new Set(["series"]),ut=new Set(["id","label","points","format"]),ht=new Set(["x","y"]),It=new Set(["id","label","value","format","description"]),gt=new Set(["entity","columns","records","total"]),yt=new Set(["key","label"]),bt=new Set(["key","label","format"]),wt=new Set(["id","title","values","action"]),Et=new Set(["tone","body"]),j=(t,e,r)=>h(t)?(I(t,ct,e,r),t.style!==void 0&&(typeof t.style!="string"||!nt.has(t.style))&&r.push({path:`${e}.style`,message:"is not supported"}),t.currency!==void 0&&b(t.currency,`${e}.currency`,r),t.precision!==void 0&&(!Number.isInteger(t.precision)||Number(t.precision)<0||Number(t.precision)>20)&&r.push({path:`${e}.precision`,message:"must be an integer between 0 and 20"}),_(t.unit,`${e}.unit`,r),!0):(r.push({path:e,message:"must be an object"}),!1),q=t=>{const e=[{kind:"visit",depth:0,value:t}],r=new WeakSet;let n=0,a=0;try{for(;e.length>0;){const s=e.pop();if(!s)break;if(s.kind==="leave"){r.delete(s.value);continue}if(a+=1,a>m.jsonNodes||s.depth>m.jsonDepth)return!1;if(s.value===null||typeof s.value=="boolean")continue;if(typeof s.value=="string"){if(n+=V(s.value,m.textCharacters),!C(s.value)||n>m.jsonCharacters)return!1;continue}if(typeof s.value=="number"){if(!Number.isFinite(s.value))return!1;continue}if(!Array.isArray(s.value)&&!h(s.value)||r.has(s.value))return!1;r.add(s.value),e.push({kind:"leave",value:s.value});const o=m.jsonNodes-a;if(Array.isArray(s.value)){if(s.value.length>o)return!1;for(let d=s.value.length-1;d>=0;d-=1)e.push({kind:"visit",depth:s.depth+1,value:s.value[d]})}else{const d=[];for(const p in s.value)if(Object.prototype.hasOwnProperty.call(s.value,p)){if(!C(p)||(n+=V(p,m.textCharacters),n>m.jsonCharacters)||d.length>=o)return!1;d.push(p)}for(let p=d.length-1;p>=0;p-=1){const i=d[p];e.push({kind:"visit",depth:s.depth+1,value:s.value[i]})}}}return!0}catch{return!1}},St=t=>t===null||typeof t=="boolean"||C(t)||$(t),Q=(t,e,r)=>h(t)?(I(t,dt,e,r),b(t.id,`${e}.id`,r),b(t.label,`${e}.label`,r),(typeof t.intent!="string"||!st.has(t.intent))&&r.push({path:`${e}.intent`,message:"is not supported"}),(!h(t.target)||!q(t.target))&&r.push({path:`${e}.target`,message:"must be a JSON object"}),t.appearance!==void 0&&(typeof t.appearance!="string"||!["primary","secondary","link"].includes(t.appearance))&&r.push({path:`${e}.appearance`,message:"is not supported"}),!0):(r.push({path:e,message:"must be an object"}),!1),At=(t,e)=>{if(I(t,ot,"",e),t.schemaVersion!=="1.0"&&e.push({path:"schemaVersion",message:"must equal 1.0"}),b(t.id,"id",e),H.includes(t.kind)||e.push({path:"kind",message:"is not a supported Artifact kind"}),_(t.title,"title",e),_(t.summary,"summary",e),t.presentation!==void 0&&(h(t.presentation)?(I(t.presentation,it,"presentation",e),t.presentation.template!==void 0&&!G(t.presentation.template)?e.push({path:"presentation.template",message:"must be a non-empty string"}):t.presentation.template!==void 0&&!C(t.presentation.template)&&e.push({path:"presentation.template",message:`must contain at most ${m.textCharacters} characters`}),t.presentation.density!==void 0&&(typeof t.presentation.density!="string"||!["compact","comfortable"].includes(t.presentation.density))&&e.push({path:"presentation.density",message:"is not supported"})):e.push({path:"presentation",message:"must be an object"})),t.actions!==void 0){if(!Array.isArray(t.actions))e.push({path:"actions",message:"must be an array"});else if(!T(t.actions,m.actions,"actions",e)){if(x(t.actions,"actions",e))return;M(t.actions,"id","actions",e),t.actions.forEach((n,a)=>Q(n,`actions[${a}]`,e))}}t.meta!==void 0&&(!h(t.meta)||!q(t.meta))&&e.push({path:"meta",message:"must be a JSON object"})},Ct=(t,e)=>{I(t,pt,"data",e),!$(t.value)&&!C(t.value)&&e.push({path:"data.value",message:"must be a finite number or string"}),t.format!==void 0&&j(t.format,"data.format",e),t.delta!==void 0&&(h(t.delta)?(I(t.delta,mt,"data.delta",e),$(t.delta.value)||e.push({path:"data.delta.value",message:"must be a finite number"}),t.delta.direction!==void 0&&(typeof t.delta.direction!="string"||!["up","down","flat"].includes(t.delta.direction))&&e.push({path:"data.delta.direction",message:"is not supported"}),t.delta.format!==void 0&&(typeof t.delta.format!="string"||!["decimal","percent"].includes(t.delta.format))&&e.push({path:"data.delta.format",message:"is not supported"}),_(t.delta.label,"data.delta.label",e)):e.push({path:"data.delta",message:"must be an object"})),_(t.context,"data.context",e)},_t=(t,e)=>{if(I(t,X,"data",e),!Array.isArray(t.items)||t.items.length===0){e.push({path:"data.items",message:"must be a non-empty array"});return}T(t.items,m.comparisonItems,"data.items",e)||x(t.items,"data.items",e)||(M(t.items,"id","data.items",e),t.items.forEach((r,n)=>{const a=`data.items[${n}]`;if(!h(r)){e.push({path:a,message:"must be an object"});return}I(r,lt,a,e),b(r.id,`${a}.id`,e),b(r.label,`${a}.label`,e),!$(r.value)&&!C(r.value)&&e.push({path:`${a}.value`,message:"must be a finite number or string"}),r.format!==void 0&&j(r.format,`${a}.format`,e),_(r.hint,`${a}.hint`,e)}))},Rt=(t,e)=>{if(I(t,ft,"data",e),!Array.isArray(t.series)||t.series.length===0){e.push({path:"data.series",message:"must be a non-empty array"});return}T(t.series,m.trendSeries,"data.series",e)||x(t.series,"data.series",e)||(M(t.series,"id","data.series",e),t.series.forEach((r,n)=>{const a=`data.series[${n}]`;if(!h(r)){e.push({path:a,message:"must be an object"});return}if(I(r,ut,a,e),b(r.id,`${a}.id`,e),b(r.label,`${a}.label`,e),r.format!==void 0&&j(r.format,`${a}.format`,e),!Array.isArray(r.points)||r.points.length===0){e.push({path:`${a}.points`,message:"must be a non-empty array"});return}T(r.points,m.trendPointsPerSeries,`${a}.points`,e)||x(r.points,`${a}.points`,e)||r.points.forEach((s,o)=>{const d=`${a}.points[${o}]`;if(!h(s)){e.push({path:d,message:"must be an object"});return}I(s,ht,d,e),!$(s.x)&&!C(s.x)&&e.push({path:`${d}.x`,message:"must be a finite number or string"}),$(s.y)||e.push({path:`${d}.y`,message:"must be a finite number"})})}))},kt=(t,e)=>{if(I(t,X,"data",e),!Array.isArray(t.items)||t.items.length===0){e.push({path:"data.items",message:"must be a non-empty array"});return}T(t.items,m.rankingItems,"data.items",e)||x(t.items,"data.items",e)||(M(t.items,"id","data.items",e),t.items.forEach((r,n)=>{const a=`data.items[${n}]`;if(!h(r)){e.push({path:a,message:"must be an object"});return}I(r,It,a,e),b(r.id,`${a}.id`,e),b(r.label,`${a}.label`,e),$(r.value)||e.push({path:`${a}.value`,message:"must be a finite number"}),r.format!==void 0&&j(r.format,`${a}.format`,e),_(r.description,`${a}.description`,e)}))},$t=(t,e)=>{if(I(t,gt,"data",e),h(t.entity)?(I(t.entity,yt,"data.entity",e),b(t.entity.key,"data.entity.key",e),_(t.entity.label,"data.entity.label",e)):e.push({path:"data.entity",message:"must be an object"}),!Array.isArray(t.columns)||t.columns.length===0)e.push({path:"data.columns",message:"must be a non-empty array"});else if(!T(t.columns,m.recordColumns,"data.columns",e)){if(x(t.columns,"data.columns",e))return;M(t.columns,"key","data.columns",e),t.columns.forEach((n,a)=>{const s=`data.columns[${a}]`;if(!h(n)){e.push({path:s,message:"must be an object"});return}I(n,bt,s,e),b(n.key,`${s}.key`,e),b(n.label,`${s}.label`,e),n.format!==void 0&&j(n.format,`${s}.format`,e)})}if(!Array.isArray(t.records))e.push({path:"data.records",message:"must be an array"});else if(!T(t.records,m.recordListRecords,"data.records",e)){if(x(t.records,"data.records",e))return;M(t.records,"id","data.records",e),t.records.forEach((n,a)=>{const s=`data.records[${a}]`;if(!h(n)){e.push({path:s,message:"must be an object"});return}if(I(n,wt,s,e),b(n.id,`${s}.id`,e),_(n.title,`${s}.title`,e),!h(n.values))e.push({path:`${s}.values`,message:"must contain only JSON primitive display values"});else{const o=n.values;let d=!1,p=0;for(const i in o)if(Object.prototype.hasOwnProperty.call(o,i)){if(p+=1,p>m.recordValues)break;d||=!C(i)||!St(o[i])}p>m.recordValues?e.push({path:`${s}.values`,message:`must contain at most ${m.recordValues} values`}):d&&e.push({path:`${s}.values`,message:"must contain only JSON primitive display values"})}n.action!==void 0&&Q(n.action,`${s}.action`,e)})}t.total!==void 0&&(!Number.isInteger(t.total)||Number(t.total)<0)&&e.push({path:"data.total",message:"must be a non-negative integer"})},Tt=(t,e)=>{I(t,Et,"data",e),(typeof t.tone!="string"||!["info","success","warning","danger"].includes(t.tone))&&e.push({path:"data.tone",message:"is not supported"}),b(t.body,"data.body",e)},J=(t,e)=>{if(At(t,e),!h(t.data)){e.push({path:"data",message:"must be an object"});return}switch(t.kind){case"metric":Ct(t.data,e);break;case"comparison":_t(t.data,e);break;case"trend":Rt(t.data,e);break;case"ranking":kt(t.data,e);break;case"record-list":$t(t.data,e);break;case"notice":Tt(t.data,e);break}},Z=t=>{const e=new U;try{if(!h(t))return{success:!1,issues:[{path:"",message:"must be an object"}]};J(t,e)}catch{return K()}if(e.length>0)return{success:!1,issues:e};if(!q(t))return{success:!1,issues:[{path:"",message:"exceeds the Artifact resource budget"}]};let r;try{r=structuredClone(t)}catch{return K()}const n=new U;try{if(!h(r))return K();J(r,n)}catch{return K()}return n.length===0&&!q(r)&&n.push({path:"",message:"exceeds the Artifact resource budget"}),n.length===0?{success:!0,artifact:r}:{success:!1,issues:n}},z=t=>{const e=Z(t);if(e.success)return e.artifact;const r=e.issues.map(n=>`${n.path||"artifact"} ${n.message}`).join(", ");throw new Error(`Invalid Make AI Artifact: ${r}`)},A=t=>t==="completed"||t==="failed"||t==="cancelled",R=t=>{if(!t||typeof t!="object"||Array.isArray(t))throw new Error("Invalid assistant data: object");return t},w=(t,e=256,r=!1)=>{if(typeof t!="string"||t.length>e*2||!r&&!t.trim()||t.includes("\0")||[...t].length>e)throw new Error("Invalid assistant data: text");return t},u=t=>{const e=w(t);if(["__proto__","constructor","prototype"].includes(e))throw new Error("Invalid assistant data: identifier");return e},k=(t,e=0,r=Number.MAX_SAFE_INTEGER)=>{if(!Number.isSafeInteger(t)||Number(t)<e||Number(t)>r)throw new Error("Invalid assistant data: integer");return t},v=t=>{if(typeof t!="boolean")throw new Error("Invalid assistant data: boolean");return t},Y=(t,e)=>{if(!Array.isArray(t)||t.length>e)throw new Error("Invalid assistant data: array");return t},y=(t,e)=>{if(Object.keys(t).some(r=>!e.includes(r)))throw new Error("Invalid assistant data: unknown field")},L=t=>{if(!["queued","dispatched","running","completed","failed","cancelled"].includes(String(t)))throw new Error("Invalid assistant data: status");return t},F=t=>Y(t,32).map(e=>{const r=R(e),n=r.id===void 0?{}:{id:u(r.id)};if(r.kind==="text")return y(r,["id","kind","text"]),{...n,kind:"text",text:w(r.text,1e5,!0)};if(!["image","file","audio","video"].includes(String(r.kind)))throw new Error("Invalid assistant data: part kind");y(r,["id","kind","name","media"]);const a=R(r.media);y(a,["contentRef","contentType","sizeBytes","digestSha256"]);const s=w(a.digestSha256,64);if(!/^[0-9a-f]{64}$/.test(s))throw new Error("Invalid assistant data: digest");return{...n,kind:r.kind,...r.name===void 0?{}:{name:w(r.name,512,!0)},media:{contentRef:u(a.contentRef),contentType:w(a.contentType,256),sizeBytes:k(a.sizeBytes,0,64<<20),digestSha256:s}}}),B=t=>{const e=R(t);if(y(e,["id","rating","revision","reason","comment"]),!["like","dislike","none"].includes(String(e.rating)))throw new Error("Invalid assistant data: rating");return{id:u(e.id),rating:e.rating,revision:k(e.revision,1),...e.reason===void 0?{}:{reason:w(e.reason,128,!0)},...e.comment===void 0?{}:{comment:w(e.comment,4e3,!0)}}},xt=t=>{const e=R(t);return y(e,["itemId","partId","text","final","revision","parts"]),{itemId:u(e.itemId),partId:u(e.partId),text:w(e.text,1e5,!0),final:v(e.final),revision:k(e.revision,1),...e.parts===void 0?{}:{parts:F(e.parts)}}},tt=t=>{const e=R(t);y(e,["chatId","responseId","status","items","cancelRequested"]);const r=Y(e.items,20).map(xt);if(new Set(r.map(n=>n.itemId)).size!==r.length||r.reduce((n,a)=>n+[...a.text].length,0)>1e5)throw new Error("Invalid assistant data: output budget or identity");return{chatId:u(e.chatId),responseId:u(e.responseId),status:L(e.status),items:r,...e.cancelRequested===void 0?{}:{cancelRequested:v(e.cancelRequested)}}},et=t=>{const e=R(t);if(y(e,["id","role","content","persistent","responseId","cursor","createdAt","parts","feedback"]),e.role!=="assistant"&&e.role!=="user"||e.persistent!==!0)throw new Error("Invalid assistant data: persisted message");return{id:u(e.id),role:e.role,content:w(e.content,1e5,!0),persistent:!0,cursor:k(e.cursor),createdAt:w(e.createdAt,64),...e.responseId===void 0?{}:{responseId:u(e.responseId)},...e.parts===void 0?{}:{parts:F(e.parts)},...e.feedback===void 0?{}:{feedback:B(e.feedback)}}},Nt=t=>{const e=R(t),r=e.type;if(r==="response.snapshot")return y(e,["type","snapshot"]),{type:r,snapshot:tt(e.snapshot)};const n=u(e.responseId);if(r==="response.accepted")return y(e,["type","chatId","responseId","messageId","acceptedCursor"]),{type:r,responseId:n,chatId:u(e.chatId),messageId:u(e.messageId),acceptedCursor:k(e.acceptedCursor)};if(r==="response.state")return y(e,["type","chatId","responseId","status"]),{type:r,responseId:n,chatId:u(e.chatId),status:L(e.status)};if(r==="response.terminal"){y(e,["type","chatId","responseId","status","code"]);const p=L(e.status);if(!A(p))throw new Error("Invalid assistant data: terminal");return{type:r,responseId:n,chatId:u(e.chatId),status:p,...e.code===void 0?{}:{code:u(e.code)}}}if(r==="response.reconciled"){y(e,["type","chatId","responseId","messages"]);const p=Y(e.messages,200).map(et);if(p.some(i=>i.responseId!==n)||new Set(p.map(i=>i.id)).size!==p.length||p.reduce((i,c)=>i+[...c.content].length,0)>1e6)throw new Error("Invalid assistant data: response history");return{type:r,responseId:n,chatId:u(e.chatId),messages:p}}const a=u(e.itemId),s=u(e.partId),o=k(e.sequence,1),d=["type","responseId","itemId","partId","sequence"];if(r==="response.output_item.added")return y(e,d),{type:r,responseId:n,itemId:a,partId:s,sequence:o};if(r==="response.output_text.delta")return y(e,[...d,"delta"]),{type:r,responseId:n,itemId:a,partId:s,sequence:o,delta:w(e.delta,1e5,!0)};if(r==="response.output_item.done")return y(e,[...d,"text","final"]),{type:r,responseId:n,itemId:a,partId:s,sequence:o,text:w(e.text,1e5,!0),final:v(e.final)};throw new Error("Invalid assistant data: event type")},N=(t,e,r=t.messages)=>{const n={...t.responses,[e.responseId]:e};let a=r;if(r.length>l.historyMessages||r.reduce((i,c)=>i+c.content.length,0)>l.historyCharacters){a=[];let i=0;for(let c=r.length-1;c>=0&&a.length<l.historyMessages;c-=1){const g=r[c];if(i+=O(g.content,l.historyCharacters-i),i>l.historyCharacters)break;a.unshift(g)}}const s=new Set(a.map(i=>i.responseId)),o=new Set(Object.values(n).filter(i=>A(i.status)).slice(-20).map(i=>i.responseId)),d=Object.fromEntries(Object.entries(n).filter(([i,c])=>!A(c.status)||s.has(i)||o.has(i))),p=Object.values(d).filter(i=>!A(i.status));return{...t,threadId:e.chatId,messages:a,responses:d,...a.length<r.length?{historyTruncated:!0}:{},activeRunId:p.at(-1)?.responseId,status:p.length?"streaming":"idle"}},Ot=(t,e)=>({id:e.itemId,role:"assistant",content:e.text,artifacts:[],responseId:t.responseId,partId:e.partId,parts:e.parts,persistent:!1,intermediate:!!t.completedItems[e.itemId]&&!e.final,status:t.completedItems[e.itemId]||A(t.status)?"complete":"streaming"}),W=(t,e)=>{const r=t.findIndex(o=>o.responseId===e.responseId&&!o.persistent),n=t.filter(o=>o.responseId!==e.responseId||o.persistent);if(e.reconciled)return n;const a=e.items.map(o=>Ot(e,o)),s=r<0?n.length:Math.min(r,n.length);return[...n.slice(0,s),...a,...n.slice(s)]},Mt=(t,e)=>{const r=e.type==="response.snapshot"?e.snapshot.responseId:e.responseId,n=t.responses&&Object.hasOwn(t.responses,r)?t.responses[r]:void 0,a=e.type==="response.snapshot"?e.snapshot.chatId:"chatId"in e?e.chatId:n?.chatId;if(!a||t.threadId&&t.threadId!==a)throw new Error("Invalid assistant response: conversation mismatch");const s=n??{chatId:a,responseId:r,status:"queued",items:[],lastSequence:0,completedItems:{}};if(e.type==="response.accepted")return N(t,s,t.messages.map(c=>c.id===e.messageId?{...c,responseId:r,cursor:e.acceptedCursor,persistent:!0}:c));if(e.type==="response.reconciled"){const c=t.messages.filter(E=>E.responseId!==r||E.persistent),g=new Map(c.map(E=>[E.id,E]));for(const E of e.messages)g.set(E.id,{...E,artifacts:[],status:"complete"});return N(t,{...s,reconciled:!0},[...g.values()])}if(e.type==="response.snapshot"){if(A(s.status)&&s.status!==e.snapshot.status)return t;const c={...s,...e.snapshot,completedItems:Object.fromEntries(e.snapshot.items.map(g=>[g.itemId,!0]))};return N(t,c,W(t.messages,c))}if(e.type==="response.state")return A(s.status)?t:N(t,{...s,status:e.status});if(e.type==="response.terminal"){if(A(s.status)&&s.status!==e.status)return t;const c={...s,status:e.status},g=t.messages.map(E=>E.responseId!==r?E:{...E,status:"complete",...e.status==="failed"?{error:{code:e.code??"AI_RUN_FAILED",message:"本次处理失败,请重试",retryable:!0}}:{}});return N(t,c,g)}if(A(s.status)||e.sequence<=s.lastSequence)return t;const o=s.items.findIndex(c=>c.itemId===e.itemId);let d;if(e.type==="response.output_item.added"){if(o>=0||s.items.length>=20)throw new Error("Invalid assistant response: duplicate item or item budget");d={itemId:e.itemId,partId:e.partId,text:"",final:!1,revision:1}}else{const c=s.items[o];if(!c||c.partId!==e.partId||s.completedItems[e.itemId])throw new Error("Invalid assistant response: item order");d=e.type==="response.output_text.delta"?{...c,text:c.text+e.delta}:{...c,text:e.text,final:e.final}}const p=o<0?[...s.items,d]:s.items.map((c,g)=>g===o?d:c);if(p.reduce((c,g)=>c+[...g.text].length,0)>1e5)throw new Error("Invalid assistant response: text budget");const i={...s,status:"running",lastSequence:e.sequence,items:p,completedItems:e.type==="response.output_item.done"?{...s.completedItems,[e.itemId]:!0}:s.completedItems};return N(t,i,W(t.messages,i))},D=t=>typeof t=="object"&&t!==null&&!Array.isArray(t),S=(t,e)=>{if(Object.keys(t).some(r=>!e.has(r)))throw new Error("Invalid assistant event: unsupported field")},f=(t,e,r=l.identifierCharacters)=>{const n=typeof t=="string"?O(t,r):0;if(typeof t!="string"||!t.trim()||n>r)throw new Error(`Invalid assistant event: ${e}`);return t},jt=t=>{if(!D(t)||typeof t.type!="string")throw new Error("Invalid assistant event: data");if(t.type.startsWith("response."))return Nt(t);switch(t.type){case"message.start":return S(t,new Set(["type","runId","messageId"])),{type:t.type,runId:f(t.runId,"runId"),messageId:f(t.messageId,"messageId")};case"message.delta":if(S(t,new Set(["type","messageId","delta"])),typeof t.delta!="string")throw new Error("Invalid assistant event: delta");return{type:t.type,messageId:f(t.messageId,"messageId"),delta:t.delta};case"message.replace":return S(t,new Set(["type","messageId","content"])),{type:t.type,messageId:f(t.messageId,"messageId"),content:f(t.content,"content",l.messageCharacters)};case"message.complete":return S(t,new Set(["type","messageId"])),{type:t.type,messageId:f(t.messageId,"messageId")};case"artifact":return S(t,new Set(["type","messageId","artifact"])),{type:t.type,messageId:f(t.messageId,"messageId"),artifact:z(t.artifact)};case"run.progress":return S(t,new Set(["type","runId","message"])),{type:t.type,runId:f(t.runId,"runId"),message:f(t.message,"message",l.messageCharacters)};case"error":if(S(t,new Set(["type","code","message","retryable","requestId"])),typeof t.retryable!="boolean")throw new Error("Invalid assistant event: retryable");return{type:t.type,code:f(t.code,"code"),message:f(t.message,"message",l.messageCharacters),retryable:t.retryable,requestId:t.requestId===void 0?void 0:f(t.requestId,"requestId")};case"run.cancelled":return S(t,new Set(["type","runId"])),{type:t.type,runId:t.runId===void 0?void 0:f(t.runId,"runId")};case"run.complete":return S(t,new Set(["type","runId","threadId"])),{type:t.type,runId:f(t.runId,"runId"),threadId:f(t.threadId,"threadId")};default:throw new Error("Invalid assistant event: unsupported type")}},vt=t=>{try{return jt(t)}catch(e){throw e instanceof Error&&(e.message.startsWith("Invalid assistant event:")||e.message.startsWith("Invalid Make AI Artifact:"))?e:new Error("Invalid assistant event: data")}},Kt=t=>{if(!D(t))throw new Error("Invalid assistant conversation snapshot: data");if(S(t,new Set(["threadId","messages","nextCursor","hasMore"])),!Array.isArray(t.messages)||t.messages.length>l.historyMessages)throw new Error("Invalid assistant conversation snapshot: messages");const e=new Set;let r=0,n=0;return{messages:t.messages.map(s=>{if(!D(s))throw new Error("Invalid assistant conversation snapshot: message");S(s,new Set(["id","role","content","artifacts","responseId","parts","persistent","cursor","createdAt","feedback"]));const o=f(s.id,"messageId");if(e.has(o))throw new Error("Invalid assistant conversation snapshot: duplicate message id");if(e.add(o),s.role!=="assistant"&&s.role!=="user")throw new Error("Invalid assistant conversation snapshot: role");const d=s.role,p=typeof s.content=="string"?O(s.content,l.messageCharacters):0;if(typeof s.content!="string"||p>l.messageCharacters)throw new Error("Invalid assistant conversation snapshot: content");if(r+=O(s.content,l.historyCharacters-r),r>l.historyCharacters)throw new Error("Invalid assistant conversation snapshot: content budget");if(s.artifacts!==void 0&&(!Array.isArray(s.artifacts)||s.artifacts.length>l.artifactsPerRun))throw new Error("Invalid assistant conversation snapshot: artifacts");const i=(s.artifacts??[]).map(z),c=new Set;for(const g of i){if(c.has(g.id))throw new Error("Invalid assistant conversation snapshot: duplicate artifact id");c.add(g.id)}if(n+=i.length,n>l.historyArtifacts)throw new Error("Invalid assistant conversation snapshot: artifact budget");return{id:o,role:d,content:s.content,artifacts:i,status:"complete",...s.responseId===void 0?{}:{responseId:f(s.responseId,"responseId")},...s.parts===void 0?{}:{parts:F(s.parts)},...s.feedback===void 0?{}:{feedback:B(s.feedback)},...s.persistent===void 0?{}:{persistent:v(s.persistent)},...s.cursor===void 0?{}:{cursor:k(s.cursor)},...s.createdAt===void 0?{}:{createdAt:f(s.createdAt,"createdAt")}}}),status:"idle",threadId:t.threadId===void 0?void 0:f(t.threadId,"threadId")}},Pt=t=>t===void 0?{messages:[],status:"idle"}:Kt(t),qt=(t,e)=>({...t,error:void 0,progress:void 0,status:"streaming",messages:[...t.messages,{id:e.id,role:"user",content:e.content,...e.parts===void 0?{}:{parts:e.parts},artifacts:[],status:"complete"}]}),P=(t,e,r)=>({...t,messages:t.messages.map(n=>n.id===e?r(n):n)}),rt=t=>{const e=t.slice(-l.progressStepsPerRun),r=[];let n=0;for(let a=e.length-1;a>=0;a-=1){const s=e[a],o=O(s,l.progressCharactersPerRun-n);if(n+o>l.progressCharactersPerRun)break;n+=o,r.unshift(s)}return r},Yt=(t,e)=>{let r=-1;for(let n=t.length-1;n>=0;n-=1){const a=t[n];if(a.role==="assistant"&&a.status==="streaming"){r=n;break}}return r<0?t:t.map((n,a)=>a===r?{...n,progressSteps:rt([...n.progressSteps??[],e])}:n)},Ft=(t,e)=>{if(e.type.startsWith("response."))return Mt(t,e);switch(e.type){case"message.start":{const r=t.progress?.runId===e.runId?t.progress.steps:void 0;return{...t,activeRunId:e.runId,error:void 0,progress:t.progress?.runId===e.runId?t.progress:void 0,status:"streaming",messages:[...t.messages,{id:e.messageId,role:"assistant",content:"",artifacts:[],progressSteps:r,status:"streaming"}]}}case"message.delta":return P(t,e.messageId,r=>({...r,content:`${r.content}${e.delta}`}));case"message.replace":return P(t,e.messageId,r=>({...r,content:e.content}));case"artifact":return P(t,e.messageId,r=>({...r,artifacts:[...r.artifacts,e.artifact]}));case"message.complete":return P(t,e.messageId,r=>({...r,status:"complete"}));case"run.progress":{const r=rt(t.progress?.runId===e.runId?[...t.progress.steps,e.message]:[e.message]);return{...t,messages:Yt(t.messages,e.message),progress:{runId:e.runId,message:e.message,steps:r}}}case"error":{const r={code:e.code,message:e.message,retryable:e.retryable,requestId:e.requestId};return{...t,activeRunId:void 0,error:r,progress:void 0,messages:t.messages.map(n=>n.status==="streaming"?{...n,error:r,status:"complete"}:n),status:"error"}}case"run.cancelled":return{...t,activeRunId:void 0,progress:void 0,status:"idle",messages:t.messages.map(r=>r.status==="streaming"?{...r,status:"complete"}:r)};case"run.complete":return{...t,activeRunId:void 0,error:void 0,progress:void 0,messages:t.messages.map(r=>r.status==="streaming"?{...r,status:"complete"}:r),status:"idle",threadId:e.threadId}}return t};exports.MAKE_AI_ARTIFACT_KINDS=H;exports.MAKE_AI_ARTIFACT_LIMITS=m;exports.MAKE_AI_ARTIFACT_SCHEMA_VERSION="1.0";exports.MAKE_AI_CONVERSATION_LIMITS=l;exports.appendUserMessage=qt;exports.countCodePointsUpTo=O;exports.createAssistantConversationState=Pt;exports.isResponseTerminal=A;exports.parseArtifact=z;exports.parseAssistantEvent=vt;exports.parseContentParts=F;exports.parseFeedback=B;exports.parseResponseSnapshot=tt;exports.parseStoredMessage=et;exports.protocolArray=Y;exports.protocolBoolean=v;exports.protocolId=u;exports.protocolInteger=k;exports.protocolKeys=y;exports.protocolRecord=R;exports.protocolText=w;exports.reduceAssistantEvent=Ft;exports.validateArtifact=Z;
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import type { MakeAssistantHostContext } from "./types.js";
|
|
2
|
+
export interface AssistantMedia {
|
|
3
|
+
contentRef: string;
|
|
4
|
+
contentType: string;
|
|
5
|
+
sizeBytes: number;
|
|
6
|
+
digestSha256: string;
|
|
7
|
+
}
|
|
8
|
+
export type AssistantContentPart = {
|
|
9
|
+
id?: string;
|
|
10
|
+
kind: "text";
|
|
11
|
+
text: string;
|
|
12
|
+
} | {
|
|
13
|
+
id?: string;
|
|
14
|
+
kind: "image" | "file" | "audio" | "video";
|
|
15
|
+
name?: string;
|
|
16
|
+
media: AssistantMedia;
|
|
17
|
+
};
|
|
18
|
+
export interface AssistantFeedback {
|
|
19
|
+
id: string;
|
|
20
|
+
rating: "like" | "dislike" | "none";
|
|
21
|
+
revision: number;
|
|
22
|
+
reason?: string;
|
|
23
|
+
comment?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface AssistantChat {
|
|
26
|
+
chatId: string;
|
|
27
|
+
appKey: string;
|
|
28
|
+
agentId: string;
|
|
29
|
+
title: string;
|
|
30
|
+
status: "active" | "deleted";
|
|
31
|
+
revision: number;
|
|
32
|
+
pinned: boolean;
|
|
33
|
+
pinnedAt?: string | null;
|
|
34
|
+
createdAt: string;
|
|
35
|
+
lastActivityAt: string;
|
|
36
|
+
}
|
|
37
|
+
export interface AssistantChatPage {
|
|
38
|
+
chats: AssistantChat[];
|
|
39
|
+
nextCursor: string;
|
|
40
|
+
hasMore: boolean;
|
|
41
|
+
}
|
|
42
|
+
export interface AssistantAgent {
|
|
43
|
+
agentId: string;
|
|
44
|
+
appKey: string;
|
|
45
|
+
name: string;
|
|
46
|
+
}
|
|
47
|
+
export type AssistantResponseStatus = "queued" | "dispatched" | "running" | "completed" | "failed" | "cancelled";
|
|
48
|
+
export interface AssistantOutputItem {
|
|
49
|
+
itemId: string;
|
|
50
|
+
partId: string;
|
|
51
|
+
text: string;
|
|
52
|
+
final: boolean;
|
|
53
|
+
revision: number;
|
|
54
|
+
parts?: AssistantContentPart[];
|
|
55
|
+
}
|
|
56
|
+
export interface AssistantResponseSnapshot {
|
|
57
|
+
chatId: string;
|
|
58
|
+
responseId: string;
|
|
59
|
+
status: AssistantResponseStatus;
|
|
60
|
+
items: AssistantOutputItem[];
|
|
61
|
+
cancelRequested?: boolean;
|
|
62
|
+
}
|
|
63
|
+
export interface AssistantUpload {
|
|
64
|
+
id: string;
|
|
65
|
+
status: "uploading" | "ready" | "cancelled";
|
|
66
|
+
name: string;
|
|
67
|
+
contentType: string;
|
|
68
|
+
sizeBytes: number;
|
|
69
|
+
partSize: number;
|
|
70
|
+
completedParts: number[];
|
|
71
|
+
content?: {
|
|
72
|
+
kind: "reference";
|
|
73
|
+
contentRef: string;
|
|
74
|
+
sizeBytes: number;
|
|
75
|
+
digestSha256: string;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
export interface AssistantStoredMessage {
|
|
79
|
+
id: string;
|
|
80
|
+
role: "user" | "assistant";
|
|
81
|
+
content: string;
|
|
82
|
+
persistent: true;
|
|
83
|
+
responseId?: string;
|
|
84
|
+
cursor: number;
|
|
85
|
+
createdAt: string;
|
|
86
|
+
parts?: AssistantContentPart[];
|
|
87
|
+
feedback?: AssistantFeedback;
|
|
88
|
+
}
|
|
89
|
+
export interface AssistantChatRef {
|
|
90
|
+
chatId: string;
|
|
91
|
+
}
|
|
92
|
+
export interface AssistantResponseRef extends AssistantChatRef {
|
|
93
|
+
responseId: string;
|
|
94
|
+
}
|
|
95
|
+
export interface AssistantUploadRef extends AssistantChatRef {
|
|
96
|
+
uploadId: string;
|
|
97
|
+
}
|
|
98
|
+
export interface AssistantChatCreate {
|
|
99
|
+
requestId: string;
|
|
100
|
+
title?: string;
|
|
101
|
+
}
|
|
102
|
+
export interface AssistantChatPatch extends AssistantChatRef {
|
|
103
|
+
expectedRevision: number;
|
|
104
|
+
title?: string;
|
|
105
|
+
pinned?: boolean;
|
|
106
|
+
}
|
|
107
|
+
export interface AssistantFeedbackWrite extends AssistantChatRef {
|
|
108
|
+
messageId: string;
|
|
109
|
+
requestId: string;
|
|
110
|
+
rating: AssistantFeedback["rating"];
|
|
111
|
+
reason?: string;
|
|
112
|
+
comment?: string;
|
|
113
|
+
}
|
|
114
|
+
export interface AssistantUploadStart extends AssistantChatRef {
|
|
115
|
+
fileId: string;
|
|
116
|
+
name: string;
|
|
117
|
+
contentType: string;
|
|
118
|
+
sizeBytes: number;
|
|
119
|
+
digestSha256?: string;
|
|
120
|
+
}
|
|
121
|
+
export interface AssistantCallOptions {
|
|
122
|
+
signal?: AbortSignal;
|
|
123
|
+
}
|
|
124
|
+
export interface AssistantManagementTransport {
|
|
125
|
+
scopeKey?(context: MakeAssistantHostContext): string;
|
|
126
|
+
listAgents?(context: MakeAssistantHostContext, options?: AssistantCallOptions): Promise<AssistantAgent[]>;
|
|
127
|
+
listConversations?(context: MakeAssistantHostContext, page?: {
|
|
128
|
+
cursor?: string;
|
|
129
|
+
limit?: number;
|
|
130
|
+
}, options?: AssistantCallOptions): Promise<AssistantChatPage>;
|
|
131
|
+
createConversation?(context: MakeAssistantHostContext, input: AssistantChatCreate, options?: AssistantCallOptions): Promise<AssistantChat>;
|
|
132
|
+
getConversation?(context: MakeAssistantHostContext, input: AssistantChatRef, options?: AssistantCallOptions): Promise<AssistantChat>;
|
|
133
|
+
updateConversation?(context: MakeAssistantHostContext, input: AssistantChatPatch, options?: AssistantCallOptions): Promise<AssistantChat>;
|
|
134
|
+
deleteConversation?(context: MakeAssistantHostContext, input: AssistantChatRef & {
|
|
135
|
+
expectedRevision: number;
|
|
136
|
+
}, options?: AssistantCallOptions): Promise<void>;
|
|
137
|
+
getResponse?(context: MakeAssistantHostContext, input: AssistantResponseRef, options?: AssistantCallOptions): Promise<AssistantResponseSnapshot>;
|
|
138
|
+
cancelResponse?(context: MakeAssistantHostContext, input: AssistantResponseRef, options?: AssistantCallOptions): Promise<AssistantResponseSnapshot>;
|
|
139
|
+
setFeedback?(context: MakeAssistantHostContext, input: AssistantFeedbackWrite, options?: AssistantCallOptions): Promise<AssistantFeedback>;
|
|
140
|
+
startUpload?(context: MakeAssistantHostContext, input: AssistantUploadStart, options?: AssistantCallOptions): Promise<AssistantUpload>;
|
|
141
|
+
getUpload?(context: MakeAssistantHostContext, input: AssistantUploadRef, options?: AssistantCallOptions): Promise<AssistantUpload>;
|
|
142
|
+
uploadPart?(context: MakeAssistantHostContext, input: AssistantUploadRef & {
|
|
143
|
+
part: number;
|
|
144
|
+
bytes: Uint8Array;
|
|
145
|
+
}, options?: AssistantCallOptions): Promise<void>;
|
|
146
|
+
completeUpload?(context: MakeAssistantHostContext, input: AssistantUploadRef, options?: AssistantCallOptions): Promise<AssistantUpload>;
|
|
147
|
+
readContent?(context: MakeAssistantHostContext, input: AssistantChatRef & {
|
|
148
|
+
contentRef: string;
|
|
149
|
+
}, options?: AssistantCallOptions): Promise<Uint8Array>;
|
|
150
|
+
}
|
|
151
|
+
export type AssistantResponseEvent = {
|
|
152
|
+
type: "response.accepted";
|
|
153
|
+
chatId: string;
|
|
154
|
+
responseId: string;
|
|
155
|
+
messageId: string;
|
|
156
|
+
acceptedCursor: number;
|
|
157
|
+
} | {
|
|
158
|
+
type: "response.state";
|
|
159
|
+
chatId: string;
|
|
160
|
+
responseId: string;
|
|
161
|
+
status: AssistantResponseStatus;
|
|
162
|
+
} | {
|
|
163
|
+
type: "response.output_item.added";
|
|
164
|
+
responseId: string;
|
|
165
|
+
itemId: string;
|
|
166
|
+
partId: string;
|
|
167
|
+
sequence: number;
|
|
168
|
+
} | {
|
|
169
|
+
type: "response.output_text.delta";
|
|
170
|
+
responseId: string;
|
|
171
|
+
itemId: string;
|
|
172
|
+
partId: string;
|
|
173
|
+
sequence: number;
|
|
174
|
+
delta: string;
|
|
175
|
+
} | {
|
|
176
|
+
type: "response.output_item.done";
|
|
177
|
+
responseId: string;
|
|
178
|
+
itemId: string;
|
|
179
|
+
partId: string;
|
|
180
|
+
sequence: number;
|
|
181
|
+
text: string;
|
|
182
|
+
final: boolean;
|
|
183
|
+
} | {
|
|
184
|
+
type: "response.snapshot";
|
|
185
|
+
snapshot: AssistantResponseSnapshot;
|
|
186
|
+
} | {
|
|
187
|
+
type: "response.reconciled";
|
|
188
|
+
chatId: string;
|
|
189
|
+
responseId: string;
|
|
190
|
+
messages: AssistantStoredMessage[];
|
|
191
|
+
} | {
|
|
192
|
+
type: "response.terminal";
|
|
193
|
+
chatId: string;
|
|
194
|
+
responseId: string;
|
|
195
|
+
status: "completed" | "failed" | "cancelled";
|
|
196
|
+
code?: string;
|
|
197
|
+
};
|
|
198
|
+
export declare const isResponseTerminal: (status: AssistantResponseStatus) => status is "completed" | "failed" | "cancelled";
|
|
199
|
+
export declare const protocolRecord: (value: unknown) => Record<string, unknown>;
|
|
200
|
+
export declare const protocolText: (value: unknown, maximum?: number, empty?: boolean) => string;
|
|
201
|
+
export declare const protocolId: (value: unknown) => string;
|
|
202
|
+
export declare const protocolInteger: (value: unknown, minimum?: number, maximum?: number) => number;
|
|
203
|
+
export declare const protocolBoolean: (value: unknown) => boolean;
|
|
204
|
+
export declare const protocolArray: (value: unknown, maximum: number) => unknown[];
|
|
205
|
+
export declare const protocolKeys: (value: Record<string, unknown>, keys: string[]) => void;
|
|
206
|
+
export declare const parseResponseStatus: (value: unknown) => AssistantResponseStatus;
|
|
207
|
+
export declare const parseContentParts: (value: unknown) => AssistantContentPart[];
|
|
208
|
+
export declare const parseFeedback: (raw: unknown) => AssistantFeedback;
|
|
209
|
+
export declare const parseOutputItem: (raw: unknown) => AssistantOutputItem;
|
|
210
|
+
export declare const parseResponseSnapshot: (raw: unknown) => AssistantResponseSnapshot;
|
|
211
|
+
export declare const parseStoredMessage: (raw: unknown) => AssistantStoredMessage;
|
|
212
|
+
export declare const parseResponseEvent: (raw: unknown) => AssistantResponseEvent;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import type { ArtifactCapabilities, MakeAiArtifact, MakeAssistantHostContext } from "./types.js";
|
|
2
|
+
import { type AssistantContentPart, type AssistantFeedback, type AssistantManagementTransport, type AssistantResponseEvent, type AssistantResponseRef } from "./conversation-management.js";
|
|
3
|
+
import { type AssistantResponseState } from "./response-state.js";
|
|
2
4
|
export interface AssistantRunRequest {
|
|
3
5
|
threadId?: string;
|
|
4
6
|
message: {
|
|
5
7
|
id: string;
|
|
6
8
|
content: string;
|
|
9
|
+
parts?: AssistantContentPart[];
|
|
7
10
|
};
|
|
8
11
|
context: MakeAssistantHostContext;
|
|
9
12
|
capabilities: ArtifactCapabilities;
|
|
@@ -16,30 +19,48 @@ export interface AssistantRegenerateRequest extends AssistantRunRequest {
|
|
|
16
19
|
}
|
|
17
20
|
export interface AssistantTransportOptions {
|
|
18
21
|
signal?: AbortSignal;
|
|
22
|
+
threadId?: string;
|
|
23
|
+
cursor?: number;
|
|
19
24
|
}
|
|
20
25
|
export interface AssistantTransportFeatures {
|
|
21
26
|
history: boolean;
|
|
22
27
|
newConversation: boolean;
|
|
23
28
|
regeneration?: boolean;
|
|
24
29
|
remoteCancellation: boolean;
|
|
30
|
+
conversationManagement?: boolean;
|
|
31
|
+
feedback?: boolean;
|
|
32
|
+
attachments?: boolean;
|
|
33
|
+
modelInputKinds?: ReadonlyArray<AssistantContentPart["kind"]>;
|
|
25
34
|
}
|
|
26
35
|
export interface AssistantConversationSnapshotMessage {
|
|
27
36
|
id: string;
|
|
28
37
|
role: "assistant" | "user";
|
|
29
38
|
content: string;
|
|
30
39
|
artifacts?: ReadonlyArray<MakeAiArtifact>;
|
|
40
|
+
responseId?: string;
|
|
41
|
+
parts?: AssistantContentPart[];
|
|
42
|
+
persistent?: boolean;
|
|
43
|
+
cursor?: number;
|
|
44
|
+
createdAt?: string;
|
|
45
|
+
feedback?: AssistantFeedback;
|
|
31
46
|
}
|
|
32
47
|
export interface AssistantConversationSnapshot {
|
|
33
48
|
threadId?: string;
|
|
34
49
|
messages: ReadonlyArray<AssistantConversationSnapshotMessage>;
|
|
50
|
+
nextCursor?: number;
|
|
51
|
+
hasMore?: boolean;
|
|
35
52
|
}
|
|
36
|
-
export interface AssistantTransport {
|
|
53
|
+
export interface AssistantTransport extends AssistantManagementTransport {
|
|
37
54
|
readonly features?: Partial<AssistantTransportFeatures>;
|
|
38
55
|
loadConversation?(context: MakeAssistantHostContext, options?: AssistantTransportOptions): Promise<AssistantConversationSnapshot>;
|
|
39
56
|
run(request: AssistantRunRequest, options?: AssistantTransportOptions): AsyncIterable<AssistantEvent>;
|
|
40
57
|
regenerate?(request: AssistantRegenerateRequest, options?: AssistantTransportOptions): AsyncIterable<AssistantEvent>;
|
|
58
|
+
watchResponse?(context: MakeAssistantHostContext, response: AssistantResponseRef & {
|
|
59
|
+
cursor?: string;
|
|
60
|
+
historyCursor?: number;
|
|
61
|
+
}, options?: AssistantTransportOptions): AsyncIterable<AssistantEvent>;
|
|
41
62
|
}
|
|
42
|
-
export type AssistantEvent = {
|
|
63
|
+
export type AssistantEvent = AssistantResponseEvent | {
|
|
43
64
|
type: "message.start";
|
|
44
65
|
runId: string;
|
|
45
66
|
messageId: string;
|
|
@@ -85,6 +106,14 @@ export interface AssistantMessage {
|
|
|
85
106
|
artifacts: MakeAiArtifact[];
|
|
86
107
|
progressSteps?: string[];
|
|
87
108
|
status: "complete" | "streaming";
|
|
109
|
+
responseId?: string;
|
|
110
|
+
partId?: string;
|
|
111
|
+
parts?: AssistantContentPart[];
|
|
112
|
+
persistent?: boolean;
|
|
113
|
+
intermediate?: boolean;
|
|
114
|
+
cursor?: number;
|
|
115
|
+
createdAt?: string;
|
|
116
|
+
feedback?: AssistantFeedback;
|
|
88
117
|
}
|
|
89
118
|
export interface AssistantConversationError {
|
|
90
119
|
code: string;
|
|
@@ -103,10 +132,13 @@ export interface AssistantConversationState {
|
|
|
103
132
|
};
|
|
104
133
|
status: "idle" | "streaming" | "error";
|
|
105
134
|
threadId?: string;
|
|
135
|
+
responses?: Record<string, AssistantResponseState>;
|
|
136
|
+
historyTruncated?: boolean;
|
|
106
137
|
}
|
|
107
138
|
export declare const createAssistantConversationState: (snapshot?: AssistantConversationSnapshot) => AssistantConversationState;
|
|
108
139
|
export declare const appendUserMessage: (state: AssistantConversationState, message: {
|
|
109
140
|
id: string;
|
|
110
141
|
content: string;
|
|
142
|
+
parts?: AssistantContentPart[];
|
|
111
143
|
}) => AssistantConversationState;
|
|
112
144
|
export declare const reduceAssistantEvent: (state: AssistantConversationState, event: AssistantEvent) => AssistantConversationState;
|
package/dist/core/index.d.ts
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AssistantConversationState } from "./conversation.js";
|
|
2
|
+
import { type AssistantResponseEvent, type AssistantResponseSnapshot } from "./conversation-management.js";
|
|
3
|
+
export interface AssistantResponseState extends AssistantResponseSnapshot {
|
|
4
|
+
lastSequence: number;
|
|
5
|
+
completedItems: Record<string, boolean>;
|
|
6
|
+
reconciled?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare const reduceResponseEvent: (state: AssistantConversationState, event: AssistantResponseEvent) => AssistantConversationState;
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./conversation-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./conversation-Cvh-IVRV.cjs"),p=r=>{const e=new Set;for(const t of r){if(!t.id.trim())throw new Error("Artifact template id must not be empty");if(e.has(t.id))throw new Error(`Duplicate artifact template id: ${t.id}`);if(t.kinds.length===0)throw new Error(`Artifact template must support at least one kind: ${t.id}`);if(t.kinds.some(n=>!i.MAKE_AI_ARTIFACT_KINDS.includes(n)))throw new Error(`Unsupported Artifact template kind: ${t.id}`);if(t.priority!==void 0&&!Number.isFinite(t.priority))throw new Error(`Artifact template priority must be finite: ${t.id}`);if(typeof t.render!="function")throw new Error(`Artifact template render must be a function: ${t.id}`);if(t.canRender!==void 0&&typeof t.canRender!="function")throw new Error(`Artifact template canRender must be a function: ${t.id}`);e.add(t.id)}},c=(r=[])=>{p(r);const e=r.map(t=>Object.freeze({...t,kinds:Object.freeze([...t.kinds])}));return Object.freeze({templates:Object.freeze(e)})},d=(r,e)=>c([...r.templates,...e]),A=(r,e,t)=>r.kinds.includes(e.kind)&&(r.canRender?.(e,t)??!0),f=(r,e,t)=>{const n=e.presentation?.template;if(n){const a=r.templates.find(s=>s.id===n&&A(s,e,t));if(a)return{template:a,reason:"requested"}}const o=r.templates.map((a,s)=>({template:a,registrationIndex:s})).filter(({template:a})=>A(a,e,t)).sort((a,s)=>(s.template.priority??0)-(a.template.priority??0)||a.registrationIndex-s.registrationIndex);return o[0]?{template:o[0].template,reason:"priority"}:void 0},l=r=>({artifactSchemaVersions:[i.MAKE_AI_ARTIFACT_SCHEMA_VERSION],artifactKinds:Array.from(new Set(r.templates.flatMap(e=>e.kinds))).sort(),templates:r.templates.map(e=>e.id).sort()});exports.MAKE_AI_ARTIFACT_KINDS=i.MAKE_AI_ARTIFACT_KINDS;exports.MAKE_AI_ARTIFACT_LIMITS=i.MAKE_AI_ARTIFACT_LIMITS;exports.MAKE_AI_ARTIFACT_SCHEMA_VERSION=i.MAKE_AI_ARTIFACT_SCHEMA_VERSION;exports.MAKE_AI_CONVERSATION_LIMITS=i.MAKE_AI_CONVERSATION_LIMITS;exports.appendUserMessage=i.appendUserMessage;exports.createAssistantConversationState=i.createAssistantConversationState;exports.parseArtifact=i.parseArtifact;exports.parseAssistantEvent=i.parseAssistantEvent;exports.reduceAssistantEvent=i.reduceAssistantEvent;exports.validateArtifact=i.validateArtifact;exports.createArtifactCapabilities=l;exports.createArtifactTemplateRegistry=c;exports.extendArtifactTemplateRegistry=d;exports.resolveArtifactTemplate=f;
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { t as p, q as d } from "./conversation-CZfbgCXd.js";
|
|
2
|
+
import { s as E, M as T, o as _, n as b, u as R, l as y, r as M, v as S } from "./conversation-CZfbgCXd.js";
|
|
3
3
|
const c = (r) => {
|
|
4
4
|
const e = /* @__PURE__ */ new Set();
|
|
5
5
|
for (const t of r) {
|
|
@@ -51,10 +51,10 @@ export {
|
|
|
51
51
|
E as MAKE_AI_ARTIFACT_LIMITS,
|
|
52
52
|
p as MAKE_AI_ARTIFACT_SCHEMA_VERSION,
|
|
53
53
|
T as MAKE_AI_CONVERSATION_LIMITS,
|
|
54
|
-
|
|
54
|
+
_ as appendUserMessage,
|
|
55
55
|
u as createArtifactCapabilities,
|
|
56
56
|
f as createArtifactTemplateRegistry,
|
|
57
|
-
|
|
57
|
+
b as createAssistantConversationState,
|
|
58
58
|
l as extendArtifactTemplateRegistry,
|
|
59
59
|
R as parseArtifact,
|
|
60
60
|
y as parseAssistantEvent,
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type AssistantChat, type AssistantChatPage, type AssistantContentPart, type AssistantResponseRef, type AssistantUpload } from "../core/conversation-management.js";
|
|
2
|
+
import type { AssistantConversationSnapshot, AssistantRunRequest } from "../core/conversation.js";
|
|
3
|
+
export declare const uuid: (raw: unknown) => string;
|
|
4
|
+
export declare const filename: (raw: unknown) => string;
|
|
5
|
+
export declare const readChat: (raw: unknown, scope: {
|
|
6
|
+
appKey: string;
|
|
7
|
+
agentId: string;
|
|
8
|
+
}, chatId?: string) => AssistantChat;
|
|
9
|
+
export declare const readChatPage: (raw: unknown, scope: {
|
|
10
|
+
appKey: string;
|
|
11
|
+
agentId: string;
|
|
12
|
+
}) => AssistantChatPage;
|
|
13
|
+
export declare const readHistory: (raw: unknown, chatId: string, cursor: number) => AssistantConversationSnapshot;
|
|
14
|
+
export declare const readResponse: (raw: unknown, ref: AssistantResponseRef) => import("../index.js").AssistantResponseSnapshot;
|
|
15
|
+
export declare const readUpload: (raw: unknown, id?: string) => AssistantUpload;
|
|
16
|
+
export type MessageInput = {
|
|
17
|
+
chatId: string;
|
|
18
|
+
messageId: string;
|
|
19
|
+
text: string;
|
|
20
|
+
parts?: never;
|
|
21
|
+
} | {
|
|
22
|
+
chatId: string;
|
|
23
|
+
messageId: string;
|
|
24
|
+
parts: AssistantContentPart[];
|
|
25
|
+
text?: never;
|
|
26
|
+
};
|
|
27
|
+
export declare const messageInput: (request: AssistantRunRequest) => MessageInput;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AssistantEvent, AssistantConversationSnapshot } from "../core/conversation.js";
|
|
2
|
+
import { type AssistantResponseRef, type AssistantResponseSnapshot } from "../core/conversation-management.js";
|
|
3
|
+
import type { MakeAppAssistantEventSourceFactory } from "../make-app.js";
|
|
4
|
+
export interface ResponseStreamDependencies {
|
|
5
|
+
eventSourceFactory: MakeAppAssistantEventSourceFactory;
|
|
6
|
+
getResponse(ref: AssistantResponseRef, signal?: AbortSignal): Promise<AssistantResponseSnapshot>;
|
|
7
|
+
loadHistory(ref: AssistantResponseRef, cursor: number, signal?: AbortSignal): Promise<AssistantConversationSnapshot>;
|
|
8
|
+
maxEventCharacters: number;
|
|
9
|
+
reconnectDelayMs: number;
|
|
10
|
+
}
|
|
11
|
+
export declare const eventQueue: <T>() => {
|
|
12
|
+
push(value: T): void;
|
|
13
|
+
fail(error: unknown): void;
|
|
14
|
+
close(): void;
|
|
15
|
+
next(): Promise<IteratorResult<T>>;
|
|
16
|
+
};
|
|
17
|
+
export declare function responseEvents(ref: AssistantResponseRef & {
|
|
18
|
+
cursor?: string;
|
|
19
|
+
historyCursor?: number;
|
|
20
|
+
}, dependencies: ResponseStreamDependencies, signal?: AbortSignal): AsyncGenerator<AssistantEvent>;
|
package/dist/make-app.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w=require("./sse.cjs"),I=require("./conversation-Cv1wdvCR.cjs"),m=100,M={AI_AGENT_UNAVAILABLE:"当前 App 尚未配置可用的 AI 助手。",AI_APP_UNAVAILABLE:"当前 App 暂不可用。",AI_AUTH_EXPIRED:"登录已失效,请重新登录。",AI_AUTH_REQUIRED:"登录已失效,请重新登录。",AI_FORBIDDEN:"当前账号无权使用该 AI 助手。",AI_RUN_FAILED:"本次 AI 处理失败,请重试。",AI_UPSTREAM_ERROR:"AI 服务暂时不可用,请稍后重试。"},u=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),h=(e,a,i=I.MAKE_AI_CONVERSATION_LIMITS.identifierCharacters)=>{if(typeof e!="string"||!e.trim()||I.countCodePointsUpTo(e,i)>i)throw new Error(`Invalid Make App assistant response: ${a}`);return e},_=e=>{if(!u(e))throw new Error("Invalid Make App assistant response: locate");return{chatId:h(e.chatId,"chatId")}},v=e=>{if(!u(e))throw new Error("Invalid Make App assistant response: send");const a=e.acceptedCursor;if(!Number.isSafeInteger(a)||Number(a)<0)throw new Error("Invalid Make App assistant response: acceptedCursor");return{acceptedCursor:a,chatId:h(e.chatId,"chatId"),responseId:h(e.responseId,"responseId")}},S=(e,a,i)=>{if(!u(e)||!Array.isArray(e.messages)||e.messages.length>i)throw new Error("Invalid Make App assistant response: history");const c=new Set;let o=0;const t=e.messages.map(s=>{if(!u(s))throw new Error("Invalid Make App assistant response: history message");if(s.role!=="user"&&s.role!=="assistant")throw new Error("Invalid Make App assistant response: history role");const r=s.role;if(!Number.isSafeInteger(s.cursor)||Number(s.cursor)<0)throw new Error("Invalid Make App assistant response: history cursor");const p=`history-${a}-${String(s.cursor)}`;if(c.has(p))throw new Error("Invalid Make App assistant response: duplicate history cursor");c.add(p);const d=h(s.text,"history text",I.MAKE_AI_CONVERSATION_LIMITS.messageCharacters);if(o+=I.countCodePointsUpTo(d,I.MAKE_AI_CONVERSATION_LIMITS.historyCharacters-o),o>I.MAKE_AI_CONVERSATION_LIMITS.historyCharacters)throw new Error("Invalid Make App assistant response: history text budget");return{id:p,role:r,content:d,artifacts:[]}});return{threadId:a,messages:t}},k=()=>{const e=[],a=[];return{next:()=>{const o=e.shift();return o?Promise.resolve(o):new Promise(t=>a.push(t))},push:o=>{const t=a.shift();t?t(o):e.push(o)}}},T=(e,a)=>{if(I.countCodePointsUpTo(e.data,a)>a)throw new Error("Make App assistant SSE event exceeds maxEventCharacters");try{const i=JSON.parse(e.data);if(!u(i))throw new Error("invalid data");return i}catch{throw new Error("Invalid Make App assistant SSE JSON")}},E=()=>new DOMException("Aborted","AbortError"),A=e=>{if(e?.aborted)throw E()},C=async function*(e,a){const i=`assistant:${e.responseId}`;A(a?.signal),yield{type:"message.start",runId:e.responseId,messageId:i};const c=k(),o=e.eventSourceFactory({chatId:e.chatId,responseId:e.responseId,cursor:"0-0"},{withCredentials:!0});let t=!1;const s=n=>{t||(t=!0,c.push(n))},r=new Map,p=(n,l)=>{const y=g=>{if(!t)try{l(T(g,e.maxEventCharacters))}catch(f){s({type:"error",error:f})}};r.set(n,y),o.addEventListener(n,y)};p("run.started",()=>{c.push({type:"event",event:{type:"run.progress",runId:e.responseId,message:"正在分析"}})}),p("response.progress",n=>{c.push({type:"event",event:{type:"run.progress",runId:e.responseId,message:h(n.message,"progress message",I.MAKE_AI_CONVERSATION_LIMITS.messageCharacters)}})}),p("response.delta",n=>{if(typeof n.text!="string")throw new Error("Invalid Make App assistant response: delta text");c.push({type:"event",event:{type:"message.delta",messageId:i,delta:n.text}})}),p("response.message",n=>{c.push({type:"event",event:{type:"message.replace",messageId:i,content:h(n.text,"message text",I.MAKE_AI_CONVERSATION_LIMITS.messageCharacters)}})}),p("response.completed",()=>{c.push({type:"event",event:{type:"message.complete",messageId:i}}),c.push({type:"event",event:{type:"run.complete",runId:e.responseId,threadId:e.chatId}}),s({type:"done"})}),p("response.failed",n=>{const l=h(n.code,"failure code");s({type:"event",event:{type:"error",code:l,message:M[l]??"本次 AI 处理失败,请重试。",retryable:!["AI_AUTH_REQUIRED","AI_AUTH_EXPIRED","AI_FORBIDDEN","AI_APP_UNAVAILABLE","AI_AGENT_UNAVAILABLE"].includes(l),requestId:e.responseId}})}),o.onerror=()=>{t||o.readyState!==void 0&&o.readyState!==2||s({type:"error",error:new Error("Make App assistant SSE disconnected")})};const d=()=>s({type:"error",error:E()});a?.signal?.addEventListener("abort",d,{once:!0}),a?.signal?.aborted&&d();try{for(;;){const n=await c.next();if(n.type==="done")return;if(n.type==="error")throw n.error;if(yield n.event,n.event.type==="error")return}}finally{t=!0,a?.signal?.removeEventListener("abort",d),o.onerror=null;for(const[n,l]of r)o.removeEventListener(n,l);o.close()}},N=e=>{const a=e.eventSourceFactory,i=e.historyLimit??m,c=e.maxEventCharacters??w.DEFAULT_MAX_SSE_EVENT_CHARACTERS;if(!Number.isInteger(i)||i<1||i>100)throw new Error("historyLimit must be an integer between 1 and 100");if(!Number.isInteger(c)||c<=0)throw new Error("maxEventCharacters must be a positive integer");const o=async(t,s)=>{A(s?.signal),console.info("[make-ai-assistant] Make App chat locate start",{appId:t.app.id});const{chatId:r}=_(await e.locateChat(t,{signal:s?.signal}));return A(s?.signal),console.info("[make-ai-assistant] Make App chat locate success",{appId:t.app.id}),r};return{features:{history:!0,newConversation:!1,regeneration:!1,remoteCancellation:!1},async loadConversation(t,s){console.info("[make-ai-assistant] Make App history load start",{appId:t.app.id});try{A(s?.signal);const r=await o(t,s),p=await e.loadHistory({chatId:r,cursor:-1,limit:i},{signal:s?.signal});A(s?.signal);const d=S(p,r,i);return console.info("[make-ai-assistant] Make App history load success",{appId:t.app.id,messageCount:d.messages.length}),d}catch(r){throw(s?.signal?.aborted?console.info:console.error)(s?.signal?.aborted?"[make-ai-assistant] Make App history load cancelled":"[make-ai-assistant] Make App history load failed",{appId:t.app.id,errorType:r instanceof Error?r.name:typeof r}),r}},async*run(t,s){console.info("[make-ai-assistant] Make App run start",{appId:t.context.app.id});try{A(s?.signal);const r=await o(t.context,s),p=v(await e.sendMessage({chatId:r,messageId:t.message.id,text:t.message.content},{signal:s?.signal}));if(A(s?.signal),p.chatId!==r)throw new Error("Invalid Make App assistant response: chatId mismatch");for await(const d of C({chatId:r,responseId:p.responseId,eventSourceFactory:a,maxEventCharacters:c},s))yield d;console.info("[make-ai-assistant] Make App run complete",{appId:t.context.app.id})}catch(r){throw s?.signal?.aborted?console.info("[make-ai-assistant] Make App run cancelled",{appId:t.context.app.id}):console.error("[make-ai-assistant] Make App run failed",{appId:t.context.app.id,errorType:r instanceof Error?r.name:typeof r}),r}}}};exports.createMakeAppAssistantTransport=N;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./conversation-Cvh-IVRV.cjs"),A=r=>{const i=t.protocolText(r,36);if(!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(i))throw new Error("Invalid Make App request: UUID");return i},x=r=>{const i=t.protocolText(r,512,!0);if(new TextEncoder().encode(i).length>512||/[\r\n/\\]/.test(i))throw new Error("Invalid Make App request: filename");return i},E=(r,i,n)=>{const d=t.protocolRecord(r);if(t.protocolKeys(d,["chatId","appKey","agentId","title","status","revision","pinned","pinnedAt","createdAt","lastActivityAt"]),d.appKey!==i.appKey||d.agentId!==i.agentId||n&&d.chatId!==n||!["active","deleted"].includes(String(d.status)))throw new Error("Invalid Make App response: chat scope");return{chatId:t.protocolId(d.chatId),appKey:i.appKey,agentId:i.agentId,title:t.protocolText(d.title,255,!0),status:d.status,revision:t.protocolInteger(d.revision,1),pinned:t.protocolBoolean(d.pinned),pinnedAt:d.pinnedAt==null?null:t.protocolText(d.pinnedAt,64),createdAt:t.protocolText(d.createdAt,64),lastActivityAt:t.protocolText(d.lastActivityAt,64)}},U=(r,i)=>{const n=t.protocolRecord(r),d=t.protocolArray(n.chats,100).map(u=>E(u,i));if(new Set(d.map(u=>u.chatId)).size!==d.length)throw new Error("Invalid Make App response: duplicate chat");const p=t.protocolText(n.nextCursor,8192,!0),I=t.protocolBoolean(n.hasMore);if(I!==!!p)throw new Error("Invalid Make App response: chat cursor");return{chats:d,nextCursor:p,hasMore:I}},P=(r,i,n)=>{const d=t.protocolRecord(r),p=t.protocolInteger(d.nextCursor,-1),I=t.protocolBoolean(d.hasMore);if(p<n||I&&p<=n)throw new Error("Invalid Make App response: history cursor did not advance");let u=0,l=n;const w=new Set,f=t.protocolArray(d.messages,200).map(m=>{const y=t.protocolRecord(m);if(y.role!=="user"&&y.role!=="assistant")throw new Error("Invalid Make App response: history role");const g=t.protocolInteger(y.cursor);if(g<=l||g>p)throw new Error("Invalid Make App response: history order");l=g;const o=y.messageId!==void 0,e=o?t.protocolId(y.messageId):`history-${i}-${g}`;if(w.has(e))throw new Error("Invalid Make App response: duplicate message");w.add(e);const s=t.protocolText(y.text,1e5,!0);if(u+=[...s].length,u>1e6)throw new Error("Invalid Make App response: history budget");return{id:e,role:y.role,content:s,persistent:o,cursor:g,createdAt:t.protocolText(y.createdAt,64),...y.responseId===void 0?{}:{responseId:t.protocolId(y.responseId)},...y.parts===void 0?{}:{parts:t.parseContentParts(y.parts)},...y.feedback===void 0?{}:{feedback:t.parseFeedback(y.feedback)}}});return{threadId:i,messages:f,nextCursor:p,hasMore:I}},M=(r,i)=>{const n=t.parseResponseSnapshot(r);if(n.chatId!==i.chatId||n.responseId!==i.responseId)throw new Error("Invalid Make App response: response scope");return n},b=(r,i)=>{const n=t.protocolRecord(r);if(!["uploading","ready","cancelled"].includes(String(n.status))||i&&n.id!==i)throw new Error("Invalid Make App response: upload");const d=t.protocolInteger(n.sizeBytes,0,64<<20),p=t.protocolInteger(n.partSize,1<<20,1<<20),I=t.protocolArray(n.completedParts,64).map(l=>t.protocolInteger(l,0,Math.max(0,Math.ceil(d/p)-1)));if(new Set(I).size!==I.length)throw new Error("Invalid Make App response: repeated upload part");const u={id:t.protocolId(n.id),status:n.status,name:x(n.name),contentType:t.protocolText(n.contentType,256),sizeBytes:d,partSize:p,completedParts:I};if(u.status==="ready"){const l=t.protocolRecord(n.content);if(l.kind!=="reference"||l.sizeBytes!==d||!/^[0-9a-f]{64}$/.test(String(l.digestSha256)))throw new Error("Invalid Make App response: content receipt");u.content={kind:"reference",contentRef:t.protocolId(l.contentRef),sizeBytes:d,digestSha256:String(l.digestSha256)}}return u},D=r=>{const i=t.protocolId(r.threadId),n=A(r.message.id);let d,p;if(r.message.parts!==void 0){const I=t.parseContentParts(r.message.parts);if(!I.length)throw new Error("Invalid Make App request: empty parts");const u=new Set;for(const l of I){const w=A(l.id);if(u.has(w))throw new Error("Invalid Make App request: duplicate part");if(u.add(w),l.kind!=="text"){l.name!==void 0&&x(l.name);const f=l.media.contentType;if(!/^[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+$/.test(f)||l.kind!=="file"&&(!f.startsWith(`${l.kind}/`)||f==="image/svg+xml"))throw new Error("Invalid Make App request: media type")}}if(p=I.filter(l=>l.kind==="text").map(l=>l.text).join(""),!p.trim()&&I.every(l=>l.kind==="text"))throw new Error("Invalid Make App request: empty input");d={chatId:i,messageId:n,parts:I}}else p=t.protocolText(r.message.content,8192),d={chatId:i,messageId:n,text:p};if(new TextEncoder().encode(p).length>8192||new TextEncoder().encode(JSON.stringify(d)).length>65536)throw new Error("输入内容过长,请控制在 8 KiB 文本和 32 个附件/文本片段以内");return d},O=()=>{const r=[];let i,n=!1,d;return{push(p){if(!n)if(i){const I=i;i=void 0,I.resolve({done:!1,value:p})}else r.length>=4096?this.fail(new Error("响应事件积压超过限制,请恢复对话")):r.push(p)},fail(p){d=p,n=!0,r.length=0,i?.reject(p),i=void 0},close(){n=!0,r.length=0,i?.resolve({done:!0,value:void 0}),i=void 0},next(){return d?Promise.reject(d):r.length?Promise.resolve({done:!1,value:r.shift()}):n?Promise.resolve({done:!0,value:void 0}):new Promise((p,I)=>{i={resolve:p,reject:I}})}}},C=(r,i)=>new Promise(n=>{if(i?.aborted){n();return}const d=()=>{clearTimeout(p),i?.removeEventListener("abort",d),n()},p=setTimeout(d,r);i?.addEventListener("abort",d,{once:!0})}),R=r=>{if(!/^\d{1,20}-\d{1,20}$/.test(r))throw new Error("Invalid Make App response: stream cursor");return r.split("-").map(BigInt)},B=(r,i)=>{const[n,d]=R(r),[p,I]=R(i);return n>p||n===p&&d>I},T=r=>{const i=r;return[400,401,403,404].includes(i?.status??i?.response?.status??0)||["AI_FORBIDDEN","AI_AUTH_REQUIRED","AI_AUTH_EXPIRED","AI_NOT_FOUND","AI_RESPONSE_NOT_FOUND"].includes(i?.code??"")||r instanceof Error&&r.message.startsWith("Invalid ")},F=["response.subscribed","response.state","response.output_item.added","response.output_text.delta","response.output_item.done","response.reset","response.snapshot","response.completed","response.failed","response.cancelled"];async function*q(r,i,n){if(n?.aborted)return;let d=r.cursor??"0-0";R(d);let p=0,I=!1,u=0;const l=new Map;yield{type:"response.state",chatId:r.chatId,responseId:r.responseId,status:"queued"};async function*w(f,m){if(f==="completed"){let y=r.historyCursor??-1,g=0;const o=[];let e=!0;for(;e&&!n?.aborted;){if(++g>200)throw new Error("历史恢复超过单次预算,请继续加载历史");const s=await i.loadHistory(r,y,n);for(const a of s.messages)if(a.responseId===r.responseId&&a.role==="assistant"&&a.persistent){const{artifacts:c,...h}=a;o.push(t.parseStoredMessage(h))}if(e=s.hasMore??!1,e&&(s.nextCursor??-1)<=y)throw new Error("Invalid Make App response: history cursor");y=s.nextCursor??y}if(n?.aborted)return;if(!o.length)throw new Error("回答已完成,历史尚未同步,请恢复对话");yield{type:"response.reconciled",chatId:r.chatId,responseId:r.responseId,messages:o}}yield{type:"response.terminal",chatId:r.chatId,responseId:r.responseId,status:f,...m?{code:m}:{}}}for(;!n?.aborted;){if(p>3){if(++u>600)throw new Error("响应连接中断,请恢复对话");let a;try{a=await i.getResponse(r,n)}catch(c){if(n?.aborted)return;if(T(c))throw c}if(a&&(yield{type:"response.snapshot",snapshot:a},t.isResponseTerminal(a.status))){yield*w(a.status);return}await C(Math.max(1e3,i.reconnectDelayMs),n);continue}const f=O();let m=0,y=!1;const g=i.eventSourceFactory({chatId:r.chatId,responseId:r.responseId,cursor:d},{withCredentials:!0}),o=F.map(a=>{const c=h=>{if(!(y||n?.aborted)){if(h.data.length>i.maxEventCharacters*2||[...h.data].length>i.maxEventCharacters||m+h.data.length>4e6){y=!0,g.close(),f.fail(new Error("Make App assistant SSE event exceeds maxEventCharacters"));return}m+=h.data.length,f.push({name:a,raw:h.data,id:h.lastEventId})}};return g.addEventListener(a,c),{name:a,listener:c}});g.onerror=()=>{!y&&!n?.aborted&&(y=!0,g.close(),f.push({reconnect:!0}))};const e=()=>{y=!0,g.close(),f.close()};n?.addEventListener("abort",e,{once:!0}),n?.aborted&&e();try{for(;!n?.aborted;){const a=await f.next();if(a.done)return;const c=a.value;if("reconnect"in c)break;if(m-=c.raw.length,c.id&&!B(c.id,d)){if(l.has(c.id)&&l.get(c.id)!==c.raw)throw new Error("Invalid Make App response: conflicting stream replay");continue}const h=t.protocolRecord(JSON.parse(c.raw));if(t.protocolId(h.responseId)!==r.responseId)throw new Error("Invalid Make App response: stream scope");if(c.name!=="response.subscribed"){if(c.name==="response.reset"){I=!0;continue}if(c.name==="response.snapshot"){const v=M(h,r);if(yield{type:"response.snapshot",snapshot:v},t.isResponseTerminal(v.status)){yield*w(v.status);return}}else if(c.name==="response.completed"||c.name==="response.cancelled"){yield*w(c.name==="response.completed"?"completed":"cancelled");return}else if(c.name==="response.failed"){if(h.code==="AI_UPSTREAM_ERROR"){y=!0,g.close();break}if(h.code==="AI_FORBIDDEN"||h.code==="AI_AUTH_EXPIRED")throw Object.assign(new Error("当前身份无法继续读取响应"),{code:h.code,status:h.code==="AI_FORBIDDEN"?403:401});yield*w("failed",typeof h.code=="string"?h.code:void 0);return}else c.name==="response.state"?yield t.parseAssistantEvent({type:c.name,chatId:r.chatId,...h}):I||(yield t.parseAssistantEvent({type:c.name,...h}));c.id&&(d=c.id,l.set(c.id,c.raw),l.size>512&&l.delete(l.keys().next().value))}}}finally{g.onerror=null,g.close(),f.close();for(const{name:a,listener:c}of o)g.removeEventListener(a,c);n?.removeEventListener("abort",e)}if(n?.aborted||(p+=1,console.info("[make-ai-assistant] response reconnect",{attempt:p}),await C(Math.min(i.reconnectDelayMs*2**(p-1),5e3),n),n?.aborted))return;let s;try{s=await i.getResponse(r,n)}catch(a){if(n?.aborted)return;if(T(a))throw a}if(s&&t.isResponseTerminal(s.status)){yield{type:"response.snapshot",snapshot:s},yield*w(s.status);return}I&&(p=4)}}const K=()=>Object.assign(new Error("Operation aborted"),{name:"AbortError"}),S=r=>{if(r?.aborted)throw K()},z=r=>{const i=t.protocolInteger(r.historyLimit??100,1,200),n=t.protocolInteger(r.maxEventCharacters??1e6,1,4e6),d=t.protocolInteger(r.reconnectDelayMs??500,1,3e4),p=o=>{const e=r.resolveScope(o);return{appKey:t.protocolId(e.appKey),agentId:t.protocolId(e.agentId),identityKey:t.protocolId(e.identityKey)}},I=o=>{const e=p(o);return`${e.identityKey}\0${e.appKey}\0${e.agentId}`},u=async(o,e,s,a)=>{S(a);const c=I(o);console.info("[make-ai-assistant] Make App operation start",{operation:e});try{const h=await s();if(S(a),c!==I(o))throw K();return h}catch(h){throw console.warn("[make-ai-assistant] Make App operation failed",{operation:e,errorType:h instanceof Error?h.name:typeof h}),h}},l=o=>({chatId:t.protocolId(o.chatId)}),w=o=>({...l(o),responseId:t.protocolId(o.responseId)}),f=o=>({...l(o),uploadId:t.protocolId(o.uploadId)}),m=async(o,e,s,a)=>u(o,"loadHistory",async()=>P(await r.loadHistory({chatId:t.protocolId(e),cursor:t.protocolInteger(s,-1),limit:i},{signal:a}),e,s),a),y=async(o,e,s)=>u(o,"getResponse",async()=>M(await r.getResponse(w(e),{signal:s}),e),s),g=(o,e,s)=>{const a=I(o),c=s?.signal;return(async function*(){for await(const h of q(e,{eventSourceFactory:r.eventSourceFactory,getResponse:(v,k)=>y(o,v,k),loadHistory:(v,k,_)=>m(o,v.chatId,k,_),maxEventCharacters:n,reconnectDelayMs:d},c)){if(c?.aborted||a!==I(o))return;yield h}})()};return{features:{history:!0,newConversation:!0,remoteCancellation:!0,regeneration:!1,conversationManagement:!0,feedback:!0,attachments:!0,modelInputKinds:r.modelInputKinds??["text"]},scopeKey:I,listAgents:(o,e)=>u(o,"listAgents",async()=>{const s=p(o),a=t.protocolRecord(await r.listAgents({appKey:s.appKey},{signal:e?.signal}));return t.protocolArray(a.agents,1e3).map(c=>{const h=t.protocolRecord(c);if(h.appKey!==s.appKey)throw new Error("Invalid Make App response: agent scope");return{agentId:t.protocolId(h.agentId),appKey:s.appKey,name:t.protocolText(h.name)}})},e?.signal),listConversations:(o,e,s)=>u(o,"listChats",async()=>{const{appKey:a,agentId:c}=p(o);return U(await r.listChats({appKey:a,agentId:c,...e?.cursor?{cursor:t.protocolText(e.cursor,8192)}:{},limit:t.protocolInteger(e?.limit??50,1,100)},{signal:s?.signal}),{appKey:a,agentId:c})},s?.signal),createConversation:(o,e,s)=>u(o,"createChat",async()=>{const{appKey:a,agentId:c}=p(o),h={appKey:a,agentId:c,requestId:A(e.requestId),...e.title===void 0?{}:{title:t.protocolText(e.title.trim(),255)}};return E(await r.createChat(h,{signal:s?.signal}),{appKey:a,agentId:c})},s?.signal),getConversation:(o,e,s)=>u(o,"getChat",async()=>E(await r.getChat(l(e),{signal:s?.signal}),p(o),e.chatId),s?.signal),updateConversation:(o,e,s)=>u(o,"updateChat",async()=>{const a={...l(e),expectedRevision:t.protocolInteger(e.expectedRevision,1)};if(e.title!==void 0&&(a.title=t.protocolText(e.title.trim(),255)),e.pinned!==void 0){if(typeof e.pinned!="boolean")throw new Error("Invalid Make App request: pinned");a.pinned=e.pinned}if(a.title===void 0&&a.pinned===void 0)throw new Error("Invalid Make App request: empty patch");return E(await r.updateChat(a,{signal:s?.signal}),p(o),e.chatId)},s?.signal),deleteConversation:(o,e,s)=>u(o,"deleteChat",()=>r.deleteChat({...l(e),expectedRevision:t.protocolInteger(e.expectedRevision,1)},{signal:s?.signal}),s?.signal),loadConversation:async(o,e)=>e?.threadId?m(o,e.threadId,e.cursor??-1,e.signal):{messages:[]},getResponse:(o,e,s)=>y(o,e,s?.signal),cancelResponse:(o,e,s)=>u(o,"cancelResponse",async()=>M(await r.cancelResponse(w(e),{signal:s?.signal}),e),s?.signal),setFeedback:(o,e,s)=>u(o,"setFeedback",async()=>{if(!["like","dislike","none"].includes(e.rating))throw new Error("Invalid Make App request: rating");const a=t.protocolText(e.reason??"",128,!0).trim(),c=t.protocolText(e.comment??"",4e3,!0).trim();if(e.rating!=="dislike"&&(a||c))throw new Error("Invalid Make App request: feedback detail");return t.parseFeedback(await r.setFeedback({...l(e),messageId:t.protocolId(e.messageId),requestId:A(e.requestId),rating:e.rating,...a?{reason:a}:{},...c?{comment:c}:{}},{signal:s?.signal}))},s?.signal),startUpload:(o,e,s)=>u(o,"startUpload",async()=>b(await r.startUpload({...l(e),fileId:A(e.fileId),name:x(e.name),contentType:t.protocolText(e.contentType,256),sizeBytes:t.protocolInteger(e.sizeBytes,0,64<<20),...e.digestSha256?{digestSha256:t.protocolText(e.digestSha256,64)}:{}},{signal:s?.signal})),s?.signal),getUpload:(o,e,s)=>u(o,"getUpload",async()=>b(await r.getUpload(f(e),{signal:s?.signal}),e.uploadId),s?.signal),uploadPart:(o,e,s)=>u(o,"uploadPart",()=>{if(!(e.bytes instanceof Uint8Array)||e.bytes.byteLength>1<<20)throw new Error("Invalid Make App request: upload bytes");return r.uploadPart({...f(e),part:t.protocolInteger(e.part,0,63),bytes:e.bytes},{signal:s?.signal})},s?.signal),completeUpload:(o,e,s)=>u(o,"completeUpload",async()=>b(await r.completeUpload(f(e),{signal:s?.signal}),e.uploadId),s?.signal),readContent:(o,e,s)=>u(o,"readContent",async()=>{const a=await r.readContent({...l(e),contentRef:t.protocolId(e.contentRef)},{signal:s?.signal});if(!(a instanceof Uint8Array)||a.byteLength>64<<20)throw new Error("Invalid Make App response: content bytes");return a},s?.signal),watchResponse:g,async*run(o,e){if(e?.signal?.aborted)return;const s=D(o),a=await u(o.context,"sendMessage",async()=>t.protocolRecord(await r.sendMessage(s,{signal:e?.signal})),e?.signal);if(a.chatId!==s.chatId)throw new Error("Invalid Make App response: accepted chat");const c=t.protocolId(a.responseId),h=t.protocolInteger(a.acceptedCursor);yield{type:"response.accepted",chatId:s.chatId,responseId:c,messageId:s.messageId,acceptedCursor:h},yield*g(o.context,{chatId:s.chatId,responseId:c,historyCursor:h},e)}}};exports.createMakeAppAssistantTransport=z;
|
package/dist/make-app.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type { AssistantTransport,
|
|
1
|
+
import type { AssistantTransport, MakeAssistantHostContext } from "./core/index.js";
|
|
2
|
+
import { type AssistantCallOptions, type AssistantChatCreate, type AssistantChatPatch, type AssistantChatRef, type AssistantFeedbackWrite, type AssistantResponseRef, type AssistantUploadRef, type AssistantUploadStart, type AssistantContentPart } from "./core/conversation-management.js";
|
|
3
|
+
import { type MessageInput } from "./make-app/protocol.js";
|
|
2
4
|
export interface MakeAppAssistantEventSourceEvent {
|
|
3
5
|
data: string;
|
|
4
6
|
lastEventId: string;
|
|
@@ -17,20 +19,53 @@ export type MakeAppAssistantEventSourceFactory = (subscription: {
|
|
|
17
19
|
}, init: {
|
|
18
20
|
withCredentials: true;
|
|
19
21
|
}) => MakeAppAssistantEventSource;
|
|
22
|
+
export interface MakeAppAssistantScope {
|
|
23
|
+
appKey: string;
|
|
24
|
+
agentId: string;
|
|
25
|
+
identityKey: string;
|
|
26
|
+
}
|
|
20
27
|
export interface MakeAppAssistantTransportOptions {
|
|
28
|
+
resolveScope(context: MakeAssistantHostContext): MakeAppAssistantScope;
|
|
21
29
|
eventSourceFactory: MakeAppAssistantEventSourceFactory;
|
|
22
30
|
historyLimit?: number;
|
|
23
31
|
maxEventCharacters?: number;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
32
|
+
reconnectDelayMs?: number;
|
|
33
|
+
modelInputKinds?: ReadonlyArray<AssistantContentPart["kind"]>;
|
|
34
|
+
listAgents(input: {
|
|
35
|
+
appKey: string;
|
|
36
|
+
}, options: AssistantCallOptions): Promise<unknown>;
|
|
37
|
+
listChats(input: {
|
|
38
|
+
appKey: string;
|
|
39
|
+
agentId: string;
|
|
40
|
+
cursor?: string;
|
|
41
|
+
limit?: number;
|
|
42
|
+
}, options: AssistantCallOptions): Promise<unknown>;
|
|
43
|
+
createChat(input: AssistantChatCreate & {
|
|
44
|
+
appKey: string;
|
|
45
|
+
agentId: string;
|
|
46
|
+
}, options: AssistantCallOptions): Promise<unknown>;
|
|
47
|
+
getChat(input: AssistantChatRef, options: AssistantCallOptions): Promise<unknown>;
|
|
48
|
+
updateChat(input: AssistantChatPatch, options: AssistantCallOptions): Promise<unknown>;
|
|
49
|
+
deleteChat(input: AssistantChatRef & {
|
|
50
|
+
expectedRevision: number;
|
|
51
|
+
}, options: AssistantCallOptions): Promise<void>;
|
|
52
|
+
loadHistory(input: AssistantChatRef & {
|
|
53
|
+
cursor: number;
|
|
27
54
|
limit: number;
|
|
28
|
-
}, options:
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
55
|
+
}, options: AssistantCallOptions): Promise<unknown>;
|
|
56
|
+
sendMessage(input: MessageInput, options: AssistantCallOptions): Promise<unknown>;
|
|
57
|
+
getResponse(input: AssistantResponseRef, options: AssistantCallOptions): Promise<unknown>;
|
|
58
|
+
cancelResponse(input: AssistantResponseRef, options: AssistantCallOptions): Promise<unknown>;
|
|
59
|
+
setFeedback(input: AssistantFeedbackWrite, options: AssistantCallOptions): Promise<unknown>;
|
|
60
|
+
startUpload(input: AssistantUploadStart, options: AssistantCallOptions): Promise<unknown>;
|
|
61
|
+
getUpload(input: AssistantUploadRef, options: AssistantCallOptions): Promise<unknown>;
|
|
62
|
+
uploadPart(input: AssistantUploadRef & {
|
|
63
|
+
part: number;
|
|
64
|
+
bytes: Uint8Array;
|
|
65
|
+
}, options: AssistantCallOptions): Promise<void>;
|
|
66
|
+
completeUpload(input: AssistantUploadRef, options: AssistantCallOptions): Promise<unknown>;
|
|
67
|
+
readContent(input: AssistantChatRef & {
|
|
68
|
+
contentRef: string;
|
|
69
|
+
}, options: AssistantCallOptions): Promise<Uint8Array>;
|
|
35
70
|
}
|
|
36
71
|
export declare const createMakeAppAssistantTransport: (options: MakeAppAssistantTransportOptions) => AssistantTransport;
|