ryugi-artifacts 1.70.3 → 1.71.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -12
- package/dist/cli.cjs +3 -3
- package/dist/comment-threads.cjs +52 -1
- package/dist/output-bootstrap.cjs +626 -8
- package/dist/server.cjs +1 -1
- package/dist/viewer-lib/index.js +1 -1
- package/package.json +6 -3
- /package/bin/{ryugi-artifacts.cjs → ryugi.cjs} +0 -0
package/README.md
CHANGED
|
@@ -9,6 +9,10 @@ npx ryugi-artifacts # open the library of the current project
|
|
|
9
9
|
npx ryugi-artifacts monitor # list running project servers
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
+
Installed globally (`npm install -g ryugi-artifacts`), the command is `ryugi`;
|
|
13
|
+
`ryugi-artifacts` stays as an alias. npx needs the package name, so
|
|
14
|
+
`npx ryugi-artifacts` is the npx form.
|
|
15
|
+
|
|
12
16
|
The server reads `.ryugi/artifacts/` in the selected project. Ryugi's skills
|
|
13
17
|
start it for you; this package also runs standalone. Node.js is required.
|
|
14
18
|
|
|
@@ -28,12 +32,12 @@ Each operation declares its supported formats; unsupported modes fail before wor
|
|
|
28
32
|
starts. There is no alternate legacy protocol or release gate.
|
|
29
33
|
|
|
30
34
|
```sh
|
|
31
|
-
ryugi
|
|
32
|
-
ryugi
|
|
33
|
-
ryugi
|
|
34
|
-
ryugi
|
|
35
|
-
ryugi
|
|
36
|
-
ryugi
|
|
35
|
+
ryugi check --artifact document/plan --format brief
|
|
36
|
+
ryugi publish --list --limit 10 --visibility private --format json
|
|
37
|
+
ryugi get https://ryugi.innei.dev/a/ID --format brief
|
|
38
|
+
ryugi get ID --detail --snapshot TOKEN --format json
|
|
39
|
+
ryugi get ID --download --out ./new-download --format json
|
|
40
|
+
ryugi config --output-format brief --project
|
|
37
41
|
```
|
|
38
42
|
|
|
39
43
|
Selection order is explicit option, `RYUGI_ARTIFACTS_FORMAT`, project
|
|
@@ -54,7 +58,7 @@ Review reads are read-only. Preview a bounded page, read complete evidence, then
|
|
|
54
58
|
explicitly acknowledge its receipt after using that evidence:
|
|
55
59
|
|
|
56
60
|
For a complete review in one request, run
|
|
57
|
-
`ryugi
|
|
61
|
+
`ryugi comment list --artifact document/plan --sections all --detail`.
|
|
58
62
|
Documents include threads/asks; artboards include threads/groups/rounds. Each
|
|
59
63
|
collection retains its own page, snapshot and continuation. Only a complete
|
|
60
64
|
unread thread page issues a receipt; state collections do not. Follow every
|
|
@@ -62,11 +66,11 @@ relevant continuation before concluding. Filters, fields and existing cursors
|
|
|
62
66
|
or snapshots require the single-collection form below.
|
|
63
67
|
|
|
64
68
|
```sh
|
|
65
|
-
ryugi
|
|
66
|
-
ryugi
|
|
67
|
-
ryugi
|
|
68
|
-
ryugi
|
|
69
|
-
ryugi
|
|
69
|
+
ryugi comment list --artifact document/plan --section threads --format brief
|
|
70
|
+
ryugi comment read --artifact document/plan --thread THREAD --detail
|
|
71
|
+
ryugi comment ack --artifact document/plan --receipt RECEIPT
|
|
72
|
+
ryugi changes --artifact document/plan --detail
|
|
73
|
+
ryugi changes ack --artifact document/plan --receipt RECEIPT
|
|
70
74
|
```
|
|
71
75
|
|
|
72
76
|
`--all` and projected reads never issue receipts. Asks, groups and rounds are
|
package/dist/cli.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";var Kn=Object.create;var Yt=Object.defineProperty;var Qn=Object.getOwnPropertyDescriptor;var Zn=Object.getOwnPropertyNames;var eo=Object.getPrototypeOf,to=Object.prototype.hasOwnProperty;var ro=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Zn(t))!to.call(e,o)&&o!==r&&Yt(e,o,{get:()=>t[o],enumerable:!(n=Qn(t,o))||n.enumerable});return e};var S=(e,t,r)=>(r=e!=null?Kn(eo(e)):{},ro(t||!e||!e.__esModule?Yt(r,"default",{value:e,enumerable:!0}):r,e));var Kt=require("node:util");var f=class extends Error{constructor(r,n="failed",o){super(r.message);this.error=r;this.kind=n;this.raw=o}error;kind;raw};function _e(e){if(e instanceof f)return e.error;let t=e,r=t?.fields;return{code:typeof r?.code=="string"?`E_${r.code.toUpperCase().replace(/^E_/,"")}`:"E_COMMAND_FAILED",message:typeof t?.message=="string"&&t.message?t.message:typeof r?.message=="string"?r.message:String(e),...typeof r?.status=="number"?{httpStatus:r.status}:{},...r&&Object.keys(r).length?{details:r}:{}}}function ce(e,t=!1){switch(e.kind){case"succeeded":return{outcome:t?"attention":"success",code:0};case"validation_failed":return{outcome:"attention",code:3};case"pending":return{outcome:"pending",code:4};case"action_required":return{outcome:"attention",code:2};case"partial":return{outcome:"partial",code:5};case"failed":return{outcome:"error",code:1};case"interrupted":return{outcome:"error",code:e.signal==="SIGINT"?130:143}}}function Jt(e,t,r,n){return!e||typeof e!="object"||Array.isArray(e)?e:Object.fromEntries(Object.entries(e).filter(([o])=>t.includes(o)?!0:(n.push({path:`${r}.${o}`,reason:"fields"}),!1)))}function ht(e,t,r,n){let o=[...t.coverage.omitted??[]],s=t.data;if(r.fields){let i=[...new Set([...r.fields,...n.requiredFields??[]])];if(n.collection&&s&&typeof s=="object"){let a=s,u=a[n.collection];s={...a,[n.collection]:Array.isArray(u)?u.map((p,d)=>Jt(p,i,`data.${n.collection}.${d}`,o)):u}}else s=Jt(s,i,"data",o)}return{schema:"ryugi.cli/v1",command:e,outcome:ce(t.completion,t.warnings.length>0).outcome,data:s,...t.coverage.page?{page:t.coverage.page}:{},...o.length?{omitted:o}:{},...t.effects.length?{effects:t.effects}:{},...t.warnings.length?{warnings:t.warnings}:{},...t.actions.length?{next:t.actions}:{},...t.completion.kind==="failed"?{error:t.completion.error}:t.completion.kind==="interrupted"?{error:{code:"E_INTERRUPTED",message:`Command interrupted by ${t.completion.signal}.`,details:{signal:t.completion.signal}}}:{}}}var Xt={format:{type:"string",value:"<brief|table|json|jsonl|raw>",help:"Output format (default: brief)"},json:{type:"boolean",help:"Shorthand for --format json"},detail:{type:"boolean",help:"Read complete evidence for the selected object or page"},fields:{type:"string",value:"<fields>",help:"Select public output fields, separated by commas"},quiet:{type:"boolean",help:"Print the command's declared scalar only"},verbose:{type:"boolean",help:"Include diagnostic details on stderr"}};function yt(e,t){let r={};for(let n=0;n<e.length;n++){let o=e[n];if(o==="--")break;if(!o.startsWith("--"))continue;let s=o.indexOf("="),i=o.slice(2,s<0?void 0:s),a=i==="source"?"boolean":t[i]?.type;a==="string"?r[i]=s<0?e[++n]??"":o.slice(s+1):a==="boolean"&&(r[i]=!0)}return r}function bt(e,t,r=process.env){let n=yt(e,t),o=["format","json","quiet","source"].filter(l=>n[l]!==void 0),s=r.RYUGI_ARTIFACTS_FORMAT??"brief",i=n.format??(n.json?"json":n.quiet?"quiet":n.source?"source":s),u=["brief","table","json","jsonl","raw","source","quiet"].includes(i),p={format:u?i:"brief",detail:!!n.detail||!!n.source,verbose:!!n.verbose},d;return o.length>1?d=new f({code:"E_OPTION_CONFLICT",message:"Choose one of --format, --json, --quiet or --source."}):(!u||!o.length&&!["brief","json","jsonl"].includes(s))&&(d=new f({code:"E_FORMAT_UNSUPPORTED",message:`Unknown output format: ${String(i)}`})),typeof n.fields=="string"&&(p.fields=n.fields.split(",").map(l=>l.trim()),p.fields.some(l=>!l)&&(d=new f({code:"E_ARGUMENT_INVALID",message:"--fields requires comma-separated field names."}))),{options:p,...d?{error:d}:{}}}var ue=S(require("node:fs"),1),zt=S(require("node:os"),1),M=S(require("node:path"),1),w=class extends Error{constructor(r,n={},o=1){super(r);this.fields=n;this.code=o}fields;code};function no(e){let t="";try{t=ue.default.realpathSync(zt.default.homedir())}catch{}let r=[];for(let n=e;r.push(n),!(ue.default.existsSync(M.default.join(n,".git"))&&(n!==t||e===t));n=M.default.dirname(n))if(M.default.dirname(n)===n)return e;return r.find(n=>ue.default.existsSync(M.default.join(n,".ryugi","artifacts")))??r.at(-1)}function z(e){let t;try{if(t=ue.default.realpathSync(M.default.resolve(e)),!ue.default.statSync(t).isDirectory())throw new Error("Not a directory")}catch{throw new w(`Project directory not found: ${e}`)}t=no(t);let r=M.default.join(t,".ryugi","artifacts"),n=M.default.join(r,".state");return{project:t,root:r,state:n,pid:M.default.join(n,"server.pid"),log:M.default.join(n,"server.log"),serverId:M.default.join(n,"server-instance-id"),info:M.default.join(n,"server-info"),version:M.default.join(n,"server-version"),owners:M.default.join(n,"owners"),agent:M.default.join(n,"agent"),stopped:M.default.join(n,"server-stopped"),lock:M.default.join(n,"start.lock")}}var ye=()=>process.env.RYUGI_ARTIFACTS_COMMAND||"ryugi
|
|
2
|
+
"use strict";var Kn=Object.create;var Yt=Object.defineProperty;var Qn=Object.getOwnPropertyDescriptor;var Zn=Object.getOwnPropertyNames;var eo=Object.getPrototypeOf,to=Object.prototype.hasOwnProperty;var ro=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Zn(t))!to.call(e,o)&&o!==r&&Yt(e,o,{get:()=>t[o],enumerable:!(n=Qn(t,o))||n.enumerable});return e};var S=(e,t,r)=>(r=e!=null?Kn(eo(e)):{},ro(t||!e||!e.__esModule?Yt(r,"default",{value:e,enumerable:!0}):r,e));var Kt=require("node:util");var f=class extends Error{constructor(r,n="failed",o){super(r.message);this.error=r;this.kind=n;this.raw=o}error;kind;raw};function _e(e){if(e instanceof f)return e.error;let t=e,r=t?.fields;return{code:typeof r?.code=="string"?`E_${r.code.toUpperCase().replace(/^E_/,"")}`:"E_COMMAND_FAILED",message:typeof t?.message=="string"&&t.message?t.message:typeof r?.message=="string"?r.message:String(e),...typeof r?.status=="number"?{httpStatus:r.status}:{},...r&&Object.keys(r).length?{details:r}:{}}}function ce(e,t=!1){switch(e.kind){case"succeeded":return{outcome:t?"attention":"success",code:0};case"validation_failed":return{outcome:"attention",code:3};case"pending":return{outcome:"pending",code:4};case"action_required":return{outcome:"attention",code:2};case"partial":return{outcome:"partial",code:5};case"failed":return{outcome:"error",code:1};case"interrupted":return{outcome:"error",code:e.signal==="SIGINT"?130:143}}}function Jt(e,t,r,n){return!e||typeof e!="object"||Array.isArray(e)?e:Object.fromEntries(Object.entries(e).filter(([o])=>t.includes(o)?!0:(n.push({path:`${r}.${o}`,reason:"fields"}),!1)))}function ht(e,t,r,n){let o=[...t.coverage.omitted??[]],s=t.data;if(r.fields){let i=[...new Set([...r.fields,...n.requiredFields??[]])];if(n.collection&&s&&typeof s=="object"){let a=s,u=a[n.collection];s={...a,[n.collection]:Array.isArray(u)?u.map((p,d)=>Jt(p,i,`data.${n.collection}.${d}`,o)):u}}else s=Jt(s,i,"data",o)}return{schema:"ryugi.cli/v1",command:e,outcome:ce(t.completion,t.warnings.length>0).outcome,data:s,...t.coverage.page?{page:t.coverage.page}:{},...o.length?{omitted:o}:{},...t.effects.length?{effects:t.effects}:{},...t.warnings.length?{warnings:t.warnings}:{},...t.actions.length?{next:t.actions}:{},...t.completion.kind==="failed"?{error:t.completion.error}:t.completion.kind==="interrupted"?{error:{code:"E_INTERRUPTED",message:`Command interrupted by ${t.completion.signal}.`,details:{signal:t.completion.signal}}}:{}}}var Xt={format:{type:"string",value:"<brief|table|json|jsonl|raw>",help:"Output format (default: brief)"},json:{type:"boolean",help:"Shorthand for --format json"},detail:{type:"boolean",help:"Read complete evidence for the selected object or page"},fields:{type:"string",value:"<fields>",help:"Select public output fields, separated by commas"},quiet:{type:"boolean",help:"Print the command's declared scalar only"},verbose:{type:"boolean",help:"Include diagnostic details on stderr"}};function yt(e,t){let r={};for(let n=0;n<e.length;n++){let o=e[n];if(o==="--")break;if(!o.startsWith("--"))continue;let s=o.indexOf("="),i=o.slice(2,s<0?void 0:s),a=i==="source"?"boolean":t[i]?.type;a==="string"?r[i]=s<0?e[++n]??"":o.slice(s+1):a==="boolean"&&(r[i]=!0)}return r}function bt(e,t,r=process.env){let n=yt(e,t),o=["format","json","quiet","source"].filter(l=>n[l]!==void 0),s=r.RYUGI_ARTIFACTS_FORMAT??"brief",i=n.format??(n.json?"json":n.quiet?"quiet":n.source?"source":s),u=["brief","table","json","jsonl","raw","source","quiet"].includes(i),p={format:u?i:"brief",detail:!!n.detail||!!n.source,verbose:!!n.verbose},d;return o.length>1?d=new f({code:"E_OPTION_CONFLICT",message:"Choose one of --format, --json, --quiet or --source."}):(!u||!o.length&&!["brief","json","jsonl"].includes(s))&&(d=new f({code:"E_FORMAT_UNSUPPORTED",message:`Unknown output format: ${String(i)}`})),typeof n.fields=="string"&&(p.fields=n.fields.split(",").map(l=>l.trim()),p.fields.some(l=>!l)&&(d=new f({code:"E_ARGUMENT_INVALID",message:"--fields requires comma-separated field names."}))),{options:p,...d?{error:d}:{}}}var ue=S(require("node:fs"),1),zt=S(require("node:os"),1),M=S(require("node:path"),1),w=class extends Error{constructor(r,n={},o=1){super(r);this.fields=n;this.code=o}fields;code};function no(e){let t="";try{t=ue.default.realpathSync(zt.default.homedir())}catch{}let r=[];for(let n=e;r.push(n),!(ue.default.existsSync(M.default.join(n,".git"))&&(n!==t||e===t));n=M.default.dirname(n))if(M.default.dirname(n)===n)return e;return r.find(n=>ue.default.existsSync(M.default.join(n,".ryugi","artifacts")))??r.at(-1)}function z(e){let t;try{if(t=ue.default.realpathSync(M.default.resolve(e)),!ue.default.statSync(t).isDirectory())throw new Error("Not a directory")}catch{throw new w(`Project directory not found: ${e}`)}t=no(t);let r=M.default.join(t,".ryugi","artifacts"),n=M.default.join(r,".state");return{project:t,root:r,state:n,pid:M.default.join(n,"server.pid"),log:M.default.join(n,"server.log"),serverId:M.default.join(n,"server-instance-id"),info:M.default.join(n,"server-info"),version:M.default.join(n,"server-version"),owners:M.default.join(n,"owners"),agent:M.default.join(n,"agent"),stopped:M.default.join(n,"server-stopped"),lock:M.default.join(n,"start.lock")}}var ye=()=>process.env.RYUGI_ARTIFACTS_COMMAND||"ryugi",le=/^(artboard|document|html|whiteboard)\/[a-z0-9][a-z0-9-]*$/,je="--artifact must be <type>/<id>: type artboard, document or html, id of lowercase letters, digits and hyphens";var Te="ryugi",te={...Xt,"project-dir":{type:"string",value:"<path>",help:"Project directory (default: current directory)"}},Qt={help:{type:"boolean",short:"h",help:"Show this help"}};function be(e,t,r=0){let n=Object.fromEntries(Object.entries({...te,...t}).map(([o,{type:s,short:i}])=>[o,i?{type:s,short:i}:{type:s}]));try{let o=(0,Kt.parseArgs)({args:e,options:n,allowPositionals:r>0,strict:!0});if(o.positionals.length>r)throw new w(`Unknown argument: ${o.positionals[r]}`);return{values:o.values,positionals:o.positionals,projectDir:o.values["project-dir"]??process.cwd()}}catch(o){if(o instanceof w)throw o;let s=/'([^']+)'/.exec(o.message)?.[1];throw new w(s?`Unknown argument: ${s.split(" ")[0]}`:o.message)}}function Zt(e){let t=e.indexOf("--");return(t===-1?e:e.slice(0,t)).some(r=>r==="--help"||r==="-h")}function wt(e){let t=Math.max(...e.map(([r])=>r.length))+2;return e.map(([r,n])=>` ${r.padEnd(t)}${n.replaceAll(`
|
|
3
3
|
`,`
|
|
4
4
|
${" ".repeat(t)}`)}`.trimEnd()).join(`
|
|
5
5
|
`)}function er(e){return Object.entries(e).filter(([,t])=>t.help!==void 0).map(([t,r])=>[`${r.short?`-${r.short}, `:""}--${t}${r.value?` ${r.value}`:""}`,r.help])}function tr(e){return[(e.usage??["[options]"]).map((r,n)=>`${n?" ":"Usage: "}${Te} ${e.name} ${r}`).join(`
|
|
@@ -62,7 +62,7 @@ function run(urls) {
|
|
|
62
62
|
`)}function Fs(e){let t={...process.env,ARTIFACTS_HOST:e.host,ARTIFACTS_URL_HOST:e.urlHost};process.env.RYUGI_ARTIFACTS_COMMAND&&(t.RYUGI_ARTIFACTS_LAUNCHER=process.env.RYUGI_ARTIFACTS_COMMAND);for(let r of["RYUGI_ARTIFACTS_OWNER","RYUGI_ARTIFACTS_VERSION","RYUGI_ARTIFACTS_COMMAND","ARTIFACTS_OPEN_CMD","ARTIFACTS_ROOT"])delete t[r];return t}var Ms=e=>e.split(`
|
|
63
63
|
`).find(t=>t.includes('"server-started"')),Us=e=>e.split(`
|
|
64
64
|
`).find(t=>t.includes('"server-error"'));async function Gs(e,t,r){let n=await fetch(Vt(e,"/api/hub/projects"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({dir:t.project,...r?{open:r}:{},...r&&process.env.ARTIFACTS_OPEN_CMD?{openCmd:process.env.ARTIFACTS_OPEN_CMD}:{}}),signal:AbortSignal.timeout(Is)});if(!n.ok)throw new w(`The artifacts server refused this project: ${await n.text()}`)}async function Ut(e,t){if(t.signal?.throwIfAborted(),e.artifact!==void 0&&!le.test(e.artifact))throw new w(je);if(e.port!==void 0&&(!/^\d+$/.test(e.port)||Number(e.port)<1||Number(e.port)>65535))throw new w("--port must be a port number");e.urlHost||=e.host==="127.0.0.1"||e.host==="localhost"?"localhost":e.host,process.umask(63);let r=z(e.projectDir),n=pe();dr(n.home),U.default.mkdirSync(r.state,{recursive:!0}),U.default.existsSync(dt.default.join(r.state,".gitignore"))||U.default.writeFileSync(dt.default.join(r.state,".gitignore"),`*
|
|
65
|
-
`);let o=process.env.RYUGI_ARTIFACTS_VERSION||"1.
|
|
65
|
+
`);let o=process.env.RYUGI_ARTIFACTS_VERSION||"1.71.0",s=fe(n.projects).some(p=>p.dir===r.project),i=async(p,d)=>{Ls(r);let l=e.open&&!e.library&&(!d||!s);await Gs(p,r,l?e.artifact??!0:void 0);let m=js(p,r,e.artifact);d&&(m.reused=!0);let C=await Ts(m,p,r,e.artifact),T=xn(r.project);if(t.signal?.throwIfAborted(),e.library&&e.open&&(process.env.ARTIFACTS_OPEN_CMD?await new Promise(j=>(0,Oe.execFile)(process.env.ARTIFACTS_OPEN_CMD,[p.url],()=>j())):await Dt(p.url,[p.url]).catch(j=>t.log(j.message,"stderr"))),await t.ready(T?{...C,loginHint:T}:C),d&&s&&process.platform==="darwin"&&e.open&&e.openExisting&&e.artifact&&!process.env.ARTIFACTS_OPEN_CMD){let j=C.link;await Dt(typeof C.cloudLink=="string"?C.cloudLink:j,[j]).catch(D=>t.log(D.message,"stderr"))}};if(!await $s(n.lock))throw new w("Another start is still starting the artifacts server; retry in a moment");let a=!0,u=()=>{if(a){a=!1;try{U.default.rmdirSync(n.lock)}catch{}}};try{t.signal?.throwIfAborted();let p=Ps(n),d=Pn(n);if(p&&!d){for(let k=0;k<Os&&J(p)&&!d;k+=100)await me(100),d=Pn(n);!d&&J(p)&&await Nn(p,"stopping artifacts server")}if(p&&d){let k=W(n.version)??"",y=Tn(k,o),c=(d.host??"127.0.0.1")!==e.host||(d.urlHost??"localhost")!==e.urlHost||(d.cloudOrigin??Ln)!==xs(process.env)||e.port!==void 0&&String(d.port)!==e.port;if(y!=="replace"&&!c&&await Ns(d))return u(),await i(d,!0),0;await Nn(p,"running artifacts server")}await Ds(),U.default.rmSync(n.info,{force:!0});let l=Dn.default.randomBytes(24).toString("hex");U.default.writeFileSync(n.serverId,`${l}
|
|
66
66
|
`),U.default.writeFileSync(n.version,`${o}
|
|
67
67
|
`);let C=[dt.default.join(__dirname,"server.cjs"),`--artifacts-server-id=${l}`,...e.port?[`--port=${e.port}`]:[]],T=Fs(e);if(e.foreground||!e.background&&!!process.env.CODEX_CI){let k=(0,Oe.spawn)(process.execPath,C,{env:T,stdio:["ignore","pipe","pipe"]});U.default.writeFileSync(n.pid,`${k.pid}
|
|
68
68
|
`);let y=()=>{k.kill("SIGTERM")};if(t.signal)t.signal.addEventListener("abort",y,{once:!0});else for(let v of["SIGINT","SIGTERM"])process.on(v,y);Gt.default.createInterface({input:k.stderr}).on("line",v=>t.log(v,"stderr"));let c=new Promise(v=>k.on("close",I=>v(I??1))),h=!1,g;Gt.default.createInterface({input:k.stdout}).on("line",v=>{let I;try{I=JSON.parse(v)}catch{t.log(v,"stdout");return}if(I.type!=="server-started"||h){t.event?t.event(I):I.type==="server-error"||I.type==="error"?t.failure(I):t.log(JSON.stringify(I),"stderr");return}h=!0,u(),g=i(I,!1),g.catch(()=>y())});try{let v=await c;return await g,v}finally{if(t.signal)t.signal.removeEventListener("abort",y);else for(let v of["SIGINT","SIGTERM"])process.removeListener(v,y)}}try{U.default.renameSync(n.log,`${n.log}.1`)}catch{}let D=U.default.openSync(n.log,"w"),b=(0,Oe.spawn)(process.execPath,C,{env:T,detached:!0,windowsHide:!0,stdio:["ignore",D,D]});U.default.closeSync(D),b.unref(),U.default.writeFileSync(n.pid,`${b.pid}
|
|
@@ -70,4 +70,4 @@ function run(urls) {
|
|
|
70
70
|
`)};if(W(e.pid)===null)return{status:"not_running"};let r=Number(W(e.pid)),n=W(e.serverId)??"";if(!Number.isInteger(r)||r<=0||!/^[\w-]{32,64}$/.test(n)||!Se(r,n))return ee.default.rmSync(e.pid,{force:!0}),ee.default.rmSync(e.serverId,{force:!0}),t("stale_pid"),{status:"stale_pid"};try{process.kill(r,"SIGTERM")}catch{}if(!await re(r,7e3)){try{process.kill(r,"SIGKILL")}catch{}await re(r,1e3)}if(J(r))return{status:"failed",error:"process still running"};for(let o of[e.pid,e.serverId])ee.default.rmSync(o,{force:!0});return t("stop"),{status:"stopped"}}var Un={name:"stop",summary:"Stop this machine's artifacts server; the artifacts are kept",usage:["[options]"],options:{},semantic:e=>_({id:"stop",mode:"finite",output:{formats:["brief","json","jsonl","quiet"],scalar:t=>t.status},async run(){let t=await qs();return x({status:t.status==="stopped"?"stopped":t.status==="failed"?"failed":"unchanged",reason:t.status,scope:"machine",artifacts:"kept"},t.status==="failed"?{kind:"failed",error:{code:"E_SERVER_STOP_FAILED",message:t.error}}:{kind:"succeeded"})},present:Ws},e)};var Wt=require("node:child_process"),Bn=S(require("node:fs"),1);var pt=S(require("node:fs"),1),Gn=S(require("node:os"),1),ft=S(require("node:path"),1);function Vn(e,t){let r=e.split(".").map(Number),n=t.split(".").map(Number);for(let o=0;o<3;o++)if(r[o]!==n[o])return r[o]>n[o];return!1}var Wn=e=>ft.default.join(e.XDG_CACHE_HOME||ft.default.join(Gn.default.homedir(),".cache"),"ryugi","artifacts","latest.json");function qn(e,t,r){try{pt.default.mkdirSync(ft.default.dirname(e),{recursive:!0});let n=`${e}.${process.pid}`;pt.default.writeFileSync(n,JSON.stringify({version:t,checkedAt:r})),pt.default.renameSync(n,e)}catch{}}var H="ryugi-artifacts",mt=["npm","pnpm","yarn","bun"],Hs=[["npx",["/_npx/"]],["pnpm dlx",["/pnpm/dlx/","/.pnpm-store/dlx/"]],["bunx",["/bunx-","/.bun/install/cache/"]]],Bs=[["pnpm",["/pnpm/global/"]],["yarn",["/yarn/global/"]],["bun",["/.bun/install/global/"]],["npm",[`/lib/node_modules/${H}/`,`/npm/node_modules/${H}/`]]];function Ys(e,t){if(t.RYUGI_ARTIFACTS_COMMAND)return{kind:"launcher"};let r=e;try{r=Bn.default.realpathSync(e)}catch{}let n=r.replaceAll("\\","/").toLowerCase(),o=s=>s.some(i=>n.includes(i));for(let[s,i]of Hs)if(o(i))return{kind:"transient",runner:s};for(let[s,i]of Bs)if(o(i))return{kind:"global",pm:s};return n.includes("/node_modules/")?{kind:"unknown"}:{kind:"local"}}function Hn(e,t){let r=`${H}@${t}`;return{cmd:e,args:e==="npm"?["install","-g",r]:e==="yarn"?["global","add",r]:["add","-g",r]}}var he=({cmd:e,args:t})=>[e,...t].join(" ");async function Js(e){let t=e.endsWith("/")?e:`${e}/`;try{let r=await fetch(new URL(`${H}/latest`,t),{signal:AbortSignal.timeout(1e4)}),{version:n}=await r.json();if(r.ok&&typeof n=="string"&&/^\d+\.\d+\.\d+/.test(n))return n;throw new Error(`registry returned ${r.status}`)}catch(r){throw new w(`Could not get the latest ${H} version from ${t}: ${r.message}`)}}function Xs(e,t){return e.kind==="transient"?`You ran ${H} through ${e.runner}, which keeps no install to update. Run \`${e.runner} ${H}@latest\` to get ${t}.`:e.kind==="local"?"This is a local build from a Ryugi checkout. Update it with `git pull`, then `pnpm build` in artifacts/.":e.kind==="launcher"?`The Ryugi skill runs ${H} through its launcher, which moves to ${t} within a day of its release.`:null}var gt=class extends w{};async function zs(e,t={}){if(e.pm!==void 0&&!mt.includes(e.pm))throw new w(`--pm must be one of ${mt.join(", ")}`);let r=e.pm?{kind:"global",pm:e.pm}:Ys(e.file,e.env),n=await Js(e.registry);qn(Wn(e.env),n,Date.now());let o={type:"update-check",current:e.current,latest:n,install:r.kind};if(!Vn(n,e.current))return{...o,upToDate:!0,command:null};if(r.kind==="unknown"){let p=mt.map(d=>` ${he(Hn(d,n))}`).join(`
|
|
71
71
|
`);throw new gt(`Could not tell how ${H} was installed (${e.file}). Install ${n} with one of:
|
|
72
72
|
${p}
|
|
73
|
-
or run \`${H} update --pm <${mt.join("|")}>\`.`)}if(r.kind!=="global")return{...o,upToDate:!1,command:null,message:Xs(r,n)};let s=Hn(r.pm,n);if(e.check)return{...o,upToDate:!1,command:he(s)};let i=process.platform==="win32";t.beforeInstall?.();let a=t.log?["inherit","pipe","pipe"]:["inherit",2,2],u=i?(0,Wt.spawnSync)(he(s),{stdio:[...a],env:e.env,shell:!0}):(0,Wt.spawnSync)(s.cmd,s.args,{stdio:[...a],env:e.env});if(u.stdout?.length&&t.log?.(u.stdout.toString()),u.stderr?.length&&t.log?.(u.stderr.toString()),u.error)throw new w(`Could not run ${he(s)}: ${u.error.message}`);if(u.status!==0)throw new w(`${he(s)} exited with ${u.status??u.signal}`);return{type:"updated",from:e.current,to:n,pm:r.pm,command:he(s)}}var Yn={name:"update",summary:"Install the newest ryugi-artifacts release with the package manager that installed this one",options:{check:{type:"boolean",help:"Compare versions only; do not install"},pm:{type:"string",value:"<npm|pnpm|yarn|bun>",help:"Use this package manager instead of detecting it"}},semantic:e=>_({id:"update",mode:"finite",output:{formats:["brief","json","jsonl"],fields:["current","latest","install","status","installed","message","command"]},async run(t,r){let n,o;try{o=await zs({current:"1.
|
|
73
|
+
or run \`${H} update --pm <${mt.join("|")}>\`.`)}if(r.kind!=="global")return{...o,upToDate:!1,command:null,message:Xs(r,n)};let s=Hn(r.pm,n);if(e.check)return{...o,upToDate:!1,command:he(s)};let i=process.platform==="win32";t.beforeInstall?.();let a=t.log?["inherit","pipe","pipe"]:["inherit",2,2],u=i?(0,Wt.spawnSync)(he(s),{stdio:[...a],env:e.env,shell:!0}):(0,Wt.spawnSync)(s.cmd,s.args,{stdio:[...a],env:e.env});if(u.stdout?.length&&t.log?.(u.stdout.toString()),u.stderr?.length&&t.log?.(u.stderr.toString()),u.error)throw new w(`Could not run ${he(s)}: ${u.error.message}`);if(u.status!==0)throw new w(`${he(s)} exited with ${u.status??u.signal}`);return{type:"updated",from:e.current,to:n,pm:r.pm,command:he(s)}}var Yn={name:"update",summary:"Install the newest ryugi-artifacts release with the package manager that installed this one",options:{check:{type:"boolean",help:"Compare versions only; do not install"},pm:{type:"string",value:"<npm|pnpm|yarn|bun>",help:"Use this package manager instead of detecting it"}},semantic:e=>_({id:"update",mode:"finite",output:{formats:["brief","json","jsonl"],fields:["current","latest","install","status","installed","message","command"]},async run(t,r){let n,o;try{o=await zs({current:"1.71.0",file:__filename,env:process.env,registry:process.env.npm_config_registry||"https://registry.npmjs.org/",check:!!e.values.check,pm:e.values.pm},{beforeInstall(){n=r.effects.begin("install",H)},log:r.diagnostic})}catch(i){throw i instanceof gt?new f({code:"E_INSTALL_UNKNOWN",message:i.message},"action_required"):i}o.type==="updated"&&n!==void 0&&r.effects.confirm(n,{from:o.from,to:o.to});let s=o.type==="updated"?{current:o.to,latest:o.to,install:"global",status:"updated",installed:!0,command:o.command}:{current:o.current,latest:o.latest,install:o.install,status:o.upToDate?"up_to_date":"available",installed:!1,command:o.command,...o.message?{message:o.message}:{}};return x(s,void 0,{effects:r.effects.snapshot()})},present:Ks},e)};function Ks({data:e}){return{heading:"Update",status:e.status,facts:[R("Current",A(e,"current"),!0),R("Latest",A(e,"latest")),R("Install",A(e,"install")),...e.message?[R("Advice",A(e,"message"))]:[]],sections:[]}}var qt=[Fn,Un,Hr,un,Kr,Vr,ln,sn,Zr,Yn];function Ht(e=process.stdout,t=process.stderr){let r=new WeakMap;for(let n of[e,t])n.on("error",o=>r.set(n,o));return{write(n,o){let s=n==="stdout"?e:t,i=r.get(s);return i?Promise.reject(i):new Promise((a,u)=>s.write(o,p=>p?u(p):a()))}}}function Bt(e){process.exitCode=e}var Xn=S(require("node:fs"),1);async function xe(e,t,r,n){return Ct({id:e,mode:"finite",output:{formats:[r.format]},run(){throw t},present(){return{heading:"Error",status:"failed",facts:[],sections:[]}}},void 0,{...r,fields:void 0,detail:!1},n)}function Jn(e,t){return{id:e,mode:"finite",output:{formats:["brief","json","jsonl"],fields:["text","version","capabilities","commands"]},run(){return x(t)},present({data:r}){return r.version?{heading:`ryugi ${r.version}`,status:"",facts:[],sections:[]}:{heading:"Help",status:"",facts:[],sections:[{kind:"content",key:"text",text:r.text}]}}}}async function zn(e,t,r,n,o,s,i){let[a,...u]=e,p=t.find(d=>d.name===a);try{if(a==="--version"||a==="-v")return be(u,{},0),await _(Jn("version",{text:n,version:n,capabilities:["reviewBundlesV1"]}),void 0).run(o,s);if(a==="--help"||a==="-h"||p&&Zt(u)){p||be(u,{},0);let l=p?tr(p):rr(t,r);return await _(Jn("help",{text:l,commands:t.map(({name:m,summary:C})=>({name:m,summary:C}))}),void 0).run(o,s)}if(!p&&(!a||a.startsWith("-")||(()=>{try{return Xn.default.statSync(a).isDirectory()}catch{return!1}})())){let l=be(e,r,1);if(l.positionals.length&&l.values["project-dir"])throw new f({code:"E_ARGUMENT_INVALID",message:"Specify one project directory."});return l.projectDir=l.values["project-dir"]??l.positionals[0]??l.projectDir,l.values.foreground=!0,l.values.open=!l.values["no-open"],await lt(l,"browse").run(o,s,i)}if(!p)throw new f({code:a?.includes("/")?"E_PROJECT_NOT_FOUND":"E_UNKNOWN_COMMAND",message:a?`Unknown command: ${a}`:"Use start --foreground to browse with semantic output."});let d;try{d=be(u,p.options,p.positionals)}catch(l){throw new f({code:"E_ARGUMENT_INVALID",message:l.message})}return await p.semantic(d).run(o,s,i)}catch(d){return xe(p?.name??a??"browse",d,o,s)}}var Qs={"no-open":{type:"boolean",help:"Print the URL without opening a browser"}};async function Zs(e){let t=Object.assign({},te,...qt.map(a=>a.options)),r=Ht(),n;try{n=bt(e,t,Ir(e,t))}catch(a){return xe(e[0]??"browse",a,bt(e,t).options,r)}if(n.error)return xe(e[0]??"browse",n.error,n.options,r);let o=new AbortController,s=()=>o.abort("SIGINT"),i=()=>o.abort("SIGTERM");process.on("SIGINT",s),process.on("SIGTERM",i);try{return await zn(e,qt,Qs,"1.71.0",n.options,r,o.signal)}finally{process.removeListener("SIGINT",s),process.removeListener("SIGTERM",i)}}Zs(process.argv.slice(2)).then(Bt,e=>xe(process.argv[2]??"browse",e,{format:"brief"},Ht()).then(Bt));
|
package/dist/comment-threads.cjs
CHANGED
|
@@ -1,2 +1,53 @@
|
|
|
1
1
|
// Generated from ryugi-cloud/packages/artifacts/src/shared/review-evidence.ts. Do not edit.
|
|
2
|
-
"use strict";
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/shared/review-evidence.ts
|
|
22
|
+
var review_evidence_exports = {};
|
|
23
|
+
__export(review_evidence_exports, {
|
|
24
|
+
humanTokens: () => humanTokens,
|
|
25
|
+
reviewStateKey: () => reviewStateKey,
|
|
26
|
+
unreadThreadCount: () => unreadThreadCount
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(review_evidence_exports);
|
|
29
|
+
var import_node_crypto = require("node:crypto");
|
|
30
|
+
var hash = (value) => (0, import_node_crypto.createHash)("sha256").update(JSON.stringify(value)).digest("hex");
|
|
31
|
+
var reviewStateKey = (artifact, agent) => hash([artifact, agent]);
|
|
32
|
+
function humanTokens(thread) {
|
|
33
|
+
const values = thread.messages.filter((message) => message.author === "human").map((message) => ({
|
|
34
|
+
token: hash([thread.id, "message", message.id, message.at, message.editedAt, message.deleted, message.text]),
|
|
35
|
+
at: message.editedAt ?? message.at
|
|
36
|
+
}));
|
|
37
|
+
if (thread.statusBy === "human")
|
|
38
|
+
values.push({ token: hash([thread.id, "status", thread.statusAt, thread.status]), at: thread.statusAt });
|
|
39
|
+
return values;
|
|
40
|
+
}
|
|
41
|
+
function unreadThreadCount(file, consumed = []) {
|
|
42
|
+
const seen = new Set(consumed);
|
|
43
|
+
return (file?.threads ?? []).filter((thread) => {
|
|
44
|
+
const anchor = thread.anchor;
|
|
45
|
+
return anchor.ask === void 0 && anchor.choice === void 0 && anchor.submit === void 0 && humanTokens(thread).some((event) => !seen.has(event.token));
|
|
46
|
+
}).length;
|
|
47
|
+
}
|
|
48
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
49
|
+
0 && (module.exports = {
|
|
50
|
+
humanTokens,
|
|
51
|
+
reviewStateKey,
|
|
52
|
+
unreadThreadCount
|
|
53
|
+
});
|
|
@@ -1,8 +1,626 @@
|
|
|
1
|
-
"use strict";var ft=Object.create;var _=Object.defineProperty;var mt=Object.getOwnPropertyDescriptor;var yt=Object.getOwnPropertyNames;var bt=Object.getPrototypeOf,ht=Object.prototype.hasOwnProperty;var xt=(t,e)=>{for(var n in e)_(t,n,{get:e[n],enumerable:!0})},z=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of yt(e))!ht.call(t,s)&&s!==n&&_(t,s,{get:()=>e[s],enumerable:!(r=mt(e,s))||r.enumerable});return t};var $=(t,e,n)=>(n=t!=null?ft(bt(t)):{},z(e||!t||!t.__esModule?_(n,"default",{value:t,enumerable:!0}):n,t)),wt=t=>z(_({},"__esModule",{value:!0}),t);var Wt={};xt(Wt,{reportFailure:()=>Lt,resolveSelection:()=>gt});module.exports=wt(Wt);var p={format:{type:"string"},json:{type:"boolean"},detail:{type:"boolean"},fields:{type:"string"},quiet:{type:"boolean"},verbose:{type:"boolean"},"project-dir":{type:"string"},artifact:{type:"string"},host:{type:"string"},"url-host":{type:"string"},port:{type:"string"},open:{type:"boolean"},"no-open":{type:"boolean"},foreground:{type:"boolean"},background:{type:"boolean"},page:{type:"string"},visibility:{type:"string"},type:{type:"string"},project:{type:"boolean"},limit:{type:"string"},cursor:{type:"string"},public:{type:"boolean"},private:{type:"boolean"},unpublish:{type:"boolean"},list:{type:"boolean"},delete:{type:"string"},"no-refs":{type:"boolean"},login:{type:"boolean"},logout:{type:"boolean"},sections:{type:"string"},section:{type:"string"},snapshot:{type:"string"},receipt:{type:"string"},status:{type:"string"},"waiting-on":{type:"string"},kind:{type:"string"},"choice-state":{type:"string"},all:{type:"boolean"},block:{type:"string"},quote:{type:"string"},board:{type:"string"},element:{type:"string"},x:{type:"string"},y:{type:"string"},thread:{type:"string"},text:{type:"string"},group:{type:"string"},clear:{type:"boolean"},ask:{type:"string"},choice:{type:"string"},round:{type:"string"},withdraw:{type:"boolean"},save:{type:"string"},frame:{type:"string"},source:{type:"boolean"},download:{type:"boolean"},out:{type:"string"},"no-comments":{type:"boolean"},"output-format":{type:"string"},"auto-publish":{type:"string"},check:{type:"boolean"},pm:{type:"string"}};var V=$(require("node:fs"),1),it=$(require("node:os"),1),q=$(require("node:path"),1);var K=["x","y","w","h"],ne=["file","page",...K],re=["src","page",...K];var I=$(require("node:path"),1);function Z(t,e,n){return e==="win32"&&t.APPDATA?I.default.join(t.APPDATA,"ryugi","credentials.json"):I.default.join(t.XDG_CONFIG_HOME||I.default.join(n,".config"),"ryugi","credentials.json")}var W=$(require("node:path"),1);var Q=t=>W.default.join(W.default.dirname(t),"config.json");var E=$(require("node:fs"),1),tt=$(require("node:os"),1),m=$(require("node:path"),1),G=class extends Error{constructor(n,r={},s=1){super(n);this.fields=r;this.code=s}fields;code};function Pt(t){let e="";try{e=E.default.realpathSync(tt.default.homedir())}catch{}let n=[];for(let r=t;n.push(r),!(E.default.existsSync(m.default.join(r,".git"))&&(r!==e||t===e));r=m.default.dirname(r))if(m.default.dirname(r)===r)return t;return n.find(r=>E.default.existsSync(m.default.join(r,".ryugi","artifacts")))??n.at(-1)}function et(t){let e;try{if(e=E.default.realpathSync(m.default.resolve(t)),!E.default.statSync(e).isDirectory())throw new Error("Not a directory")}catch{throw new G(`Project directory not found: ${t}`)}e=Pt(e);let n=m.default.join(e,".ryugi","artifacts"),r=m.default.join(n,".state");return{project:e,root:n,state:r,pid:m.default.join(r,"server.pid"),log:m.default.join(r,"server.log"),serverId:m.default.join(r,"server-instance-id"),info:m.default.join(r,"server-info"),version:m.default.join(r,"server-version"),owners:m.default.join(r,"owners"),agent:m.default.join(r,"agent"),stopped:m.default.join(r,"server-stopped"),lock:m.default.join(r,"start.lock")}}var w=class extends Error{constructor(n,r="failed",s){super(n.message);this.error=n;this.kind=r;this.raw=s}error;kind;raw};function At(t,e=!1){switch(t.kind){case"succeeded":return{outcome:e?"attention":"success",code:0};case"validation_failed":return{outcome:"attention",code:3};case"pending":return{outcome:"pending",code:4};case"action_required":return{outcome:"attention",code:2};case"partial":return{outcome:"partial",code:5};case"failed":return{outcome:"error",code:1};case"interrupted":return{outcome:"error",code:t.signal==="SIGINT"?130:143}}}function nt(t,e,n,r){return!t||typeof t!="object"||Array.isArray(t)?t:Object.fromEntries(Object.entries(t).filter(([s])=>e.includes(s)?!0:(r.push({path:`${n}.${s}`,reason:"fields"}),!1)))}function rt(t,e,n,r){let s=[...e.coverage.omitted??[]],u=e.data;if(n.fields){let d=[...new Set([...n.fields,...r.requiredFields??[]])];if(r.collection&&u&&typeof u=="object"){let c=u,h=c[r.collection];u={...c,[r.collection]:Array.isArray(h)?h.map((O,b)=>nt(O,d,`data.${r.collection}.${b}`,s)):h}}else u=nt(u,d,"data",s)}return{schema:"ryugi.cli/v1",command:t,outcome:At(e.completion,e.warnings.length>0).outcome,data:u,...e.coverage.page?{page:e.coverage.page}:{},...s.length?{omitted:s}:{},...e.effects.length?{effects:e.effects}:{},...e.warnings.length?{warnings:e.warnings}:{},...e.actions.length?{next:e.actions}:{},...e.completion.kind==="failed"?{error:e.completion.error}:e.completion.kind==="interrupted"?{error:{code:"E_INTERRUPTED",message:`Command interrupted by ${e.completion.signal}.`,details:{signal:e.completion.signal}}}:{}}}function U(t,e){let n={};for(let r=0;r<t.length;r++){let s=t[r];if(s==="--")break;if(!s.startsWith("--"))continue;let u=s.indexOf("="),d=s.slice(2,u<0?void 0:u),c=d==="source"?"boolean":e[d]?.type;c==="string"?n[d]=u<0?t[++r]??"":s.slice(u+1):c==="boolean"&&(n[d]=!0)}return n}function Y(t,e,n=process.env){let r=U(t,e),s=["format","json","quiet","source"].filter(k=>r[k]!==void 0),u=n.RYUGI_ARTIFACTS_FORMAT??"brief",d=r.format??(r.json?"json":r.quiet?"quiet":r.source?"source":u),h=["brief","table","json","jsonl","raw","source","quiet"].includes(d),O={format:h?d:"brief",detail:!!r.detail||!!r.source,verbose:!!r.verbose},b;return s.length>1?b=new w({code:"E_OPTION_CONFLICT",message:"Choose one of --format, --json, --quiet or --source."}):(!h||!s.length&&!["brief","json","jsonl"].includes(u))&&(b=new w({code:"E_FORMAT_UNSUPPORTED",message:`Unknown output format: ${String(d)}`})),typeof r.fields=="string"&&(O.fields=r.fields.split(",").map(k=>k.trim()),O.fields.some(k=>!k)&&(b=new w({code:"E_ARGUMENT_INVALID",message:"--fields requires comma-separated field names."}))),{options:O,...b?{error:b}:{}}}var ot=["brief","json","jsonl"];function kt(t){return{global:Q(Z(process.env,process.platform,it.default.homedir())),project:q.default.join(q.default.dirname(et(t).root),"config.json")}}function Rt(t){try{let e=JSON.parse(V.default.readFileSync(t,"utf8"));if(!e||typeof e!="object"||Array.isArray(e))throw new Error("Expected an object");return e}catch(e){if(e.code==="ENOENT")return{};throw new w({code:"E_CONFIG_INVALID",message:`Cannot read ${t}: ${e.message}`})}}function $t(t){let e=kt(t),n=u=>{let d=Rt(u).output;if(d?.format!==void 0&&!ot.includes(d.format))throw new w({code:"E_FORMAT_UNSUPPORTED",message:`Unsupported output format in ${u}: ${String(d.format)}`});return d&&ot.includes(d.format)?d.format:null},r=n(e.global),s=n(e.project);return{global:r,project:s,effective:s??r??"brief",source:s?"project":r?"global":"default"}}function st(t,e,n=process.env){if(n.RYUGI_ARTIFACTS_FORMAT!==void 0)return n;let r=U(t,e);if(["format","json","quiet","source"].some(d=>r[d]!==void 0))return n;let s=typeof r["project-dir"]=="string"?r["project-dir"]:process.cwd();if(!r["project-dir"]&&t[0]&&!t[0].startsWith("-"))try{V.default.statSync(t[0]).isDirectory()&&(s=t[0])}catch{}let u=$t(s);return{...n,RYUGI_ARTIFACTS_FORMAT:u.effective}}function at(t,e={kind:"succeeded"},n={}){return{data:t,completion:e,coverage:{},effects:[],warnings:[],actions:[],...n}}var jt=/^\d{4}-\d\d-\d\dT\d\d:\d\d(?::\d\d(?:\.\d+)?)?(?:Z|[+-]\d\d:?\d\d)$/,C=t=>String(t).padStart(2,"0"),ct=t=>typeof t=="string"&&jt.test(t)&&!Number.isNaN(Date.parse(t));function ut(t,e=new Date){let n=new Date(t);if(Number.isNaN(n.getTime()))return t;let r=`${C(n.getHours())}:${C(n.getMinutes())}`;return n.getFullYear()!==e.getFullYear()?`${n.getFullYear()}-${C(n.getMonth()+1)}-${C(n.getDate())}`:n.getMonth()===e.getMonth()&&n.getDate()===e.getDate()?r:`${C(n.getMonth()+1)}-${C(n.getDate())} ${r}`}function lt(t,e){let n=t.details;return!n||typeof n!="object"||Array.isArray(n)?[]:Object.entries(n).flatMap(([r,s])=>typeof s=="string"&&/^https?:\/\/\S+$/i.test(s)?[{kind:"url",label:e?`${e} ${r}`:r,url:s}]:[])}var f=t=>t.replaceAll(new RegExp("\\p{Cc}","gu")," ");function Et(t,e=160){let n=[...new Intl.Segmenter(void 0,{granularity:"grapheme"}).segment(t)];return n.length>e?`${n.slice(0,e).map(r=>r.segment).join("")}\u2026`:t}function D(t,e=!1){if(t==null)return"";if(Array.isArray(t))return t.map(n=>D(n,!0)).join(", ");if(typeof t=="object"){let n=Object.entries(t).filter(([,r])=>!F(r)).map(([r,s])=>`${r} ${D(s,!0)}`).join(e?", ":" \xB7 ");return e?`(${n})`:n}return ct(t)?ut(t):String(t)}var Ct=(t,e,n)=>{if(t!==null&&typeof t=="object"){if(!n)throw new Error(`Brief cannot print the object at ${e}; flatten it in the view.`);return D(t)}return D(t)},F=(t,e)=>t==null||t===""||t===!1||e!==void 0&&t===e,vt={1:"FAILED",2:"NEEDS YOU",3:"ISSUES",4:"INCOMPLETE",5:"PARTIAL",130:"INTERRUPTED",143:"INTERRUPTED"},Tt={E_ARTIFACT_NOT_FOUND:"check --artifact and --project-dir; artifacts live in <project>/.ryugi/artifacts/<type>/<id>/",E_ARGUMENT_INVALID:"run the command with --help for its options",E_CURSOR_EXPIRED:"run the read again without --cursor or --snapshot",E_CURSOR_MISMATCH:"run the read again without --cursor or --snapshot"},_t=(t,e)=>e?vt[e]??"FAILED":f(t).replaceAll("_"," ").toUpperCase(),It=t=>{let e=t.replaceAll(/[._]/g," ").trim();return e?e[0].toUpperCase()+e.slice(1):"Command"};function Ft(t){let e=t.offset??0;if(!t.hasMore&&e===0)return null;let n=t.total===null?"":` of ${t.total}`;return t.offset===void 0?`${t.returned}${n} shown${t.total===null&&t.hasMore?" \xB7 more available":""}`:`${t.returned?`${e+1}\u2013${e+t.returned}`:"none"}${n}`}var Dt=t=>/^[\w./:@=+-]+$/.test(t)?t:`'${t.replaceAll("'","'\\''")}'`;function dt(t){return t.kind==="command"?t.argv.map(Dt).join(" "):t.url}var Nt=t=>t.map(e=>`Effect: ${f(e.operation)} ${f(e.target)} \xB7 ${e.state}`),Mt=t=>t.split(".").filter(Boolean).at(-1)??t;function Bt(t,e,n,r,s=[],u=0){let d=[_t(t.status,u),t.subject&&f(t.subject),t.summary&&f(t.summary)].filter(Boolean),c=[d.length?`${f(t.heading)}: ${d.join(" \xB7 ")}`:f(t.heading)],h=[...e.omitted??[]],O=(o,a=!1)=>a||s.includes(o)||!n.fields||n.fields.includes(o),b=(o,a,i=!1)=>{let l=f(Ct(o,a,i)),x=n.detail?l:Et(l);return x!==l&&h.push({path:a,reason:"preview"}),x},k=(o,a,i,l,x,R,g=!1)=>{if(F(i,R))return null;let S=f(o??a);if(i===!0)return S;let y=b(i,l,g);return x?y:`${S} ${y}`},v=(o,a=!1)=>{for(let i of o){if(!r&&!O(i.binding.key,i.required)||F(i.binding.value))continue;let l=i.binding.value===!0?"yes":b(i.binding.value,`data.${i.binding.key}`,a);c.push(`${f(i.label)}: ${l}`)}},J=(o,a)=>o.map(i=>k(i.label,i.binding.key,i.binding.value,`${a}.${i.binding.key}`,i.positional)).filter(i=>i!==null).join(" \xB7 "),N=(o,a)=>{o&&c.push(a?`${f(o)} \xB7 ${f(a)}`:f(o))},M=o=>{let a=o&&Ft(o);a&&c.push(a)};v(t.facts);let X=e.error?lt(e.error):[];if(e.error){c.push(`${f(e.error.code)}: ${f(e.error.message)}`),e.error.httpStatus!==void 0&&e.error.httpStatus>=500&&c.push(`HTTP: ${e.error.httpStatus}`);let o=Tt[e.error.code];o&&c.push(`Next: ${o}`);let a=e.error.details;if(a&&typeof a=="object"&&!Array.isArray(a))for(let[i,l]of Object.entries(a))X.some(x=>x.label===i)||v([{label:i,binding:{key:i,value:l},required:!0}],!0);else a!==void 0&&v([{label:"Details",binding:{key:"details",value:a},required:!0}],!0)}if(!r&&n.fields&&e.data&&typeof e.data=="object"){let o=new Set([...t.facts.map(i=>i.binding.key),...t.sections.flatMap(i=>i.kind==="fields"?i.facts.map(l=>l.binding.key):[i.key])]),a=e.data;v([...new Set([...n.fields,...s])].filter(i=>!o.has(i)&&Object.hasOwn(a,i)).map(i=>({label:i,binding:{key:i,value:a[i]}})),!0)}for(let o of t.sections){if(o.kind==="fields"){v(o.facts);continue}if(!r&&!O(o.key))continue;let a="title"in o&&o.title?o.title:void 0;if(o.kind==="records"){N(a??(o.page?o.key:void 0),o.summary);let i=new Set(o.columns.map(g=>g.key)),l=o.key===r?[...new Set([...n.fields??[],...n.fields?s:[]])].filter(g=>!i.has(g)).map(g=>({key:g,label:g})):[],x=new Set(l.map(g=>g.key)),R=[...o.columns,...l].filter(g=>o.key!==r||O(g.key,g.required));if(n.format==="table"){let g=R.map(P=>P.label??P.key),S=o.rows.map((P,j)=>R.map(A=>F(P[A.key],A.default)?"":b(P[A.key],`data.${o.key}.${j}.${A.key}`,x.has(A.key)))),y=g.map((P,j)=>Math.max(P.length,...S.map(A=>A[j]?.length??0)));c.push(...[g,...S].map(P=>P.map((j,A)=>j.padEnd(y[A]??j.length)).join(" ").trimEnd()))}else for(let[g,S]of o.rows.entries())c.push(` ${R.map(y=>k(y.label,y.key,S[y.key],`data.${o.key}.${g}.${y.key}`,y.positional,y.default,x.has(y.key))).filter(y=>y!==null).join(" \xB7 ")}`);!o.rows.length&&!a&&!o.page&&c.push("No records."),M(o.page)}else if(o.kind==="messages"){N(a,o.summary);for(let[i,l]of o.groups.entries()){c.push(` ${J(l.facts,`data.${o.key}.${i}`)}`);for(let[x,R]of l.messages.entries())c.push(` ${J(R.facts,`data.${o.key}.${i}.messages.${x}`)}`),c.push(...R.text.split(`
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/cli/output/bootstrap/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
reportFailure: () => reportFailure,
|
|
34
|
+
resolveSelection: () => resolveSelection
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(index_exports);
|
|
37
|
+
|
|
38
|
+
// <define:BOOTSTRAP_OPTIONS>
|
|
39
|
+
var define_BOOTSTRAP_OPTIONS_default = { format: { type: "string" }, json: { type: "boolean" }, detail: { type: "boolean" }, fields: { type: "string" }, quiet: { type: "boolean" }, verbose: { type: "boolean" }, "project-dir": { type: "string" }, artifact: { type: "string" }, host: { type: "string" }, "url-host": { type: "string" }, port: { type: "string" }, open: { type: "boolean" }, "no-open": { type: "boolean" }, foreground: { type: "boolean" }, background: { type: "boolean" }, page: { type: "string" }, visibility: { type: "string" }, type: { type: "string" }, project: { type: "boolean" }, limit: { type: "string" }, cursor: { type: "string" }, public: { type: "boolean" }, private: { type: "boolean" }, unpublish: { type: "boolean" }, list: { type: "boolean" }, delete: { type: "string" }, "no-refs": { type: "boolean" }, login: { type: "boolean" }, logout: { type: "boolean" }, sections: { type: "string" }, section: { type: "string" }, snapshot: { type: "string" }, receipt: { type: "string" }, status: { type: "string" }, "waiting-on": { type: "string" }, kind: { type: "string" }, "choice-state": { type: "string" }, all: { type: "boolean" }, block: { type: "string" }, quote: { type: "string" }, board: { type: "string" }, element: { type: "string" }, x: { type: "string" }, y: { type: "string" }, thread: { type: "string" }, text: { type: "string" }, group: { type: "string" }, clear: { type: "boolean" }, ask: { type: "string" }, choice: { type: "string" }, round: { type: "string" }, withdraw: { type: "boolean" }, save: { type: "string" }, frame: { type: "string" }, source: { type: "boolean" }, download: { type: "boolean" }, out: { type: "string" }, "no-comments": { type: "boolean" }, "output-format": { type: "string" }, "auto-publish": { type: "string" }, check: { type: "boolean" }, pm: { type: "string" } };
|
|
40
|
+
|
|
41
|
+
// src/cli/output/configuration.ts
|
|
42
|
+
var import_node_fs2 = __toESM(require("node:fs"), 1);
|
|
43
|
+
var import_node_os2 = __toESM(require("node:os"), 1);
|
|
44
|
+
var import_node_path4 = __toESM(require("node:path"), 1);
|
|
45
|
+
|
|
46
|
+
// src/shared/cloud.ts
|
|
47
|
+
var MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
|
|
48
|
+
|
|
49
|
+
// src/shared/validate.ts
|
|
50
|
+
var BOARD_NUMBERS = ["x", "y", "w", "h"];
|
|
51
|
+
var BOARD_REQUIRED = ["file", "page", ...BOARD_NUMBERS];
|
|
52
|
+
var MEDIA_REQUIRED = ["src", "page", ...BOARD_NUMBERS];
|
|
53
|
+
|
|
54
|
+
// src/server/credentials.ts
|
|
55
|
+
var import_node_path = __toESM(require("node:path"), 1);
|
|
56
|
+
function credentialsFile(env, platform, home) {
|
|
57
|
+
if (platform === "win32" && env.APPDATA)
|
|
58
|
+
return import_node_path.default.join(env.APPDATA, "ryugi", "credentials.json");
|
|
59
|
+
return import_node_path.default.join(env.XDG_CONFIG_HOME || import_node_path.default.join(home, ".config"), "ryugi", "credentials.json");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// src/server/settings.ts
|
|
63
|
+
var import_node_path2 = __toESM(require("node:path"), 1);
|
|
64
|
+
var settingsFileFor = (credentialsFile2) => import_node_path2.default.join(import_node_path2.default.dirname(credentialsFile2), "config.json");
|
|
65
|
+
|
|
66
|
+
// src/cli/paths.ts
|
|
67
|
+
var import_node_fs = __toESM(require("node:fs"), 1);
|
|
68
|
+
var import_node_os = __toESM(require("node:os"), 1);
|
|
69
|
+
var import_node_path3 = __toESM(require("node:path"), 1);
|
|
70
|
+
var CliError = class extends Error {
|
|
71
|
+
constructor(message, fields = {}, code = 1) {
|
|
72
|
+
super(message);
|
|
73
|
+
this.fields = fields;
|
|
74
|
+
this.code = code;
|
|
75
|
+
}
|
|
76
|
+
fields;
|
|
77
|
+
code;
|
|
78
|
+
};
|
|
79
|
+
function projectRoot(dir) {
|
|
80
|
+
let home = "";
|
|
81
|
+
try {
|
|
82
|
+
home = import_node_fs.default.realpathSync(import_node_os.default.homedir());
|
|
83
|
+
} catch {
|
|
84
|
+
}
|
|
85
|
+
const chain = [];
|
|
86
|
+
for (let current = dir; ; current = import_node_path3.default.dirname(current)) {
|
|
87
|
+
chain.push(current);
|
|
88
|
+
if (import_node_fs.default.existsSync(import_node_path3.default.join(current, ".git")) && (current !== home || dir === home)) break;
|
|
89
|
+
if (import_node_path3.default.dirname(current) === current) return dir;
|
|
90
|
+
}
|
|
91
|
+
return chain.find((candidate) => import_node_fs.default.existsSync(import_node_path3.default.join(candidate, ".ryugi", "artifacts"))) ?? chain.at(-1);
|
|
92
|
+
}
|
|
93
|
+
function projectPaths(dir) {
|
|
94
|
+
let project2;
|
|
95
|
+
try {
|
|
96
|
+
project2 = import_node_fs.default.realpathSync(import_node_path3.default.resolve(dir));
|
|
97
|
+
if (!import_node_fs.default.statSync(project2).isDirectory()) throw new Error("Not a directory");
|
|
98
|
+
} catch {
|
|
99
|
+
throw new CliError(`Project directory not found: ${dir}`);
|
|
100
|
+
}
|
|
101
|
+
project2 = projectRoot(project2);
|
|
102
|
+
const root = import_node_path3.default.join(project2, ".ryugi", "artifacts");
|
|
103
|
+
const state = import_node_path3.default.join(root, ".state");
|
|
104
|
+
return {
|
|
105
|
+
project: project2,
|
|
106
|
+
root,
|
|
107
|
+
state,
|
|
108
|
+
pid: import_node_path3.default.join(state, "server.pid"),
|
|
109
|
+
log: import_node_path3.default.join(state, "server.log"),
|
|
110
|
+
serverId: import_node_path3.default.join(state, "server-instance-id"),
|
|
111
|
+
info: import_node_path3.default.join(state, "server-info"),
|
|
112
|
+
version: import_node_path3.default.join(state, "server-version"),
|
|
113
|
+
owners: import_node_path3.default.join(state, "owners"),
|
|
114
|
+
agent: import_node_path3.default.join(state, "agent"),
|
|
115
|
+
stopped: import_node_path3.default.join(state, "server-stopped"),
|
|
116
|
+
lock: import_node_path3.default.join(state, "start.lock")
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// src/cli/output/normalize.ts
|
|
121
|
+
var OutputError = class extends Error {
|
|
122
|
+
constructor(error, kind = "failed", raw) {
|
|
123
|
+
super(error.message);
|
|
124
|
+
this.error = error;
|
|
125
|
+
this.kind = kind;
|
|
126
|
+
this.raw = raw;
|
|
127
|
+
}
|
|
128
|
+
error;
|
|
129
|
+
kind;
|
|
130
|
+
raw;
|
|
131
|
+
};
|
|
132
|
+
function completionState(completion, warning = false) {
|
|
133
|
+
switch (completion.kind) {
|
|
134
|
+
case "succeeded":
|
|
135
|
+
return { outcome: warning ? "attention" : "success", code: 0 };
|
|
136
|
+
case "validation_failed":
|
|
137
|
+
return { outcome: "attention", code: 3 };
|
|
138
|
+
case "pending":
|
|
139
|
+
return { outcome: "pending", code: 4 };
|
|
140
|
+
case "action_required":
|
|
141
|
+
return { outcome: "attention", code: 2 };
|
|
142
|
+
case "partial":
|
|
143
|
+
return { outcome: "partial", code: 5 };
|
|
144
|
+
case "failed":
|
|
145
|
+
return { outcome: "error", code: 1 };
|
|
146
|
+
case "interrupted":
|
|
147
|
+
return { outcome: "error", code: completion.signal === "SIGINT" ? 130 : 143 };
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function project(value, keys, path5, omitted) {
|
|
151
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return value;
|
|
152
|
+
return Object.fromEntries(
|
|
153
|
+
Object.entries(value).filter(([key]) => {
|
|
154
|
+
if (keys.includes(key)) return true;
|
|
155
|
+
omitted.push({ path: `${path5}.${key}`, reason: "fields" });
|
|
156
|
+
return false;
|
|
157
|
+
})
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
function normalize(command, result2, options, policy) {
|
|
161
|
+
const omitted = [...result2.coverage.omitted ?? []];
|
|
162
|
+
let data = result2.data;
|
|
163
|
+
if (options.fields) {
|
|
164
|
+
const keys = [.../* @__PURE__ */ new Set([...options.fields, ...policy.requiredFields ?? []])];
|
|
165
|
+
if (policy.collection && data && typeof data === "object") {
|
|
166
|
+
const record = data;
|
|
167
|
+
const rows = record[policy.collection];
|
|
168
|
+
data = {
|
|
169
|
+
...record,
|
|
170
|
+
[policy.collection]: Array.isArray(rows) ? rows.map((row, i) => project(row, keys, `data.${policy.collection}.${i}`, omitted)) : rows
|
|
171
|
+
};
|
|
172
|
+
} else data = project(data, keys, "data", omitted);
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
schema: "ryugi.cli/v1",
|
|
176
|
+
command,
|
|
177
|
+
outcome: completionState(result2.completion, result2.warnings.length > 0).outcome,
|
|
178
|
+
data,
|
|
179
|
+
...result2.coverage.page ? { page: result2.coverage.page } : {},
|
|
180
|
+
...omitted.length ? { omitted } : {},
|
|
181
|
+
...result2.effects.length ? { effects: result2.effects } : {},
|
|
182
|
+
...result2.warnings.length ? { warnings: result2.warnings } : {},
|
|
183
|
+
...result2.actions.length ? { next: result2.actions } : {},
|
|
184
|
+
...result2.completion.kind === "failed" ? { error: result2.completion.error } : result2.completion.kind === "interrupted" ? {
|
|
185
|
+
error: {
|
|
186
|
+
code: "E_INTERRUPTED",
|
|
187
|
+
message: `Command interrupted by ${result2.completion.signal}.`,
|
|
188
|
+
details: { signal: result2.completion.signal }
|
|
189
|
+
}
|
|
190
|
+
} : {}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// src/cli/output/planning.ts
|
|
195
|
+
function scanOptions(argv, optionSpecs) {
|
|
196
|
+
const values = {};
|
|
197
|
+
for (let i = 0; i < argv.length; i++) {
|
|
198
|
+
const token = argv[i];
|
|
199
|
+
if (token === "--") break;
|
|
200
|
+
if (!token.startsWith("--")) continue;
|
|
201
|
+
const equal = token.indexOf("=");
|
|
202
|
+
const name = token.slice(2, equal < 0 ? void 0 : equal);
|
|
203
|
+
const type = name === "source" ? "boolean" : optionSpecs[name]?.type;
|
|
204
|
+
if (type === "string") values[name] = equal < 0 ? argv[++i] ?? "" : token.slice(equal + 1);
|
|
205
|
+
else if (type === "boolean") values[name] = true;
|
|
206
|
+
}
|
|
207
|
+
return values;
|
|
208
|
+
}
|
|
209
|
+
function selectOutput(argv, optionSpecs, env = process.env) {
|
|
210
|
+
const values = scanOptions(argv, optionSpecs);
|
|
211
|
+
const explicit = ["format", "json", "quiet", "source"].filter((key) => values[key] !== void 0);
|
|
212
|
+
const configured = env.RYUGI_ARTIFACTS_FORMAT ?? "brief";
|
|
213
|
+
const requested = values.format ?? (values.json ? "json" : values.quiet ? "quiet" : values.source ? "source" : configured);
|
|
214
|
+
const formats = ["brief", "table", "json", "jsonl", "raw", "source", "quiet"];
|
|
215
|
+
const valid = formats.includes(requested);
|
|
216
|
+
const options = {
|
|
217
|
+
format: valid ? requested : "brief",
|
|
218
|
+
detail: !!values.detail || !!values.source,
|
|
219
|
+
verbose: !!values.verbose
|
|
220
|
+
};
|
|
221
|
+
let error;
|
|
222
|
+
if (explicit.length > 1)
|
|
223
|
+
error = new OutputError({
|
|
224
|
+
code: "E_OPTION_CONFLICT",
|
|
225
|
+
message: "Choose one of --format, --json, --quiet or --source."
|
|
226
|
+
});
|
|
227
|
+
else if (!valid || !explicit.length && !["brief", "json", "jsonl"].includes(configured))
|
|
228
|
+
error = new OutputError({
|
|
229
|
+
code: "E_FORMAT_UNSUPPORTED",
|
|
230
|
+
message: `Unknown output format: ${String(requested)}`
|
|
231
|
+
});
|
|
232
|
+
if (typeof values.fields === "string") {
|
|
233
|
+
options.fields = values.fields.split(",").map((field) => field.trim());
|
|
234
|
+
if (options.fields.some((field) => !field))
|
|
235
|
+
error = new OutputError({
|
|
236
|
+
code: "E_ARGUMENT_INVALID",
|
|
237
|
+
message: "--fields requires comma-separated field names."
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
return { options, ...error ? { error } : {} };
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// src/cli/output/configuration.ts
|
|
244
|
+
var PERSISTED_FORMATS = ["brief", "json", "jsonl"];
|
|
245
|
+
function outputFiles(projectDir) {
|
|
246
|
+
return {
|
|
247
|
+
global: settingsFileFor(credentialsFile(process.env, process.platform, import_node_os2.default.homedir())),
|
|
248
|
+
project: import_node_path4.default.join(import_node_path4.default.dirname(projectPaths(projectDir).root), "config.json")
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
function read(file) {
|
|
252
|
+
try {
|
|
253
|
+
const raw = JSON.parse(import_node_fs2.default.readFileSync(file, "utf8"));
|
|
254
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) throw new Error("Expected an object");
|
|
255
|
+
return raw;
|
|
256
|
+
} catch (error) {
|
|
257
|
+
if (error.code === "ENOENT") return {};
|
|
258
|
+
throw new OutputError({
|
|
259
|
+
code: "E_CONFIG_INVALID",
|
|
260
|
+
message: `Cannot read ${file}: ${error.message}`
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
function outputValues(projectDir) {
|
|
265
|
+
const files = outputFiles(projectDir);
|
|
266
|
+
const get = (file) => {
|
|
267
|
+
const output = read(file).output;
|
|
268
|
+
if (output?.format !== void 0 && !PERSISTED_FORMATS.includes(output.format))
|
|
269
|
+
throw new OutputError({
|
|
270
|
+
code: "E_FORMAT_UNSUPPORTED",
|
|
271
|
+
message: `Unsupported output format in ${file}: ${String(output.format)}`
|
|
272
|
+
});
|
|
273
|
+
return output && PERSISTED_FORMATS.includes(output.format) ? output.format : null;
|
|
274
|
+
};
|
|
275
|
+
const global = get(files.global), project2 = get(files.project);
|
|
276
|
+
return {
|
|
277
|
+
global,
|
|
278
|
+
project: project2,
|
|
279
|
+
effective: project2 ?? global ?? "brief",
|
|
280
|
+
source: project2 ? "project" : global ? "global" : "default"
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
function configuredEnvironment(argv, specs, env = process.env) {
|
|
284
|
+
if (env.RYUGI_ARTIFACTS_FORMAT !== void 0) return env;
|
|
285
|
+
const values = scanOptions(argv, specs);
|
|
286
|
+
if (["format", "json", "quiet", "source"].some((key) => values[key] !== void 0)) return env;
|
|
287
|
+
let project2 = typeof values["project-dir"] === "string" ? values["project-dir"] : process.cwd();
|
|
288
|
+
if (!values["project-dir"] && argv[0] && !argv[0].startsWith("-")) {
|
|
289
|
+
try {
|
|
290
|
+
if (import_node_fs2.default.statSync(argv[0]).isDirectory()) project2 = argv[0];
|
|
291
|
+
} catch {
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const config = outputValues(project2);
|
|
295
|
+
return { ...env, RYUGI_ARTIFACTS_FORMAT: config.effective };
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// src/cli/output/protocol.ts
|
|
299
|
+
function result(data, completion = { kind: "succeeded" }, extra = {}) {
|
|
300
|
+
return { data, completion, coverage: {}, effects: [], warnings: [], actions: [], ...extra };
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// src/cli/output/time.ts
|
|
304
|
+
var ISO = /^\d{4}-\d\d-\d\dT\d\d:\d\d(?::\d\d(?:\.\d+)?)?(?:Z|[+-]\d\d:?\d\d)$/;
|
|
305
|
+
var two = (n) => String(n).padStart(2, "0");
|
|
306
|
+
var isIsoTime = (value) => typeof value === "string" && ISO.test(value) && !Number.isNaN(Date.parse(value));
|
|
307
|
+
function formatTime(iso, now = /* @__PURE__ */ new Date()) {
|
|
308
|
+
const at = new Date(iso);
|
|
309
|
+
if (Number.isNaN(at.getTime())) return iso;
|
|
310
|
+
const clock = `${two(at.getHours())}:${two(at.getMinutes())}`;
|
|
311
|
+
if (at.getFullYear() !== now.getFullYear())
|
|
312
|
+
return `${at.getFullYear()}-${two(at.getMonth() + 1)}-${two(at.getDate())}`;
|
|
313
|
+
if (at.getMonth() === now.getMonth() && at.getDate() === now.getDate()) return clock;
|
|
314
|
+
return `${two(at.getMonth() + 1)}-${two(at.getDate())} ${clock}`;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// src/cli/output/view.ts
|
|
318
|
+
function recoveryActions(error, subject) {
|
|
319
|
+
const details = error.details;
|
|
320
|
+
if (!details || typeof details !== "object" || Array.isArray(details)) return [];
|
|
321
|
+
return Object.entries(details).flatMap(
|
|
322
|
+
([key, url]) => typeof url === "string" && /^https?:\/\/\S+$/i.test(url) ? [{ kind: "url", label: subject ? `${subject} ${key}` : key, url }] : []
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// src/cli/output/render.ts
|
|
327
|
+
var clean = (text) => text.replaceAll(new RegExp("\\p{Cc}", "gu"), " ");
|
|
328
|
+
function clip(text, size = 160) {
|
|
329
|
+
const segments = [...new Intl.Segmenter(void 0, { granularity: "grapheme" }).segment(text)];
|
|
330
|
+
return segments.length > size ? `${segments.slice(0, size).map((s) => s.segment).join("")}\u2026` : text;
|
|
331
|
+
}
|
|
332
|
+
function flatten(value, nested = false) {
|
|
333
|
+
if (value === null || value === void 0) return "";
|
|
334
|
+
if (Array.isArray(value)) return value.map((item) => flatten(item, true)).join(", ");
|
|
335
|
+
if (typeof value === "object") {
|
|
336
|
+
const text = Object.entries(value).filter(([, item]) => !absent(item)).map(([key, item]) => `${key} ${flatten(item, true)}`).join(nested ? ", " : " \xB7 ");
|
|
337
|
+
return nested ? `(${text})` : text;
|
|
338
|
+
}
|
|
339
|
+
return isIsoTime(value) ? formatTime(value) : String(value);
|
|
340
|
+
}
|
|
341
|
+
var scalar = (value, path5, loose) => {
|
|
342
|
+
if (value !== null && typeof value === "object") {
|
|
343
|
+
if (!loose)
|
|
344
|
+
throw new Error(`Brief cannot print the object at ${path5}; flatten it in the view.`);
|
|
345
|
+
return flatten(value);
|
|
346
|
+
}
|
|
347
|
+
return flatten(value);
|
|
348
|
+
};
|
|
349
|
+
var absent = (value, fallback) => value === void 0 || value === null || value === "" || value === false || fallback !== void 0 && value === fallback;
|
|
350
|
+
var EXIT_WORDS = {
|
|
351
|
+
1: "FAILED",
|
|
352
|
+
2: "NEEDS YOU",
|
|
353
|
+
3: "ISSUES",
|
|
354
|
+
4: "INCOMPLETE",
|
|
355
|
+
5: "PARTIAL",
|
|
356
|
+
130: "INTERRUPTED",
|
|
357
|
+
143: "INTERRUPTED"
|
|
358
|
+
};
|
|
359
|
+
var RECOVERY = {
|
|
360
|
+
E_ARTIFACT_NOT_FOUND: "check --artifact and --project-dir; artifacts live in <project>/.ryugi/artifacts/<type>/<id>/",
|
|
361
|
+
E_ARGUMENT_INVALID: "run the command with --help for its options",
|
|
362
|
+
E_CURSOR_EXPIRED: "run the read again without --cursor or --snapshot",
|
|
363
|
+
E_CURSOR_MISMATCH: "run the read again without --cursor or --snapshot"
|
|
364
|
+
};
|
|
365
|
+
var statusWord = (status, code) => code ? EXIT_WORDS[code] ?? "FAILED" : clean(status).replaceAll("_", " ").toUpperCase();
|
|
366
|
+
var commandName = (id) => {
|
|
367
|
+
const words = id.replaceAll(/[._]/g, " ").trim();
|
|
368
|
+
return words ? words[0].toUpperCase() + words.slice(1) : "Command";
|
|
369
|
+
};
|
|
370
|
+
function pageText(page) {
|
|
371
|
+
const offset = page.offset ?? 0;
|
|
372
|
+
if (!page.hasMore && offset === 0) return null;
|
|
373
|
+
const of = page.total === null ? "" : ` of ${page.total}`;
|
|
374
|
+
if (page.offset === void 0)
|
|
375
|
+
return `${page.returned}${of} shown${page.total === null && page.hasMore ? " \xB7 more available" : ""}`;
|
|
376
|
+
return `${page.returned ? `${offset + 1}\u2013${offset + page.returned}` : "none"}${of}`;
|
|
377
|
+
}
|
|
378
|
+
var quote = (value) => /^[\w./:@=+-]+$/.test(value) ? value : `'${value.replaceAll("'", "'\\''")}'`;
|
|
379
|
+
function actionText(action) {
|
|
380
|
+
return action.kind === "command" ? action.argv.map(quote).join(" ") : action.url;
|
|
381
|
+
}
|
|
382
|
+
var effectLines = (effects) => effects.map(
|
|
383
|
+
(effect) => `Effect: ${clean(effect.operation)} ${clean(effect.target)} \xB7 ${effect.state}`
|
|
384
|
+
);
|
|
385
|
+
var lastSegment = (path5) => path5.split(".").filter(Boolean).at(-1) ?? path5;
|
|
386
|
+
function renderText(view, wire, options, collection, requiredFields = [], code = 0) {
|
|
387
|
+
const head = [
|
|
388
|
+
statusWord(view.status, code),
|
|
389
|
+
view.subject && clean(view.subject),
|
|
390
|
+
view.summary && clean(view.summary)
|
|
391
|
+
].filter(Boolean);
|
|
392
|
+
const lines = [head.length ? `${clean(view.heading)}: ${head.join(" \xB7 ")}` : clean(view.heading)];
|
|
393
|
+
const omissions = [...wire.omitted ?? []];
|
|
394
|
+
const selected = (key, required = false) => required || requiredFields.includes(key) || !options.fields || options.fields.includes(key);
|
|
395
|
+
const value = (input, path5, loose = false) => {
|
|
396
|
+
const text = clean(scalar(input, path5, loose));
|
|
397
|
+
const shown = options.detail ? text : clip(text);
|
|
398
|
+
if (shown !== text) omissions.push({ path: path5, reason: "preview" });
|
|
399
|
+
return shown;
|
|
400
|
+
};
|
|
401
|
+
const cell = (label, key, input, path5, positional, fallback, loose = false) => {
|
|
402
|
+
if (absent(input, fallback)) return null;
|
|
403
|
+
const name = clean(label ?? key);
|
|
404
|
+
if (input === true) return name;
|
|
405
|
+
const text = value(input, path5, loose);
|
|
406
|
+
return positional ? text : `${name} ${text}`;
|
|
407
|
+
};
|
|
408
|
+
const facts = (items, loose = false) => {
|
|
409
|
+
for (const item of items) {
|
|
410
|
+
if (!collection && !selected(item.binding.key, item.required)) continue;
|
|
411
|
+
if (absent(item.binding.value)) continue;
|
|
412
|
+
const text = item.binding.value === true ? "yes" : value(item.binding.value, `data.${item.binding.key}`, loose);
|
|
413
|
+
lines.push(`${clean(item.label)}: ${text}`);
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
const metadata = (items, path5) => items.map(
|
|
417
|
+
(item) => cell(
|
|
418
|
+
item.label,
|
|
419
|
+
item.binding.key,
|
|
420
|
+
item.binding.value,
|
|
421
|
+
`${path5}.${item.binding.key}`,
|
|
422
|
+
item.positional
|
|
423
|
+
)
|
|
424
|
+
).filter((text) => text !== null).join(" \xB7 ");
|
|
425
|
+
const title = (text, summary) => {
|
|
426
|
+
if (text) lines.push(summary ? `${clean(text)} \xB7 ${clean(summary)}` : clean(text));
|
|
427
|
+
};
|
|
428
|
+
const pageLine = (page) => {
|
|
429
|
+
const text = page && pageText(page);
|
|
430
|
+
if (text) lines.push(text);
|
|
431
|
+
};
|
|
432
|
+
facts(view.facts);
|
|
433
|
+
const errorActions = wire.error ? recoveryActions(wire.error) : [];
|
|
434
|
+
if (wire.error) {
|
|
435
|
+
lines.push(`${clean(wire.error.code)}: ${clean(wire.error.message)}`);
|
|
436
|
+
if (wire.error.httpStatus !== void 0 && wire.error.httpStatus >= 500)
|
|
437
|
+
lines.push(`HTTP: ${wire.error.httpStatus}`);
|
|
438
|
+
const hint = RECOVERY[wire.error.code];
|
|
439
|
+
if (hint) lines.push(`Next: ${hint}`);
|
|
440
|
+
const details2 = wire.error.details;
|
|
441
|
+
if (details2 && typeof details2 === "object" && !Array.isArray(details2)) {
|
|
442
|
+
for (const [key, detail] of Object.entries(details2)) {
|
|
443
|
+
if (!errorActions.some((action) => action.label === key))
|
|
444
|
+
facts([{ label: key, binding: { key, value: detail }, required: true }], true);
|
|
445
|
+
}
|
|
446
|
+
} else if (details2 !== void 0)
|
|
447
|
+
facts(
|
|
448
|
+
[{ label: "Details", binding: { key: "details", value: details2 }, required: true }],
|
|
449
|
+
true
|
|
450
|
+
);
|
|
451
|
+
}
|
|
452
|
+
if (!collection && options.fields && wire.data && typeof wire.data === "object") {
|
|
453
|
+
const bound = /* @__PURE__ */ new Set([
|
|
454
|
+
...view.facts.map((item) => item.binding.key),
|
|
455
|
+
...view.sections.flatMap(
|
|
456
|
+
(section) => section.kind === "fields" ? section.facts.map((item) => item.binding.key) : [section.key]
|
|
457
|
+
)
|
|
458
|
+
]);
|
|
459
|
+
const data = wire.data;
|
|
460
|
+
facts(
|
|
461
|
+
[.../* @__PURE__ */ new Set([...options.fields, ...requiredFields])].filter((key) => !bound.has(key) && Object.hasOwn(data, key)).map((key) => ({ label: key, binding: { key, value: data[key] } })),
|
|
462
|
+
true
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
for (const section of view.sections) {
|
|
466
|
+
if (section.kind === "fields") {
|
|
467
|
+
facts(section.facts);
|
|
468
|
+
continue;
|
|
469
|
+
}
|
|
470
|
+
if (!collection && !selected(section.key)) continue;
|
|
471
|
+
const named = "title" in section && section.title ? section.title : void 0;
|
|
472
|
+
if (section.kind === "records") {
|
|
473
|
+
title(named ?? (section.page ? section.key : void 0), section.summary);
|
|
474
|
+
const declared = new Set(section.columns.map((column) => column.key));
|
|
475
|
+
const extra = section.key === collection ? [.../* @__PURE__ */ new Set([...options.fields ?? [], ...options.fields ? requiredFields : []])].filter((key) => !declared.has(key)).map((key) => ({ key, label: key })) : [];
|
|
476
|
+
const loose = new Set(extra.map((column) => column.key));
|
|
477
|
+
const columns = [...section.columns, ...extra].filter(
|
|
478
|
+
(column) => section.key !== collection || selected(column.key, column.required)
|
|
479
|
+
);
|
|
480
|
+
if (options.format === "table") {
|
|
481
|
+
const labels = columns.map((column) => column.label ?? column.key);
|
|
482
|
+
const rows = section.rows.map(
|
|
483
|
+
(row, i) => columns.map(
|
|
484
|
+
(column) => absent(row[column.key], column.default) ? "" : value(
|
|
485
|
+
row[column.key],
|
|
486
|
+
`data.${section.key}.${i}.${column.key}`,
|
|
487
|
+
loose.has(column.key)
|
|
488
|
+
)
|
|
489
|
+
)
|
|
490
|
+
);
|
|
491
|
+
const widths = labels.map(
|
|
492
|
+
(label, i) => Math.max(label.length, ...rows.map((row) => row[i]?.length ?? 0))
|
|
493
|
+
);
|
|
494
|
+
lines.push(
|
|
495
|
+
...[labels, ...rows].map(
|
|
496
|
+
(row) => row.map((text, i) => text.padEnd(widths[i] ?? text.length)).join(" ").trimEnd()
|
|
497
|
+
)
|
|
498
|
+
);
|
|
499
|
+
} else
|
|
500
|
+
for (const [i, row] of section.rows.entries())
|
|
501
|
+
lines.push(
|
|
502
|
+
` ${columns.map(
|
|
503
|
+
(column) => cell(
|
|
504
|
+
column.label,
|
|
505
|
+
column.key,
|
|
506
|
+
row[column.key],
|
|
507
|
+
`data.${section.key}.${i}.${column.key}`,
|
|
508
|
+
column.positional,
|
|
509
|
+
column.default,
|
|
510
|
+
loose.has(column.key)
|
|
511
|
+
)
|
|
512
|
+
).filter((text) => text !== null).join(" \xB7 ")}`
|
|
513
|
+
);
|
|
514
|
+
if (!section.rows.length && !named && !section.page) lines.push("No records.");
|
|
515
|
+
pageLine(section.page);
|
|
516
|
+
} else if (section.kind === "messages") {
|
|
517
|
+
title(named, section.summary);
|
|
518
|
+
for (const [g, group] of section.groups.entries()) {
|
|
519
|
+
lines.push(` ${metadata(group.facts, `data.${section.key}.${g}`)}`);
|
|
520
|
+
for (const [m, message] of group.messages.entries()) {
|
|
521
|
+
lines.push(` ${metadata(message.facts, `data.${section.key}.${g}.messages.${m}`)}`);
|
|
522
|
+
lines.push(
|
|
523
|
+
...message.text.split("\n").map(
|
|
524
|
+
(line) => ` ${line.replaceAll(new RegExp("\\p{Cc}", "gu"), (char) => char === " " ? char : "")}`
|
|
525
|
+
)
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
if (!section.groups.length && !named && !section.page) lines.push("No messages.");
|
|
530
|
+
pageLine(section.page);
|
|
531
|
+
} else if (section.kind === "diagnostics") {
|
|
532
|
+
const limit = options.detail ? section.items.length : section.preview ?? 3;
|
|
533
|
+
for (const item of section.items.slice(0, limit))
|
|
534
|
+
lines.push(
|
|
535
|
+
` ${item.location ? `${clean(item.location)} ` : ""}${clean(item.code)}: ${value(item.message, `data.${section.key}`)}`
|
|
536
|
+
);
|
|
537
|
+
if (limit < section.items.length)
|
|
538
|
+
omissions.push({
|
|
539
|
+
path: `data.${section.key}`,
|
|
540
|
+
reason: "preview",
|
|
541
|
+
count: section.items.length - limit
|
|
542
|
+
});
|
|
543
|
+
} else {
|
|
544
|
+
title(named && `${named}:`, section.summary);
|
|
545
|
+
lines.push(
|
|
546
|
+
...section.text.trimEnd().split("\n").map(
|
|
547
|
+
(line) => ` ${line.replaceAll(new RegExp("\\p{Cc}", "gu"), (char) => char === " " || char === "\n" ? char : "")}`
|
|
548
|
+
)
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
if (wire.page) pageLine(wire.page);
|
|
553
|
+
if (code || (wire.effects ?? []).some((effect) => effect.state !== "confirmed"))
|
|
554
|
+
lines.push(...effectLines(wire.effects ?? []));
|
|
555
|
+
for (const warning of wire.warnings ?? []) lines.push(`Warning: ${clean(warning.message)}`);
|
|
556
|
+
const actions = [...view.actions ?? wire.next ?? [], ...errorActions];
|
|
557
|
+
const used = /* @__PURE__ */ new Set();
|
|
558
|
+
const details = actions.find((action) => action.label === "Details");
|
|
559
|
+
for (const omission of omissions) {
|
|
560
|
+
if (omission.count === void 0) continue;
|
|
561
|
+
const more = `${omission.count} more ${lastSegment(omission.path)}`;
|
|
562
|
+
if (details && !used.has(details)) {
|
|
563
|
+
used.add(details);
|
|
564
|
+
lines.push(`${more} \xB7 Details: ${actionText(details)}`);
|
|
565
|
+
} else lines.push(more);
|
|
566
|
+
}
|
|
567
|
+
if (!details && !options.detail && omissions.some((item) => item.reason === "preview" && item.count === void 0))
|
|
568
|
+
lines.push("Some values are clipped; add --detail to see them in full.");
|
|
569
|
+
for (const action of actions)
|
|
570
|
+
if (!used.has(action))
|
|
571
|
+
lines.push(
|
|
572
|
+
`${clean(action.label ?? "Next")}: ${action.reason ? `${clean(action.reason)} \xB7 ` : ""}${actionText(action)}`
|
|
573
|
+
);
|
|
574
|
+
return `${lines.join("\n")}
|
|
575
|
+
`;
|
|
576
|
+
}
|
|
577
|
+
function renderFailure(wire, options, code = 1) {
|
|
578
|
+
return renderText(
|
|
579
|
+
{ heading: commandName(wire.command), status: "", facts: [], sections: [] },
|
|
580
|
+
wire,
|
|
581
|
+
{
|
|
582
|
+
...options,
|
|
583
|
+
fields: void 0
|
|
584
|
+
},
|
|
585
|
+
void 0,
|
|
586
|
+
[],
|
|
587
|
+
code
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// src/cli/output/bootstrap/index.ts
|
|
592
|
+
function resolveSelection(argv) {
|
|
593
|
+
return selectOutput(argv, define_BOOTSTRAP_OPTIONS_default, configuredEnvironment(argv, define_BOOTSTRAP_OPTIONS_default));
|
|
594
|
+
}
|
|
595
|
+
function reportFailure(argv, error, selection) {
|
|
596
|
+
let selected;
|
|
597
|
+
try {
|
|
598
|
+
selected = selection ?? resolveSelection(argv);
|
|
599
|
+
} catch {
|
|
600
|
+
selected = selectOutput(argv, define_BOOTSTRAP_OPTIONS_default);
|
|
601
|
+
}
|
|
602
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
603
|
+
const detail = selected.error?.error ?? (error instanceof OutputError ? error.error : { code: "E_BOOTSTRAP_FAILED", message });
|
|
604
|
+
const failure = result(null, { kind: "failed", error: detail });
|
|
605
|
+
const wire = {
|
|
606
|
+
...normalize(
|
|
607
|
+
argv[0] && !argv[0].startsWith("-") ? argv[0] : "browse",
|
|
608
|
+
failure,
|
|
609
|
+
{ format: selected.options.format },
|
|
610
|
+
{ formats: [selected.options.format] }
|
|
611
|
+
),
|
|
612
|
+
error: detail
|
|
613
|
+
};
|
|
614
|
+
if (selected.options.format === "json") process.stdout.write(`${JSON.stringify(wire)}
|
|
615
|
+
`);
|
|
616
|
+
else if (selected.options.format === "jsonl")
|
|
617
|
+
process.stdout.write(`${JSON.stringify({ ...wire, seq: 0, kind: "result" })}
|
|
618
|
+
`);
|
|
619
|
+
else process.stderr.write(renderFailure(wire, selected.options));
|
|
620
|
+
process.exitCode = 1;
|
|
621
|
+
}
|
|
622
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
623
|
+
0 && (module.exports = {
|
|
624
|
+
reportFailure,
|
|
625
|
+
resolveSelection
|
|
626
|
+
});
|
package/dist/server.cjs
CHANGED
|
@@ -63,7 +63,7 @@ React keys must be passed directly to JSX without using spread:
|
|
|
63
63
|
`+Object.keys(C).map(Q=>`${Q}: ${C[Q]}`).join(`\r
|
|
64
64
|
`)+`\r
|
|
65
65
|
\r
|
|
66
|
-
`+I)}function q2(g,A,I,C,Q,B){if(g.listenerCount("wsClientError")){let e=new Error(Q);Error.captureStackTrace(e,q2),g.emit("wsClientError",e,I,A)}else dm(I,C,Q,B)}});var b7g=require("node:child_process"),T7g=WA(require("node:crypto"),1),V1=WA(require("node:fs"),1),pxA=WA(require("node:os"),1),AdA=WA(require("node:path"),1);var hk="1.
|
|
66
|
+
`+I)}function q2(g,A,I,C,Q,B){if(g.listenerCount("wsClientError")){let e=new Error(Q);Error.captureStackTrace(e,q2),g.emit("wsClientError",e,I,A)}else dm(I,C,Q,B)}});var b7g=require("node:child_process"),T7g=WA(require("node:crypto"),1),V1=WA(require("node:fs"),1),pxA=WA(require("node:os"),1),AdA=WA(require("node:path"),1);var hk="1.71.0";var h4A=require("node:child_process"),l4A=require("node:util");var E4A=[27319,27320,27321];var idA=WA(require("node:crypto"),1),mm=WA(require("node:fs"),1);var o4A={html:"text/html; charset=utf-8",js:"text/javascript; charset=utf-8",mjs:"text/javascript; charset=utf-8",css:"text/css; charset=utf-8",json:"application/json; charset=utf-8",xml:"application/xml; charset=utf-8",txt:"text/plain; charset=utf-8",svg:"image/svg+xml",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",webp:"image/webp",avif:"image/avif",ico:"image/x-icon",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf",mp4:"video/mp4",webm:"video/webm"},i4A=o4A.json;function Lm(g){let A=g.slice(Math.max(g.lastIndexOf("/"),g.lastIndexOf("\\"))+1),I=A.lastIndexOf(".");return I>0&&o4A[A.slice(I+1).toLowerCase()]||"application/octet-stream"}var $c=()=>idA.default.randomBytes(24).toString("base64url");function $0(g,A){let I=Buffer.from(g),C=Buffer.from(A);return I.length===C.length&&idA.default.timingSafeEqual(I,C)}function n4A(g){let A={};for(let I of(g??"").split(";")){let C=I.indexOf("=");C>0&&(A[I.slice(0,C).trim()]=I.slice(C+1).trim())}return A}function lk(g){try{return mm.default.readFileSync(g,"utf8").trim()}catch{return""}}function wk(g,A,I){return new Promise((C,Q)=>{let B=t=>{g.off("listening",e),Q(t)},e=()=>{g.off("error",B),C(g.address().port)};g.once("error",B),g.once("listening",e),g.listen(I,A)})}var v2=g=>g.includes(":")&&!g.startsWith("[")?`[${g}]`:g;function QI(g,A,I,C={}){g.writeHead(A,{"Referrer-Policy":"no-referrer","Cache-Control":"no-store",...C}),g.end(I)}function cg(g,A,I){QI(g,A,JSON.stringify(I),{"Content-Type":i4A})}function uWg(g,A){let I=g&&/^bytes=(\d*)-(\d*)$/.exec(g.trim());if(!I||!I[1]&&!I[2])return null;let C=I[1]?Number(I[1]):Math.max(0,A-Number(I[2])),Q=I[1]&&I[2]?Math.min(Number(I[2]),A-1):A-1;return C>Q||C>=A?"unsatisfiable":{start:C,end:Q}}function O2(g,A,I={},C){mm.default.stat(A,(Q,B)=>{if(Q||!B.isFile()){QI(g,404,"Not found");return}let e={"Referrer-Policy":"no-referrer","Cache-Control":"no-store","Content-Type":Lm(A),"Accept-Ranges":"bytes",...I},t=uWg(C,B.size);if(t==="unsatisfiable"){g.writeHead(416,{...e,"Content-Range":`bytes */${B.size}`}),g.end();return}t?g.writeHead(206,{...e,"Content-Range":`bytes ${t.start}-${t.end}/${B.size}`,"Content-Length":String(t.end-t.start+1)}):g.writeHead(200,{...e,"Content-Length":String(B.size)}),mm.default.createReadStream(A,t??{}).on("error",()=>g.destroy()).pipe(g)})}var MWg=[27329,27330,27331];function ndA(g,A){let I=A==="main"?g.RYUGI_ARTIFACTS_PORTS:g.RYUGI_ARTIFACTS_BOARD_PORTS,C=A==="main"?E4A:MWg;if(!I)return C;let Q=I.split(",").map(B=>Number(B.trim()));return Q.length&&Q.every(B=>Number.isInteger(B)&&B>=0&&B<65536)?Q:C}async function adA(g,A,I){for(let C of I)try{return await wk(g,A,C)}catch(Q){if(Q.code!=="EADDRINUSE")throw Q}throw new Error(`Ports ${I.join(", ")} are all in use; pick a free one with --port <n>`)}var a4A="--artifacts-server-id=",s4A="--port=",fWg="https://ryugi.innei.dev",SWg=g=>g==="127.0.0.1"||g==="localhost"||g==="::1";function r4A(g,A=[]){let I=g.ARTIFACTS_HOST||"127.0.0.1",C=g.ARTIFACTS_URL_HOST||(SWg(I)?"localhost":I),Q=A.find(t=>t.startsWith(a4A)),B=A.find(t=>t.startsWith(s4A)),e=B?Number(B.slice(s4A.length)):NaN;return{host:I,urlHost:C,ports:Number.isInteger(e)&&e>=0&&e<65536?[e]:ndA(g,"main"),boardPorts:ndA(g,"board"),openCmd:g.ARTIFACTS_OPEN_CMD||null,serverId:Q?Q.slice(a4A.length):null,cloudOrigin:(g.RYUGI_CLOUD_ORIGIN||fWg).replace(/\/+$/,"")}}function c4A(g,A){return g==="darwin"?{bin:"open",args:[A]}:g==="win32"?{bin:"cmd",args:["/c","start",'""',A]}:g==="linux"||g==="freebsd"||g==="openbsd"?{bin:"xdg-open",args:[A]}:null}var D4A=(0,l4A.promisify)(h4A.execFile),pWg=String.raw`
|
|
67
67
|
function run(urls) {
|
|
68
68
|
function key(url) {
|
|
69
69
|
return String(url).split(/[?#]/)[0].replace(/^(https?:\/\/)127\.0\.0\.1:/, '$1localhost:').replace(/\/$/, '');
|
package/dist/viewer-lib/index.js
CHANGED
|
@@ -11671,7 +11671,7 @@ function Nm(e, t) {
|
|
|
11671
11671
|
return e.code === "plan_limit" && jm(e.limit) ? Mm(e.limit) : Am(e.code, typeof e.error == "string" ? e.error : t);
|
|
11672
11672
|
}
|
|
11673
11673
|
// src/viewer/lib/version.ts
|
|
11674
|
-
var Pm = "1.
|
|
11674
|
+
var Pm = "1.71.0", Fm = {
|
|
11675
11675
|
path: (e, t) => `/a/${t}`,
|
|
11676
11676
|
refId: (e) => e.to,
|
|
11677
11677
|
frameSrc: (e, t) => `/a/${t}/view`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ryugi-artifacts",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.71.0",
|
|
4
4
|
"description": "Server and viewer for the Ryugi artifacts app",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"./package.json": "./package.json"
|
|
33
33
|
},
|
|
34
34
|
"bin": {
|
|
35
|
-
"ryugi
|
|
35
|
+
"ryugi": "bin/ryugi.cjs",
|
|
36
|
+
"ryugi-artifacts": "bin/ryugi.cjs"
|
|
36
37
|
},
|
|
37
38
|
"files": [
|
|
38
39
|
"bin",
|
|
@@ -54,7 +55,9 @@
|
|
|
54
55
|
"build:viewer": "NODE_ENV=production vite build && node scripts/plugin-dir.mjs dist/viewer viewer",
|
|
55
56
|
"dev": "vite",
|
|
56
57
|
"prepublishOnly": "pnpm build",
|
|
57
|
-
"
|
|
58
|
+
"sync:plugin": "node scripts/sync-plugin.mjs",
|
|
59
|
+
"test": "pnpm run test:build && vitest run",
|
|
60
|
+
"test:build": "node --test test/plugin-sync.test.mjs",
|
|
58
61
|
"typecheck": "tsrs --noEmit -p tsconfig.json"
|
|
59
62
|
},
|
|
60
63
|
"devDependencies": {
|
|
File without changes
|