dsh-runnpu 0.1.0 → 0.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-runnpu",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "DeepSeek Harness plugin adding two agent modes over RunNPU: compute management (cluster dashboard, pinned charts) and training (SwanLab-instrumented runs on a NPU cluster).",
5
5
  "keywords": [
6
6
  "deepseek-harness",
@@ -1,4 +0,0 @@
1
- import{randomUUID as K}from"node:crypto";import{readFile as H,writeFile as g,mkdir as v,chmod as R,readdir as P,rename as U,rm as _}from"node:fs/promises";import{existsSync as w}from"node:fs";import{homedir as C}from"node:os";import{join as s,resolve as A}from"node:path";var L=".train",x={apiHost:"https://api.swanlab.cn",webHost:"https://swanlab.cn"},S={runnpuToken:"RUNNPU_TOKEN",swanlabApiKey:"SWANLAB_API_KEY"};function N(){let e=process.env.DSH_HOME||s(C(),".dsh");return s(e,"runnpu-modes")}async function f(e){try{return JSON.parse(await H(e,"utf8"))}catch{return}}async function m(e,n,r){await v(s(e,".."),{recursive:!0}),await g(e,`${JSON.stringify(n,void 0,2)}
2
- `,{encoding:"utf8",mode:r}),r!==void 0&&await R(e,r)}function l(e){return s(A(e),L)}async function I(e){if(!e)return{config:void 0,secrets:void 0,dir:void 0};let n=l(e);return{dir:n,config:await f(s(n,"config.json")),secrets:await f(s(n,"secrets.json"))}}async function D(e){let n=l(e);await v(s(n,"runs"),{recursive:!0});let r=s(n,".gitignore");return w(r)||await g(r,`secrets.json
3
- `,"utf8"),n}async function G(e,n){let r=await D(e),i={...await f(s(r,"config.json"))??{},...n,updatedAt:new Date().toISOString()};return await m(s(r,"config.json"),i),i}async function J(e,n){let r=await D(e),t=s(r,"secrets.json"),o={...await f(t)??{}};for(let[a,c]of Object.entries(n))c===void 0||c===""?delete o[a]:o[a]=c;return await m(t,o,384),Object.keys(o)}async function h(e,n,r){let t=r?.[n];if(typeof t=="string"&&t!=="")return{value:t,source:"project"};let i=e.get?.("credentials");if(i)try{let a=await i.resolve(n);if(a?.value)return{value:a.value,source:`credentials:${a.source}`}}catch{}let o=process.env[n];if(o)return{value:o,source:"env"}}async function V(e,n,r,t){if(t.scope==="project"){if(!t.cwd)throw new Error("project scope needs a workspace");return await J(t.cwd,{[n]:r}),"project"}let i=e.get?.("credentials");if(!i)throw new Error("credential provider unavailable; use project scope");return await i.set(n,r),"credentials"}async function E(e,n,r){let{config:t,secrets:i,dir:o}=await I(r),a=await f(s(N(),"connections.json"))??{},c=t?.runnpu?.server||a.runnpu?.server||n?.runnpu?.server||process.env.RUNNPU_SERVER||"",p=await h(e,S.runnpuToken,i),u=t?.swanlab?.mode||a.swanlab?.mode||"cloud",d=u==="cloud",j=t?.swanlab?.apiHost||a.swanlab?.apiHost||(d?x.apiHost:""),O=t?.swanlab?.webHost||a.swanlab?.webHost||(d?x.webHost:""),b=await h(e,S.swanlabApiKey,i);return{workspace:r??void 0,trainDir:o,runnpu:{server:c,configured:!!(c&&p),tokenSource:p?.source,token:p?.value},swanlab:{mode:u,apiHost:j,webHost:O,configured:!!(j&&b),apiKeySource:b?.source,apiKey:b?.value}}}async function Y(e,n,r){let t=await E(e,n,r);return{workspace:t.workspace,trainDir:t.trainDir,runnpu:{server:t.runnpu.server,configured:t.runnpu.configured,tokenSource:t.runnpu.tokenSource},swanlab:{mode:t.swanlab.mode,apiHost:t.swanlab.apiHost,webHost:t.swanlab.webHost,configured:t.swanlab.configured,apiKeySource:t.swanlab.apiKeySource}}}async function Q(e,n,r){return await E(e,n,r)}async function X(e){let n=s(N(),"connections.json"),t={...await f(n)??{},...e};return await m(n,t),t}async function Z(e){if(!e)return[];let n=s(l(e),"runs"),r;try{r=await P(n)}catch{return[]}let t=[];for(let i of r.filter(o=>o.endsWith(".json")).sort().reverse()){let o=await f(s(n,i));o&&t.push(o)}return t}function T(e){return`${String(e).padStart(4,"0")}.json`}var k=Object.freeze(["swanlabRun","status","endedAt","swanlabUpload"]),y=new Map;function $(e,n){let r=A(e),i=(y.get(r)??Promise.resolve()).then(n),o=i.catch(()=>{});return y.set(r,o),o.then(()=>{y.get(r)===o&&y.delete(r)}),i}async function F(e,n){await v(s(e,".."),{recursive:!0});let r=`${e}.${K().slice(0,8)}.tmp`;await g(r,`${JSON.stringify(n,void 0,2)}
4
- `,"utf8");try{await U(r,e)}catch(t){throw await _(r,{force:!0}),t}}async function ee(e,n,r){return await $(e,async()=>{let t=s(l(e),"runs",T(n)),i=r??{},o=Object.keys(i).filter(u=>!k.includes(u)),a=await f(t);if(!a)return{path:t,run:void 0,changed:[],ignored:o};let c={...a},p=[];for(let u of k){if(!(u in i))continue;let d=i[u];d===void 0||d===a[u]||(c[u]=d,p.push(u))}return p.length===0?{path:t,run:a,changed:p,ignored:o}:(await F(t,c),{path:t,run:c,changed:p,ignored:o})})}async function ne(e){if(e)return await f(s(l(e),"metrics.json"))}async function te(e){if(!e)return!1;if(w(l(e))||w(s(e,"train.py")))return!0;for(let n of["requirements.txt","pyproject.toml"])try{let r=await H(s(e,n),"utf8");if(/\b(torch|transformers|deepspeed|swanlab|accelerate|ultralytics)\b/i.test(r))return!0}catch{}for(let n of["configs","config"])if(w(s(e,n,"accelerate.yaml"))||w(s(e,n,"deepspeed.json")))return!0;return!1}export{x as a,S as b,N as c,l as d,I as e,D as f,G as g,J as h,V as i,Y as j,Q as k,X as l,Z as m,ee as n,ne as o,te as p};
@@ -1,9 +0,0 @@
1
- import{randomBytes as m,timingSafeEqual as b}from"node:crypto";var y=m(32).toString("base64url"),N="x-runnpu-nonce",E="nonce",a=0,d;function _(r){let t=r.get("webServer");t&&r.effect(()=>(a+=1,a===1&&(d=t.tapIndex(e=>e.replace("</head>",`<script>globalThis.__RUNNPU_NONCE__=${JSON.stringify(y)}</script></head>`))),()=>{a-=1,!(a>0)&&(d?.(),d=void 0)}),"runnpu: index nonce injection")}function p(r){if(typeof r!="string"||r.length===0)return!1;let t=Buffer.from(r,"utf8"),e=Buffer.from(y,"utf8");return t.byteLength===e.byteLength&&b(t,e)}function u(r,t){let e=r.headers?.[N];if(p(Array.isArray(e)?e[0]:e))return!0;let n=t??new URL(r.url??"/","http://127.0.0.1");return p(n.searchParams.get(E)??"")}function x(r,t,e){let n=JSON.stringify(e);r.writeHead(t,{"content-type":"application/json; charset=utf-8","cache-control":"no-store","content-length":Buffer.byteLength(n)}),r.end(n)}function h(r,t,e,n,o){x(r,t,{error:e,status:t,message:n,details:o})}async function H(r,t=256*1024){let e=[],n=0;for await(let o of r){if(n+=o.length,n>t)throw Object.assign(new Error(`request body exceeds ${t} bytes`),{status:413,code:"body_too_large"});e.push(o)}if(n!==0)try{return JSON.parse(Buffer.concat(e).toString("utf8"))}catch(o){throw Object.assign(new Error(`request body is not valid JSON: ${o.message}`),{status:400,code:"bad_json"})}}function S(r){let t=r.headers.origin;if(!t)return!0;try{let e=new URL(t);return e.hostname==="127.0.0.1"||e.hostname==="localhost"||e.hostname==="[::1]"}catch{return!1}}function J(r){return async(t,e)=>{try{let n=new URL(t.url??"/","http://127.0.0.1"),o=r[t.method??"GET"];if(!o){e.writeHead(405,{allow:Object.keys(r).join(", ")}).end();return}if(t.method!=="GET"&&t.method!=="HEAD"&&!S(t)){h(e,403,"forbidden_origin","cross-origin request refused");return}if(!u(t,n)){h(e,401,"unauthenticated","\u7F3A\u5C11\u6216\u65E0\u6548\u7684\u63D2\u4EF6\u8BF7\u6C42\u4EE4\u724C");return}await o(t,e,n)}catch(n){if(e.headersSent){e.end();return}h(e,n?.status&&Number.isInteger(n.status)?n.status:500,n?.code??"internal_error",String(n?.message??n),n?.details)}}}var f=class{#e=new Set;subscribe(t,e){e.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache, no-transform",connection:"keep-alive"}),e.write(`: connected
2
-
3
- `);let n={res:e};this.#e.add(n);let o=()=>{this.#e.delete(n);try{e.end()}catch{}};return t.on("close",o),o}publish(t,e){let n=`event: ${t}
4
- data: ${JSON.stringify(e)}
5
-
6
- `;for(let o of this.#e)try{o.res.write(n)}catch{this.#e.delete(o)}}closeAll(){for(let t of this.#e)try{t.res.end()}catch{}this.#e.clear()}get size(){return this.#e.size}};function v(r,t,e){try{r.write(`event: ${t}
7
- data: ${JSON.stringify(e)}
8
-
9
- `)}catch{}}function R({refresh:r,intervalMs:t}){let e=new f;async function n(){await r()}function o(i,c,s){if(i.method!=="GET"){c.writeHead(405,{allow:"GET"}).end();return}if(!u(i)){c.writeHead(401,{"content-type":"application/json"}).end('{"error":"unauthenticated"}');return}if(e.subscribe(i,c),s?.onClose&&i.on("close",s.onClose),!!s?.seed)try{s.seed((l,w)=>v(c,l,w))}catch{}}function g(i,c){i.effect(()=>{let s=!1,l=setInterval(()=>{e.size!==0&&(s||(s=!0,n().catch(()=>{}).finally(()=>{s=!1})))},t);return()=>clearInterval(l)},`${c}: refresh loop`),i.effect(()=>()=>e.closeAll(),`${c}: sse teardown`)}return{hub:e,handler:o,install:g}}export{_ as a,x as b,h as c,H as d,J as e,R as f};