allyhub 0.2.0-next.2 → 0.2.0-next.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client.d.ts +5 -1
- package/dist/charge.js +2 -0
- package/dist/commands/check.js +1 -1
- package/dist/commands/cloud-tools.js +10 -10
- package/dist/commands/mcp.js +1 -1
- package/dist/commands/voice.js +2 -2
- package/dist/lent/model-three.d.ts +2 -0
- package/dist/main.js +4 -4
- package/editor-app/view.html +2 -2
- package/editor-web/assets/chevron-left-BzSzrFR5.js +1 -0
- package/editor-web/assets/{chevron-up-DdzgESXy.js → chevron-up-C-TmFeHp.js} +1 -1
- package/editor-web/assets/{dist-DqFDRJ1S.js → dist-49NTUm82.js} +2 -2
- package/editor-web/assets/{dist-ZLZyLIPV.js → dist-Cdp4CLOB.js} +1 -1
- package/editor-web/assets/{dist-CiIDdJZw.js → dist-Cun2C_27.js} +1 -1
- package/editor-web/assets/{dist-DlzWTZjN.js → dist-DJIfS4Mh.js} +1 -1
- package/editor-web/assets/{floating-ui.react-dom-BrYYB6DH.js → floating-ui.react-dom-iFhm-7Xc.js} +1 -1
- package/editor-web/assets/index-9-pcRXol.js +56 -0
- package/editor-web/assets/{react-DIqYlXoe.js → react-DAVp_9d7.js} +1 -1
- package/editor-web/assets/{undo-2-oaEQLQ47.js → undo-2-57uMP9M_.js} +1 -1
- package/editor-web/index.html +3 -3
- package/node_modules/@allyhub-next/audio/package.json +1 -1
- package/node_modules/@allyhub-next/browser/package.json +1 -1
- package/node_modules/@allyhub-next/build/package.json +1 -1
- package/node_modules/@allyhub-next/check/package.json +1 -1
- package/node_modules/@allyhub-next/cloud/dist/call.js +2 -2
- package/node_modules/@allyhub-next/cloud/dist/index.js +1 -1
- package/node_modules/@allyhub-next/cloud/dist/voice.js +1 -1
- package/node_modules/@allyhub-next/cloud/package.json +1 -1
- package/node_modules/@allyhub-next/components/package.json +1 -1
- package/node_modules/@allyhub-next/dev-server/dist/live.d.ts +1 -1
- package/node_modules/@allyhub-next/dev-server/dist/tools.js +1 -1
- package/node_modules/@allyhub-next/dev-server/package.json +1 -1
- package/node_modules/@allyhub-next/doc/package.json +1 -1
- package/node_modules/@allyhub-next/export/package.json +1 -1
- package/node_modules/@allyhub-next/formats/package.json +1 -1
- package/node_modules/@allyhub-next/measure/package.json +1 -1
- package/node_modules/@allyhub-next/media/package.json +1 -1
- package/node_modules/@allyhub-next/model/package.json +1 -1
- package/node_modules/@allyhub-next/project/package.json +1 -1
- package/node_modules/@allyhub-next/protocol/dist/cloud.d.ts +23 -0
- package/node_modules/@allyhub-next/protocol/dist/cloud.js +1 -1
- package/node_modules/@allyhub-next/protocol/package.json +1 -1
- package/node_modules/@allyhub-next/registry/package.json +1 -1
- package/node_modules/@allyhub-next/render/package.json +1 -1
- package/node_modules/@allyhub-next/runtime/package.json +1 -1
- package/node_modules/@allyhub-next/runtimes/manifest.json +88 -14
- package/node_modules/@allyhub-next/runtimes/package.json +1 -1
- package/node_modules/@allyhub-next/scenery/package.json +1 -1
- package/node_modules/@allyhub-next/scenery-host/package.json +1 -1
- package/node_modules/@allyhub-next/sheet/package.json +1 -1
- package/node_modules/@allyhub-next/site/package.json +1 -1
- package/node_modules/@allyhub-next/stage/package.json +1 -1
- package/node_modules/@allyhub-next/video-core/package.json +1 -1
- package/package.json +30 -27
- package/editor-web/assets/chevron-left-BWWKfQPt.js +0 -1
- package/editor-web/assets/index-DYkuF7LX.js +0 -56
package/client.d.ts
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
// "allyhub/client" to `types` in tsconfig.json, beside "@allyhub/sdk/client".
|
|
4
4
|
// Each points at `allyhub/lent/*`, the bundled package's own declarations,
|
|
5
5
|
// written into the npm package when it is packed
|
|
6
|
-
// (apps/create-allyhub/scripts/npm-packages.ts
|
|
6
|
+
// (apps/create-allyhub/scripts/npm-packages.ts, which refuses to pack a
|
|
7
|
+
// lent entry this file does not declare).
|
|
7
8
|
|
|
8
9
|
declare module "@allyhub-next/scenery-host/layer" {
|
|
9
10
|
export * from "allyhub/lent/scenery-host/layer";
|
|
@@ -11,3 +12,6 @@ declare module "@allyhub-next/scenery-host/layer" {
|
|
|
11
12
|
declare module "@allyhub-next/model" {
|
|
12
13
|
export * from "allyhub/lent/model";
|
|
13
14
|
}
|
|
15
|
+
declare module "@allyhub-next/model/three" {
|
|
16
|
+
export * from "allyhub/lent/model/three";
|
|
17
|
+
}
|
package/dist/charge.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
|
|
2
|
+
import{request as f}from"node:http";import{CHARGE_META as w,STUDIO_ASK_ENV as l}from"@allyhub-next/protocol";import{CommandError as u}from"./command.js";export const ASK_ABOVE=10;export function chargeOf(t,o,e){return{tool:t,title:o,credits:e.credits,estimated:e.estimated,unknown:e.lines.some(n=>n.unknown&&n.rate>0)}}export const beyond=(t,o)=>t.unknown||t.credits>o,askingAbove=(t,o)=>e=>beyond(e,t)?o(e):Promise.resolve(!0);const m=t=>new Intl.NumberFormat("en-US",{maximumFractionDigits:2}).format(t);export function priceWords(t){return t.unknown?t.credits>0?`at least ${m(t.credits)} credits`:"credits by what it makes, known once it is made":`${t.estimated?"about ":""}${m(t.credits)} credits`}export const chargeMessage=t=>`${t.title} (${t.tool}) costs ${priceWords(t)} of AllyHub's. Allow it?`,chargeQuestion=t=>({mode:"form",message:chargeMessage(t),requestedSchema:{type:"object",properties:{}},_meta:{[w]:t}});export function studioApprove(t,o,e){const n=t[l];if(n===void 0||n==="")return;const s=t.ALLYHUB_ASK_ABOVE?.trim(),i=s===void 0||s===""?Number.NaN:Number(s),r=Number.isFinite(i)&&i>=0?i:ASK_ABOVE;return askingAbove(r,async a=>{const{status:c,text:p}=await g(n,JSON.stringify({cwd:o,params:chargeQuestion(a)}),e),d=JSON.parse(p);if(c!==200)throw new u("not-asked",`Studio could not ask the person: ${d.error?.message??`it answered ${String(c)}`}. Nothing was called or charged.`);return d.action==="accept"})}function g(t,o,e){return new Promise((n,s)=>{const i=f(t,{method:"POST",headers:{"content-type":"application/json"},signal:e},r=>{const a=[];r.on("data",c=>a.push(c)),r.on("end",()=>{n({status:r.statusCode??0,text:Buffer.concat(a).toString("utf8")})}),r.on("error",s)});i.on("error",r=>{s(new u("not-asked",`Studio could not be reached to ask the person: ${r.message}. Nothing was called or charged.`))}),i.end(o)})}
|
package/dist/commands/check.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
|
|
2
|
-
import{z as
|
|
2
|
+
import{z as o}from"zod";import{EXIT as s}from"@allyhub-next/protocol";import{formatCheck as c}from"../text/index.js";import{defineCommand as m}from"../command.js";import{projectRoot as a}from"../project.js";import{dir as l}from"../fields.js";import{checkIndexed as n}from"../version.js";export const check=m({name:"check",summary:"Problems: objective errors in the project's items, by rule; exits 1 when one must be fixed",input:o.strictObject({item:o.string().optional().describe("Only this item: its id, a path into it, or a folder of items"),dir:l,fresh:o.boolean().default(!1).describe("Load every version again, not the last check's results")}),positional:["item"],output:o.looseObject({}),examples:["allyhub check","allyhub check launch/film","allyhub check --json"]},async(t,r)=>{const i=await a(r.cwd,t.dir),e=await n({dir:i,fresh:t.fresh,...t.item===void 0?{}:{piece:t.item}},r);return{value:{check:e.check,problems:e.problems,stats:e.stats,facts:e.facts.length,console:e.console},text:c(e),exit:e.check.errors>0?s.failed:s.ok}});
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
|
|
2
|
-
import{readFile as
|
|
3
|
-
`)}}))}const k=
|
|
4
|
-
`);if(
|
|
5
|
-
`);const
|
|
6
|
-
`),...
|
|
7
|
-
`)}const
|
|
8
|
-
`)}}const
|
|
2
|
+
import{readFile as J}from"node:fs/promises";import{join as E,resolve as T}from"node:path";import{z as a}from"zod";import{callTool as L,findTool as C,loadCatalog as h,priceCalls as F,priceText as j,resumeJob as M,uploadFiles as H}from"@allyhub-next/cloud";import{WORK_DIR as U}from"@allyhub-next/formats";import{EXIT as g}from"@allyhub-next/protocol";import{CommandError as $,defineCommand as w}from"../command.js";import{optionName as B}from"../args.js";import{chargeOf as K}from"../charge.js";import{commandHelp as _}from"../help.js";import{requiredMissing as G,toolInput as P,toolOptions as z}from"../tool-options.js";import{cloudOf as p,cloudWork as f,placeFrom as X,plural as b}from"./cloud.js";const Q=8e3,d={input:a.string().optional().describe("The input as JSON, or a file of it: the whole of it, or the fields no option gives; an option given beside it wins"),quote:a.boolean().default(!1).describe("Say what a call with this input would cost, calling nothing and charging nothing"),file:a.string().optional().describe("The path of the file it makes (without an extension it takes the result's); the same call with the same input then keeps it, calling nothing; default a folder under .allyhub/work/"),force:a.boolean().default(!1).describe("With --file: call even when the file was made from this input, and replace a file that has no record"),wait:a.boolean().default(!0).describe("Wait for a long tool (an audit, a video model); --no-wait returns its call at once"),resume:a.string().optional().describe("Wait for a call of this tool this computer made (from --no-wait, or a call that stopped waiting), and download its file")},y=(e,n)=>new $("usage",e,{exit:g.usage,...n===void 0?{}:{hint:n}}),R=e=>{const n=e.reduce((t,r)=>r.map((s,i)=>Math.max(t[i]??0,s.length)),[]);return e.map(t=>` ${t.map((r,s)=>s===t.length-1?r:r.padEnd(n[s]??0)).join(" ")}`.trimEnd())};function I(e){return w({name:e.id,summary:`${e.title}: ${e.description} Lists the tools, each a command`,input:a.strictObject({fresh:a.boolean().default(!1).describe("Read the catalog from AllyHub again, not the copy kept an hour")}),output:a.looseObject({work:a.string(),tools:a.array(a.looseObject({name:a.string()}))}),examples:[`allyhub ${e.id}`,`allyhub ${e.id} --json`]},(n,t)=>f(async()=>{const s=(await h(p(t),{refresh:n.fresh})).tools.filter(i=>i.work===e.id).sort((i,o)=>i.name.localeCompare(o.name));return{value:{work:e.id,title:e.title,tools:s.map(i=>({name:i.name,title:i.title,description:i.description,price:j(i.price),long:i.long}))},text:[`${e.title} (${b(s.length,"tool")}):`,...R(s.map(i=>[i.name,i.title,j(i.price)])),"",`Each costs credits when it worked; a failed call is free. allyhub help ${e.id} <tool> shows a tool's options; --quote prices a call first.`].join(`
|
|
3
|
+
`)}}))}const k=e=>new Intl.NumberFormat("en-US",{maximumFractionDigits:4}).format(e),V=e=>`${e.estimated?`about ${new Intl.NumberFormat("en-US",{maximumFractionDigits:2}).format(e.credits)}`:k(e.credits)} credits`;function Y(e){return e.lines.map(n=>{if(n.unknown)return` ${n.what.replace(/^0 /u,"")}: ${k(n.rate)} each, counted by the call (not in the total)`;const t=n.what==="per call"?"":` (${k(n.rate)} each)`;return` ${n.what}: ${k(n.credits)}${t}${n.estimated?", estimated":""}`})}function Z(e,n=5,t=160){const r=i=>{const o=i===void 0?"undefined":JSON.stringify(i);return o.length>t?`${o.slice(0,t-1)}…`:o},s=(i,o)=>[`${i?`${i}: `:""}${b(o.length,"item")}${o.length>n?`, the first ${String(n)}:`:":"}`,...o.slice(0,n).map((l,u)=>` [${String(u)}] ${r(l)}`)];return Array.isArray(e)?s("",e):typeof e!="object"||e===null?[r(e)]:Object.entries(e).flatMap(([i,o])=>Array.isArray(o)?s(i,o):[`${i}: ${r(o)}`])}function W(e,n){if("jobId"in e)return[`${e.tool} is still working (call ${e.jobId}).`,`Wait for it: allyhub ${n} --resume ${e.jobId}`].join(`
|
|
4
|
+
`);if(e.kept)return[`Kept ${e.file??""}: ${e.tool} made it from this same input on ${e.kept.at} (${e.gen??""}).`,"Nothing was called or charged. --force makes it again."].join(`
|
|
5
|
+
`);const t=JSON.stringify(e.output,null,2);return[t.length<=Q?t:[`Output: ${String(Math.round(Buffer.byteLength(t)/1024))} KB of JSON, in short (--json prints it whole):`,...Z(e.output)].join(`
|
|
6
|
+
`),...e.file?[`File: ${e.file}${e.replaced?" (replaced: it was made from another input)":""}`]:[],...e.words?[`Words: ${e.words} (when each word is said: a part can say a stretch of the file)`]:[],...e.gen?[`Record: ${e.gen} (move it with the file)`]:[],`Credits used: ${e.credits===void 0?"not reported":String(e.credits)}`].join(`
|
|
7
|
+
`)}const ee=e=>{const n=Math.max(0,Math.round(e));return`${String(Math.floor(n/60))}:${String(n%60).padStart(2,"0")}`},te=e=>e!==null&&typeof e=="object"&&!Array.isArray(e);async function ie(e,n){const t=e.trim().startsWith("{"),r=t?e:await J(T(n.cwd,e),"utf8").catch(i=>{throw new $("not-found",`--input: cannot read ${e}: ${i.message}`,{exit:g.notFound,hint:"Give a JSON object, or a file of one."})});let s;try{s=JSON.parse(r)}catch{s=void 0}if(!te(s))throw y(`--input: ${t?"the text":e} is not a JSON object.`,`Give '{"field": …}', or a file of it.`);return s}export function toolCommand(e){const n=`${e.work} ${e.name}`,t=z(e.input,Object.keys(d)),r=a.strictObject({...t.shape,...d,input:d.input.describe(t.inputOnly.length?`${d.input.description??""}. Fields only it gives: ${t.inputOnly.join(", ")}`:d.input.description??"")}),s=j(e.price),i=[...t.fields].filter(([,o])=>t.required.includes(o)).map(([o,l])=>`--${B(o)} <${l}>`);return{spec:{name:n,summary:e.description,input:r,output:a.looseObject({tool:a.string(),output:a.record(a.string(),a.unknown()).optional(),credits:a.number().optional(),file:a.string().optional(),gen:a.string().optional(),words:a.string().optional(),jobId:a.string().optional(),quote:a.looseObject({credits:a.number()}).nullable().optional()}),examples:[`allyhub ${[n,...i,"--quote"].join(" ")}`,`allyhub ${[n,...i].join(" ")}`]},about:{lines:[e.title,"",`Costs credits: ${s}. A call is charged once, when it worked; a failed call is free. --quote prices an input first, charging nothing.`,...e.long?["A long tool: the command waits for it (--no-wait returns its call, --resume waits again)."]:[]],value:{work:e.work,title:e.title,price:s,priceRule:e.price,long:e.long,inputSchema:e.input,outputSchema:e.output}},run:(o,l)=>f(async()=>{const u=o,D=o,O=p(l),v=await X(l),m=P(t,D,u.input===void 0?{}:await ie(u.input,l));let S=0;const A={base:v,signal:l.signal,onRunning:c=>{Date.now()-S<3e4||(S=Date.now(),l.progress(`${e.name}: working · ${ee((Date.now()-Date.parse(c.createdAt))/1e3)} (call ${c.id})`))}};if(u.resume!==void 0){if(Object.keys(m).length>0||u.quote||u.file!==void 0)throw y("--resume waits for a call as it was made: give it no input, --quote or --file.");const c=await M(O,u.resume,{...A,tool:e.name});return{value:{...c},text:W(c,n)}}if(u.quote){const c=F(e.price,e.input,[m]).calls[0];if(!c)throw new Error("No quote.");return{value:{tool:e.name,quote:c},text:[`A call${Object.keys(m).length===0?" with the defaults":""}: ${V(c)}`,...Y(c),...c.estimated?["Estimated parts are charged by what the call returns."]:[],"A call is charged once, when it worked; a failed call is free."].join(`
|
|
8
|
+
`)}}const q=G(t,m);if(q.length>0)throw y(`${e.name} needs ${q.join(", ")}.`,`allyhub help ${n} shows its options.`);const x=l.approve,N=await L(O,e.name,m,{...A,...x===void 0?{}:{approve:()=>{const c=F(e.price,e.input,[m]).calls[0];return c===void 0?Promise.resolve(!0):x(K(n,e.title,c))}},outDir:E(v,U,e.work,e.name),...u.file===void 0?{}:{file:T(l.cwd,u.file)},force:u.force,wait:u.wait});return{value:{...N},text:W(N,n)}})}}const oe=e=>h(p(e)).catch(()=>{});export const CLOUD_SOURCE={entries:[{name:"<work>",summary:"List a work's cloud tools (AllyHub's catalog), a line each with its price; allyhub help lists the works"},{name:"<work> <tool>",summary:"Run a cloud tool with the account's credits, its input as options (allyhub help <work> <tool>); --quote prices it first"}],async nouns(e){return(await h(p(e))).works.map(t=>({name:t.id,summary:`${t.title}: ${t.description}`}))},resolve:(e,n)=>f(async()=>{const[t,r]=e;if(t===void 0||t.startsWith("-"))return;let s=await oe(n),i=s?.works.find(l=>l.id===t);if(i||(s=await h(p(n),{refresh:!0}).catch(()=>s),i=s?.works.find(l=>l.id===t)),!s||!i)return;if(r===void 0||r.startsWith("-"))return{command:I(i),rest:e.slice(1),list:!0};const o=s.tools.find(l=>l.name===r);if(o?.work!==i.id)throw new $("unknown-tool",o?`${r} is not a ${i.id} tool: it is in allyhub ${o.work}.`:`No ${i.id} tool ${r}.`,{exit:g.notFound,hint:o?`allyhub ${o.work} ${r}`:`allyhub ${i.id} lists its tools.`});return{command:toolCommand(o),rest:e.slice(2),list:!1}})},upload=w({name:"upload",summary:"Upload files from this computer for a cloud tool whose input takes a URL (a presenter photo, speech audio, a reference clip), and print a signed URL for each, which works for a few hours",input:a.strictObject({files:a.array(a.string()).min(1).describe("The files: images (.jpg, .png, .webp, .gif), sound (.mp3, .wav, .m4a, .aac, .ogg, .flac) or video (.mp4, .mov, .webm), 50 MB at most")}),positional:["files"],output:a.looseObject({files:a.array(a.looseObject({file:a.string(),ok:a.boolean(),url:a.string().optional()}))}),examples:["allyhub upload assets/media/presenter.jpg"]},(e,n)=>f(async()=>{const t=await H(p(n),e.files,{base:n.cwd}),r=t.filter(o=>!o.ok),s=t.map(o=>o.ok?`${o.file}
|
|
9
9
|
${o.url}${o.expiresAt===void 0?"":` (works until ${o.expiresAt})`}`:`${o.file}
|
|
10
|
-
failed: ${o.error.message}${o.error.hint?` ${o.error.hint}`:""}`);
|
|
11
|
-
`),...i?{exit:i.error.exit}:{}}})),cloudList=w({name:"cloud list",summary:"List AllyHub's cloud works, or one work's tools, a line each with its price",input:
|
|
12
|
-
`)};const r=
|
|
10
|
+
failed: ${o.error.message}${o.error.hint?` ${o.error.hint}`:""}`);t.length>1&&s.push(r.length===0?`${b(t.length,"file")} uploaded.`:`${String(t.length-r.length)} of ${b(t.length,"file")} uploaded; ${String(r.length)} failed.`);const i=r[0];return{value:{files:t.map(o=>o.ok?{...o}:{file:o.file,ok:!1,error:{code:o.error.code,message:o.error.message,...o.error.hint?{hint:o.error.hint}:{}}})},text:s.join(`
|
|
11
|
+
`),...i?{exit:i.error.exit}:{}}})),cloudList=w({name:"cloud list",summary:"List AllyHub's cloud works, or one work's tools, a line each with its price",input:a.strictObject({work:a.string().optional().describe("The work whose tools to list; none lists the works")}),output:a.looseObject({})},(e,n)=>f(async()=>{const t=await h(p(n));if(e.work===void 0)return{value:{works:t.works},text:["AllyHub's cloud works:",...R(t.works.map(i=>[i.id,i.description]))].join(`
|
|
12
|
+
`)};const r=t.works.find(i=>i.id===e.work);if(!r)throw new $("unknown-work",`No work ${e.work}.`,{exit:g.notFound,hint:`The works are ${t.works.map(i=>i.id).join(", ")}.`});const s=await I(r).run({fresh:!1},n);return{value:s.value,text:s.text}})),cloudTool=w({name:"cloud tool",summary:"Show a cloud tool: what it does, its input (as cloud call's input takes it) and its price",input:a.strictObject({tool:a.string().describe("The tool's name, as cloud list lists it")}),output:a.looseObject({name:a.string()})},(e,n)=>f(async()=>{const t=toolCommand(await C(p(n),e.tool));return{value:{name:e.tool,summary:t.spec.summary,about:t.about?.lines??[],...t.about?.value},text:_(t.spec,t.about?.lines)}})),cloudCall=w({name:"cloud call",summary:"Run a cloud tool with the account's credits: its output, the credits used, and the file it makes with its record; waits for a long one",input:a.strictObject({tool:a.string().describe("The tool's name, as cloud list lists it"),input:a.record(a.string(),a.unknown()).default({}).describe("Its input, by its input schema (cloud tool)"),quote:d.quote,file:d.file,force:d.force,wait:d.wait,resume:d.resume}),output:a.looseObject({tool:a.string()})},(e,n)=>f(async()=>{const{tool:t,input:r,...s}=e,i=toolCommand(await C(p(n),t)),o=i.spec.input.safeParse({...s,...Object.keys(r).length?{input:JSON.stringify(r)}:{}});if(!o.success)throw y(o.error.message);const l=await i.run(o.data,n);return{...l,value:{tool:t,...l.value}}}));
|
package/dist/commands/mcp.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
|
|
2
|
-
import{McpServer as
|
|
2
|
+
import{McpServer as g}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as y}from"@modelcontextprotocol/sdk/server/stdio.js";import{CallToolRequestSchema as v,ListResourcesRequestSchema as k,ListToolsRequestSchema as S,ReadResourceRequestSchema as R}from"@modelcontextprotocol/sdk/types.js";import{z as u}from"zod";import{describeCommand as C,toolName as A}from"@allyhub-next/protocol";import{ASK_ABOVE as M,askingAbove as O,chargeQuestion as E}from"../charge.js";import{CommandError as p,defineCommand as T}from"../command.js";import{CardApp as j}from"./mcp-app.js";import{docResources as q,readDoc as N}from"./mcp-docs.js";const _="0.0.0",I=2147483647;async function P(n,a,d){const l=(e,t=!1)=>({content:[{type:"text",text:JSON.stringify(e,null,2)}],...t?{isError:t}:{}}),c=n.spec.input.safeParse(a??{});if(!c.success){const e=c.error.issues[0];return l({error:{code:"usage",message:`${e?.path.join(".")??n.spec.name}: ${e?.message??"not valid"}.`}},!0)}try{const e=await n.run(c.data,d);return l(e.value)}catch(e){const t=e instanceof p?e:new p("failed",e instanceof Error?e.message:String(e));return l({error:{code:t.code,message:t.message,...t.hint===void 0?{}:{hint:t.hint}}},!0)}}export const mcp=T({name:"mcp",summary:"The commands as MCP tools, over stdio",input:u.strictObject({ask:u.boolean().default(!0).describe("Ask the person before a cloud call that costs more than --ask-above credits, or one priced only by what it makes, where the client can ask (MCP's elicitation); --no-ask never asks"),askAbove:u.number().nonnegative().default(M).describe("The credits a call may cost without asking the person; 0 asks before every call that costs credits")}),output:u.looseObject({}),examples:["claude mcp add allyhub -- allyhub mcp","allyhub mcp --ask-above 50"],mcp:!1},async(n,a)=>{const{COMMANDS:d,MCP_COMMANDS:l}=await import("./index.js"),c=new Map([...d,...l].filter(s=>s.spec.mcp!==!1).map(s=>[A(s.spec.name),s]));console.log=console.error,console.info=console.error;const e=new g({name:"allyhub",version:_},{capabilities:{tools:{},resources:{}}}),t=new j(a),i=e.server;i.setRequestHandler(S,()=>({tools:[...t.tools(),...[...c].map(([s,o])=>{const r=Object.fromEntries(Object.entries(C(o.spec).input).filter(([m])=>m!=="$schema"));return{name:s,description:o.spec.summary,inputSchema:{type:"object",...r}}})]})),i.setRequestHandler(k,async()=>({resources:[...t.resources(),...await q(a.cwd)]})),i.setRequestHandler(R,async s=>{const{uri:o}=s.params;if(o===t.resources()[0]?.uri)return{contents:[await t.resource()]};const r=await N(a.cwd,o);if(r===void 0)throw new p("not-found",`allyhub has no resource ${o}.`);return{contents:[r]}}),i.setRequestHandler(v,(s,o)=>{if(t.has(s.params.name))return t.call(s.params.arguments);const r=c.get(s.params.name);if(!r)throw new p("unknown-tool",`allyhub has no tool ${s.params.name}.`);const m=AbortSignal.any([a.signal,o.signal]),b=n.ask&&i.getClientCapabilities()?.elicitation?.form;return P(r,s.params.arguments,{...a,signal:m,...b?{approve:O(n.askAbove,async w=>(await i.elicitInput(E(w),{signal:m,timeout:I,relatedRequestId:o.requestId})).action==="accept")}:{}})});const h=new y,f=new Promise(s=>{h.onclose=s});return await e.connect(h),process.stdin.once("end",()=>{e.close()}),a.signal.addEventListener("abort",()=>{e.close()}),await f,await t.close(),{value:{},text:""}});
|
package/dist/commands/voice.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
|
|
2
|
-
import{z as i}from"zod";import{projectSays as
|
|
3
|
-
`)}}const
|
|
2
|
+
import{z as i}from"zod";import{projectSays as y}from"@allyhub-next/project";import{declined as w,makeSay as $,quoteSays as g}from"@allyhub-next/cloud";import{EXIT as v}from"@allyhub-next/protocol";import{CommandError as b,defineCommand as j}from"../command.js";import{projectRoot as k}from"../project.js";import{cloudOf as S,cloudWork as q,plural as m}from"./cloud.js";import{dir as O}from"../fields.js";const h=a=>Math.round(a*1e6)/1e6;export const voice=j({name:"voice",summary:"Make the voice files a project's say(text) parts need, with their cloud voice tool, one per say that has none (assets/media/gen/say/<hash>, its words and its record); --quote prices them first",input:i.strictObject({item:i.string().optional().describe("Only this item's says: its id, a path into it, or a folder of items"),dir:O,quote:i.boolean().default(!1).describe("Say what making the missing files would cost, making nothing and charging nothing")}),positional:["item"],output:i.looseObject({says:i.number(),missing:i.array(i.looseObject({part:i.string(),stem:i.string()})).optional(),made:i.array(i.looseObject({part:i.string(),file:i.string()})).optional(),credits:i.number()}),examples:["allyhub voice --quote","allyhub voice launch/film"]},async(a,n)=>{const p=await k(n.cwd,a.dir),c=await y(p,a.item===void 0?{}:{piece:a.item});if(a.item!==void 0&&c.pieces.length===0)throw new b("no-item",`No video ${a.item} in the project.`,{exit:v.notFound});const o=c.says.filter(l=>l.file===void 0),u=`Every say has its file (${m(c.says.length,"say")}). Nothing to make.`;return await q(async()=>{const l=S(n);if(a.quote){const e=await g(l,o),s=t=>{const r=e.says[t]?.credits;return r===void 0?{}:{credits:r}};return{value:{says:c.says.length,missing:o.map((t,r)=>({piece:t.piece,part:t.part,tool:t.tool,...t.voice===void 0?{}:{voice:t.voice},...t.params===void 0?{}:{params:t.params},characters:t.text.length,stem:t.stem,...s(r)})),credits:e.credits,estimated:e.estimated},text:o.length===0?u:[`${m(o.length,"say")} without a file:`,...o.map((t,r)=>` ${t.piece} · ${t.part}: ${m(t.text.length,"character")}${s(r).credits===void 0?"":`, ${String(h(s(r).credits??0))} credits`}`),`${e.estimated?"About ":""}${String(e.credits)} credits in all. Nothing was charged; allyhub voice makes them.`].join(`
|
|
3
|
+
`)}}const d=[];if(n.approve!==void 0&&o.length>0){const e=await g(l,o);if(!await n.approve({tool:"voice",title:`${m(o.length,"voice file")} with ${e.titles.join(", ")}`,credits:e.credits,estimated:e.estimated,unknown:e.unknown}))throw w("voice")}for(const e of o){n.progress(`${e.piece} · ${e.part}: ${e.tool}…`);const s=await $(l,p,e,{base:p,signal:n.signal});d.push({piece:e.piece,part:e.part,...s})}const f=h(d.reduce((e,s)=>e+s.credits,0));return{value:{says:c.says.length,made:d,kept:c.says.length-o.length,credits:f},text:d.length===0?u:[`Made ${m(d.length,"file")}:`,...d.map(e=>` ${e.file} (${e.piece} · ${e.part}, ${String(h(e.seconds))} s)`),`Credits used: ${String(f)}.`].join(`
|
|
4
4
|
`)}})});
|
package/dist/main.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
|
|
2
|
-
import{readFileSync as
|
|
2
|
+
import{readFileSync as R}from"node:fs";import{EXIT as m,describeCommand as M}from"@allyhub-next/protocol";import{readArgs as T}from"./args.js";import{studioApprove as H}from"./charge.js";import{CommandError as h}from"./command.js";import{COMMAND_SOURCES as j,COMMANDS as x}from"./commands/index.js";import{commandHelp as A,listHelp as J,workHelp as G}from"./help.js";import{sdkDocs as U}from"./sdk-docs.js";import{WORKS as W,cloudNouns as F,workNamed as K,workTitle as E}from"./works.js";const N=JSON.parse(R(new URL("../package.json",import.meta.url),"utf8")).version,L={stdout:t=>process.stdout.write(t),stderr:t=>process.stderr.write(t),cwd:process.cwd(),env:process.env};export function findCommand(t,o=x){let i;for(const c of o){const u=c.spec.name.split(" ");u.every((r,a)=>t[a]===r)&&u.length>(i?.length??0)&&(i={command:c,length:u.length})}return i?{command:i.command,rest:t.slice(i.length)}:{rest:[...t]}}export async function resolveCommand(t,o,i=x,c=j){const u=findCommand(t,i);if(u.command)return u;for(const r of c){const a=await r.resolve(t,o);if(a)return a}return u}const D=t=>({...M(t.spec),...t.about?.value});export async function main(t,o=L,i=x,c=j){const u=t.includes("--json"),r=t.filter(n=>n!=="--json"),a=(n,e)=>{o.stdout(u?`${JSON.stringify(n,null,2)}
|
|
3
3
|
`:`${e}
|
|
4
|
-
`)},S=i.map(n=>n.spec),
|
|
5
|
-
`)},signal:
|
|
6
|
-
`):
|
|
4
|
+
`)},S=i.map(n=>n.spec),v=new AbortController,$=H(o.env,o.cwd,v.signal),y={cwd:o.cwd,env:o.env,progress:n=>{o.stderr(`${n}
|
|
5
|
+
`)},signal:v.signal,...$===void 0?{}:{approve:$}};if(r[0]==="--version"||r[0]==="-v")return a({version:N},N),m.ok;if(r.length===0||r[0]==="help"||r[0]==="--help"||r[0]==="-h"){const n=r.slice(1),e=await U(o.cwd).catch(()=>{}),k=async()=>{const s=await Promise.all(c.map(l=>l.nouns(y).catch(()=>{})));return s.some(l=>l===void 0)?void 0:s.flatMap(l=>l??[])};if(n.length===0){const s=await k();return a({version:N,docs:e?.dir,works:W.map(l=>({...l,title:E(l,s)})),commands:S.map(M),made:[...c.flatMap(l=>l.entries),...s??[]]},J(S,c,s,e?.dir)),m.ok}const d=n.length===1?K(n[0]??""):void 0;if(d){const s=d.cloud===void 0?[]:await k();return a({...d,title:E(d,s),...d.cloud===void 0?{}:{cloudWorks:s&&F(d,s)},docsDir:e?.dir},G(d,S,c,e?.dir,s)),m.ok}let p;try{p=await resolveCommand(n,y,i,c)}catch(s){return g(s)}const{command:f,rest:I}=p;return f&&p.list===!0?await O(f,I):!f||I.length>0?g(new h("unknown-command",`allyhub has no command "${n.join(" ")}".`,{exit:m.usage,hint:"allyhub help lists them and the works."})):(a(D(f),A(f.spec,f.about?.lines)),m.ok)}let C;try{C=await resolveCommand(r,y,i,c)}catch(n){return g(n)}const{command:w,rest:b}=C;if(!w)return g(new h("unknown-command",`allyhub has no command "${r[0]??""}".`,{exit:m.usage,hint:"allyhub help lists them."}));if(b.includes("--help")||b.includes("-h"))return a(D(w),A(w.spec,w.about?.lines)),m.ok;return await O(w,b);async function O(n,e){const k=()=>{v.abort(new h("interrupted","Stopped.",{exit:m.interrupted}))};process.once("SIGINT",k);try{const d=T(n.spec,e),p=await n.run(d,y);return a(p.value,p.text),p.exit??m.ok}catch(d){return g(d)}finally{process.off("SIGINT",k)}}function g(n){const e=n instanceof h?n:v.signal.aborted?new h("interrupted","Stopped.",{exit:m.interrupted}):new h("failed",n instanceof Error?n.message:String(n));return u?o.stdout(`${JSON.stringify({error:{code:e.code,message:e.message,...e.hint?{hint:e.hint}:{}}},null,2)}
|
|
6
|
+
`):o.stderr(`${e.message}${e.hint?`
|
|
7
7
|
${e.hint}`:""}
|
|
8
8
|
`),e.exit}}
|