@ours.network/sdk 3.0.1 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/api/contacts.js +1 -1
- package/dist/api/files.js +1 -1
- package/dist/api/history.d.ts +4 -1
- package/dist/api/history.js +1 -1
- package/dist/api/identity.js +1 -1
- package/dist/api/messaging.d.ts +1 -0
- package/dist/api/messaging.js +1 -1
- package/dist/api/profile.js +1 -1
- package/dist/book.js +1 -1
- package/dist/boot.js +1 -1
- package/dist/{chunk-GVEBDMN6.js → chunk-2XOTJ6G3.js} +1 -1
- package/dist/chunk-5KVWI5BW.js +2 -0
- package/dist/{chunk-54BIUFRS.js → chunk-5OAIOIQ2.js} +1 -1
- package/dist/{chunk-YBNUNQNM.js → chunk-67DAPEUW.js} +1 -1
- package/dist/{chunk-ZWUFPR6V.js → chunk-ETBJ4VOK.js} +1 -1
- package/dist/{chunk-SQ4M4QQA.js → chunk-GJXNZNS6.js} +1 -1
- package/dist/{chunk-PMSTI7RY.js → chunk-HZCFYJAG.js} +1 -1
- package/dist/{chunk-HEWVNFUK.js → chunk-J2Q2JDUS.js} +1 -1
- package/dist/{chunk-WSEDMA2W.js → chunk-JTQMUWPE.js} +1 -1
- package/dist/{chunk-6XZYUNSM.js → chunk-LPXPNZTS.js} +1 -1
- package/dist/{chunk-O2QIPLR6.js → chunk-LRMN6BSO.js} +1 -1
- package/dist/{chunk-K3NRXUJW.js → chunk-M2WREVID.js} +1 -1
- package/dist/{chunk-YZJB6DZI.js → chunk-NODVUYDQ.js} +1 -1
- package/dist/{chunk-3NTV3JFP.js → chunk-O3WRMYAS.js} +1 -1
- package/dist/{chunk-WFONSX5L.js → chunk-PBLR7J42.js} +1 -1
- package/dist/{chunk-S24UCZDR.js → chunk-PJ5F7BI6.js} +1 -1
- package/dist/{chunk-5WE5G2CD.js → chunk-PMDY4YIZ.js} +1 -1
- package/dist/{chunk-4DWIX7KY.js → chunk-PXIK7DM2.js} +1 -1
- package/dist/{chunk-Z5IFINRU.js → chunk-SBKG5P7O.js} +1 -1
- package/dist/{chunk-FOFYSUCT.js → chunk-SEZTXIKN.js} +1 -1
- package/dist/{chunk-DYQHWN7X.js → chunk-TXAIJEXA.js} +28 -22
- package/dist/{chunk-IWY6MRSV.js → chunk-ZLCQNN5W.js} +1 -1
- package/dist/chunk-ZPG5V73S.js +2 -0
- package/dist/client/http.d.ts +1 -0
- package/dist/client/http.js +1 -1
- package/dist/client/select.js +1 -1
- package/dist/client.js +1 -1
- package/dist/cluster/control.js +1 -1
- package/dist/cluster/manifest.js +1 -1
- package/dist/connector.js +1 -1
- package/dist/gc.js +1 -1
- package/dist/history.d.ts +8 -0
- package/dist/history.js +1 -1
- package/dist/http/api-routes.d.ts +1 -0
- package/dist/http/api-routes.js +1 -1
- package/dist/http/server.js +1 -1
- package/dist/identity/hierarchy.js +1 -1
- package/dist/identity/lease.js +1 -1
- package/dist/identity/lifecycle.js +1 -1
- package/dist/identity/model.js +1 -1
- package/dist/identity/provision.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/messaging/send.js +1 -1
- package/dist/mufl/handlers.js +1 -1
- package/dist/mufl/tx.js +1 -1
- package/dist/mufl_code/351F16D444E6DAA252D4A8D829D17204360D9015FEF670ACE68FB4747BB3B14E.muflo +0 -0
- package/dist/notify.js +1 -1
- package/dist/runtime/env.js +1 -1
- package/dist/state.js +1 -1
- package/dist/sweeps.js +1 -1
- package/dist/uploads.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-PLCNB2IO.js +0 -2
- package/dist/chunk-VNZYANLS.js +0 -2
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{a as se,b as A}from"./chunk-
|
|
2
|
+
import{a as se,b as A}from"./chunk-J2Q2JDUS.js";import{M as p,a as T,f as k,g as q,h as W,i as z,j as U,k as Y,l as G,m as J,n as K,o as Q,p as S,q as X,r as Z,s as ee,t as te,u as oe,v as ne,w as re,x as ie}from"./chunk-65KGEJBX.js";import{a as ae,c as de}from"./chunk-M2WREVID.js";import{b as f,e as b,f as N,g as E}from"./chunk-GJXNZNS6.js";import{j as L,k as _,r as M,v as j}from"./chunk-NODVUYDQ.js";import{a as h,b as v,e as I,f as B,g as H,h as V,i as g}from"./chunk-PMDY4YIZ.js";import{c,n as w,o as $}from"./chunk-ETBJ4VOK.js";import{i as R,p as x}from"./chunk-ZLCQNN5W.js";import{k as D,m as F}from"./chunk-WS6UFNKF.js";import{randomBytes as ce}from"node:crypto";import{isAbsolute as me}from"node:path";function le(r){try{return b(r)}catch{return null}}function C(r){let o=le(r);return{name:r.name,cid:r.cid,bio:o?.bio??"",persona:o?.persona??"",roleId:o?.roleId??"",rootCid:o?.rootCid??"",rootName:o?.rootName??""}}async function P(r,o){o&&await M(async e=>{await j(r,"::a2a_messaging::set_my_bio",{bio:o},e)})}function pe(r){let o=V(r.sessionId());if(!("error"in o))return o.id;throw new T(o.code,o.error)}async function ke(r,o){let{name:e,bio:i,exposeLocal:d,localAutoAccept:s}=o,n=x(e);if(n)throw p("create_identity",n,"NAME_INVALID");if(c.has(e))throw k("create_identity",e);try{let t=await _(e,{exposeLocal:d,localAutoAccept:s});await P(t,i);let a,l=null,m=[],u=[],y=f?c.get(f):void 0;if(y)await N(y,t),a="role",l=y.name,ae()&&de(y);else{a="root";let O=await E(t);m=O.adopted,u=O.failed}return g(r.sessionId(),e),{info:C(t),hierarchy:a,underRoot:l,adopted:m,failed:u,exposedLocal:d,localAutoAccept:s}}catch(t){throw p("create_identity",String(t),"PROVISION_FAILED")}}async function Ae(r,o){let{bio:e,exposeLocal:i,localAutoAccept:d}=o,s=r.leaseToken(),n=r.clientPid();if(!s||!n)throw q();let t=o.name;if(t!==void 0){let l=x(t);if(l)throw p("create_temporary_identity",l,"NAME_INVALID");if(c.has(t)||L.has(t))throw k("create_temporary_identity",t)}else{for(let l=0;l<5&&t===void 0;l++){let m=`tmp-${ce(5).toString("hex")}`;!c.has(m)&&!L.has(m)&&(t=m)}if(t===void 0)throw W()}let a=t;try{let l=await _(a,{exposeLocal:i,localAutoAccept:d,temp:{tokenHash:w(s),pid:n}});return await P(l,e),g(r.sessionId(),a),{info:C(l),ownerPid:n,exposedLocal:i,localAutoAccept:d}}catch(l){throw p("create_temporary_identity",String(l),"PROVISION_FAILED")}}async function Ce(r,o){let e=r.leaseToken(),i;if(o.name!==void 0){if(i=c.get(o.name),!i)return{name:o.name,result:null}}else{let n=e?B(e):void 0;if(i=n?c.get(n.identity):void 0,!i)throw U()}if(!i.temp)throw Y(i.name);let d=i.temp.owner,s=e!==void 0&&d.tokenHash===w(e);if(!s&&!i.temp.closing&&I(d.pid))throw G(i.name,d.pid);try{let n=await A(i,s?"explicit close by owner":"stale reclaim via close_temporary_identity");if(n.deleteError){let t=n.attempted===0?"It had no contacts, so no remove-me notices were needed.":`Remove-me notices: ${n.notified}/${n.attempted} queued, ${n.failed} not sent (best effort \u2014 delivery and remote contact deletion are not guaranteed).`;throw J(i.name,n.deleteError,t)}return{name:i.name,result:n}}catch(n){throw n instanceof T?n:p("close_temporary_identity",String(n),"CLOSE_FAILED")}}async function ve(r,o){let{name:e,bio:i,exposeLocal:d,localAutoAccept:s,skipIfRootExists:n}=o,t=x(e);if(t)throw p("create_root_identity",t,"NAME_INVALID");let a=f;if(n&&a&&c.has(a))throw z(a);if(c.has(e))throw k("create_root_identity",e);try{let l=await _(e,{exposeLocal:d,localAutoAccept:s});await P(l,i);let m=f?c.get(f):void 0;if(m&&m.name!==e)return await N(m,l),g(r.sessionId(),e),{info:C(l),hierarchy:"role",underRoot:m.name,adopted:[],failed:[],exposedLocal:d,localAutoAccept:s};let{adopted:u,failed:y}=await E(l);return g(r.sessionId(),e),{info:C(l),hierarchy:"root",underRoot:null,adopted:u,failed:y,exposedLocal:d,localAutoAccept:s}}catch(l){throw p("create_root_identity",String(l),"PROVISION_FAILED")}}async function Le(r){if(!me(r.path))throw K(r.path);let o={name:r.name,force:r.force,exposeLocal:r.exposeLocal,localAutoAccept:r.localAutoAccept};try{return{written:F(r.path,o,r.overwrite),json:D(o)}}catch(e){throw p("define_local_identity_file",String(e),"WRITE_FAILED")}}async function Se(r,o){let{name:e,force:i}=o;if(!c.has(e))throw Q(e);let d=r.sessionId(),s=r.leaseToken();if(!s)throw S();let n=c.get(e);if(n.temp){if(n.temp.closing)throw X(e);let m=n.temp.owner;if(m.tokenHash!==w(s))throw I(m.pid)?Z(e,m.pid):ee(e,m.pid);let u=r.clientPid();if(u&&u!==m.pid){m.pid=u;try{$(n.dir,n.temp)}catch(y){R(`[${e}] temp marker refresh failed:`,String(y))}}}let t=h.get(e);if(t&&t.token!==s)if(!I(t.pid))R(`auto-reclaiming "${e}" from dead client pid ${t.pid}`),h.delete(e);else if(i)v.add(t.token),h.delete(e);else throw te(e);let a=[...h.values()].find(m=>m.token===s&&m.identity!==e)?.identity,l=a&&c.has(a)?a:null;return g(d,e),{name:e,cid:c.get(e).cid,switchedFrom:l}}async function Ne(r){if(c.size===0)return[];let o=r.leaseToken(),e=t=>{let a=h.get(t);return a?a.token===o?"mine":I(a.pid)?"other-live":null:null},i=t=>{if(!t.temp)return null;let a=t.temp.owner.pid;return t.temp.closing?{state:"closing",ownerPid:a}:o!==void 0&&t.temp.owner.tokenHash===w(o)?{state:"mine",ownerPid:a}:I(a)?{state:"other-live",ownerPid:a}:{state:"stale",ownerPid:a}},d=(t,a)=>({name:t.name,cid:t.cid,kind:a,temp:i(t),session:e(t.name)}),s=f?c.get(f):void 0,n=[];if(s){n.push({...d(s,"root"),temp:null});for(let t of c.values())t.name!==s.name&&b(t).roleId!==""&&n.push(d(t,"role"));for(let t of c.values())t.name===s.name||b(t).roleId!==""||n.push(d(t,"flat"))}else for(let t of c.values())n.push(d(t,"flat"));return n}async function Ee(r){let o=pe(r),e=le(o);return{name:o.name,cid:o.cid,bio:e?.bio??"",persona:e?.persona??"",roleId:e?.roleId??"",rootCid:e?.rootCid??"",rootName:e?.rootName??"",temporary:o.temp!==void 0,isRoot:o.name===f,described:e!==null}}async function Pe(r,o){let{name:e}=o,i=c.get(e);if(!i)throw p("remove_identity",`no identity named "${e}".`,"NO_SUCH_IDENTITY");if(i.temp){let s=r.leaseToken(),n=i.temp.owner;if((s===void 0||n.tokenHash!==w(s))&&!i.temp.closing&&I(n.pid))throw oe(e,n.pid);try{let t=await A(i,"remove_identity");if(t.deleteError){let a=t.attempted===0?"":` Remove-me notices: ${t.notified}/${t.attempted} queued, ${t.failed} not sent (best effort).`;throw ne(e,t.deleteError,a)}return{name:e,kind:"temporary",close:t}}catch(t){throw t instanceof T?t:p("remove_identity",String(t),"CLOSE_FAILED")}}if(e===f){let s=[...c.values()].filter(n=>n.name!==e&&b(n).rootCid===i.cid);if(s.length>0)throw re(e,s.map(n=>n.name))}let d=se(i);if(d)throw ie(e,d);return{name:e,kind:"permanent"}}async function Oe(r){let o=r.leaseToken();if(!o)throw S();let e=[];for(let[i,d]of[...h]){if(d.token!==o)continue;h.delete(i),e.push(i);let s=c.get(i);s?.temp&&s.temp.owner.tokenHash===w(o)&&!s.temp.closing&&A(s,"owning session released its lease").catch(n=>R(`[${i}] close on lease release failed:`,String(n)))}return v.delete(o),H(),R(`lease released by token \u2026${o.slice(-6)}`),{released:e}}export{pe as a,ke as b,Ae as c,Ce as d,ve as e,Le as f,Se as g,Ne as h,Ee as i,Pe as j,Oe as k};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{a as O}from"./chunk-
|
|
2
|
+
import{a as O}from"./chunk-HZCFYJAG.js";import{b as N,e as T}from"./chunk-WS6UFNKF.js";import{randomBytes as I}from"node:crypto";import{readFileSync as w}from"node:fs";import{homedir as x}from"node:os";import{join as v,resolve as p}from"node:path";var a=class extends Error{constructor(i,n){super(n);this.code=i;this.name="DaemonSelectionError"}},S=class extends a{constructor(i,n,d={}){super("DAEMON_UNAVAILABLE",`no ours daemon is running at ${i} for state directory ${JSON.stringify(n)}. Install the operator CLI with \`npm install --global @ours.network/cli\`, then start the shared daemon with \`ours daemon start\` or install/start its per-user service through \`ours daemon install-service\`. SDK applications attach to the shared daemon and do not start an embedded daemon.`);this.endpoint=i;this.stateDir=n;this.name="DaemonUnavailableError",d.cause!==void 0&&(this.cause=d.cause)}},b=N.port,C=T,R=".ours",k=["explicit","environment","config-file"];function _(e={}){let t=e.env??process.env,i=e.readTextFile??(h=>w(h,"utf8")),n=e.homeDir??x(),d=f(t,"OURS_INSTANCE");if(d!==void 0)throw new a("INCOHERENT_SELECTION",`OURS_INSTANCE=${JSON.stringify(d)} is set, but named daemon instances are not implemented. Select the daemon with an explicit endpoint/port option or with OURS_PORT, and unset OURS_INSTANCE.`);if(e.stateDir!==void 0&&e.expectStateDir!==void 0){let h=p(e.stateDir),D=p(e.expectStateDir);if(h!==D)throw new a("INCOHERENT_SELECTION",`stateDir ${JSON.stringify(h)} and expectStateDir ${JSON.stringify(D)} name different directories. The state directory decides which token is read; the expected one decides which daemon that token may be sent to. Reconcile them, or pass only one.`)}let r=V(e.configPath,f(t,"OURS_CONFIG")),s=r?L(r.value,i):{},o=E(e.port,F(f(t,"OURS_PORT")),s.port,b),c=E(e.stateDir??e.expectStateDir,f(t,"OURS_STATE_DIR"),s.stateDir,v(n,R)),l={value:p(c.value),source:c.source},g=e.endpoint!==void 0?{value:P(e.endpoint),source:"explicit"}:{value:`http://127.0.0.1:${o.value}`,source:o.source},m=f(t,"OURS_API_TOKEN");A({endpointSelected:e.endpoint!==void 0||o.source!=="default",endpointSource:g.source,stateDirIntentional:k.includes(l.source),stateDirSource:l.source,hasExplicitToken:e.token!==void 0&&e.token!=="",hasEnvToken:m!==void 0,requireExplicitSelection:e.requireExplicitSelection===!0,portSource:o.source});let y=U(e.token,m,s,l,i);return{baseUrl:g,port:o,stateDir:l,expectStateDir:e.expectStateDir!==void 0?p(e.expectStateDir):l.value,...y?{token:y}:{},...r?{configPath:r}:{}}}function K(e){return{baseUrl:e.baseUrl.value,baseUrlSource:e.baseUrl.source,port:e.port.value,portSource:e.port.source,stateDir:e.stateDir.value,stateDirSource:e.stateDir.source,expectStateDir:e.expectStateDir,tokenSource:e.token?.source??"none",configPath:e.configPath?.value??null}}function A(e){if(e.requireExplicitSelection){if(e.endpointSource==="default"&&e.portSource==="default")throw u(`requireExplicitSelection is set, but no daemon was selected. Pass endpoint/port, set OURS_PORT, or point OURS_CONFIG at a config file. Refusing the built-in default 127.0.0.1:${b}.`);if(!e.stateDirIntentional)throw u("requireExplicitSelection is set, but the state directory is the built-in default. Every auth-affecting field must be chosen deliberately: pass stateDir or expectStateDir, set OURS_STATE_DIR, or name a config file. Refusing before reading any token or opening any socket.")}if(e.endpointSelected&&!e.stateDirIntentional)throw u(`the endpoint was selected (source: ${e.endpointSource}) but the state directory is the built-in default. A daemon's API token belongs to one state directory, so reading the default token and sending it to a separately chosen endpoint would disclose a credential to it. Select the state directory too: stateDir, expectStateDir, OURS_STATE_DIR, or one config file. An explicit token alone is not enough \u2014 without an expected state directory there is nothing to assert the endpoint against before the token is sent.`);if(e.hasEnvToken&&!e.stateDirIntentional)throw u("OURS_API_TOKEN is set, but the state directory is the built-in default. An environment token is process-wide and authenticates to every daemon it is offered to, so it requires an explicitly expected state directory: pass stateDir or expectStateDir, or set OURS_STATE_DIR.");if(e.hasExplicitToken&&!e.stateDirIntentional)throw u("an explicit token was given, but the state directory is the built-in default, so there would be nothing to assert the daemon against before the token is sent. Pass expectStateDir (or stateDir) naming the state directory that token belongs to.")}function u(e){return new a("INCOHERENT_SELECTION",e)}function U(e,t,i,n,d){if(e!==void 0&&e!=="")return{value:e,source:"explicit"};if(t!==void 0)return{value:t,source:"environment"};let r=i.apiToken?.trim();if(r)return{value:r,source:"config-file"};try{let s=d(v(n.value,C)).trim();if(s)return{value:s,source:"token-file"}}catch{}}function L(e,t){let i;try{i=t(e)}catch{throw new a("CONFIG_UNREADABLE",`the daemon config file ${JSON.stringify(e)} could not be read.`)}let n;try{n=JSON.parse(i)}catch{throw new a("CONFIG_INVALID",`the daemon config file ${JSON.stringify(e)} is not valid JSON.`)}if(n===null||typeof n!="object"||Array.isArray(n))throw new a("CONFIG_INVALID",`the daemon config file ${JSON.stringify(e)} is not a JSON object.`);let d=n,r={},s=d.port;if(s!==void 0){if(typeof s!="number"||!Number.isInteger(s)||s<1||s>65535)throw new a("CONFIG_INVALID",`the daemon config file ${JSON.stringify(e)} declares an invalid port; expected an integer 1-65535.`);r.port=s}let o=d.stateDir;if(o!==void 0){if(typeof o!="string"||o.trim()==="")throw new a("CONFIG_INVALID",`the daemon config file ${JSON.stringify(e)} declares an invalid stateDir; expected a non-empty string.`);r.stateDir=o}let c=d.apiToken;if(c!==void 0){if(typeof c!="string"||c.trim()==="")throw new a("CONFIG_INVALID",`the daemon config file ${JSON.stringify(e)} declares an invalid apiToken; expected a non-empty string.`);r.apiToken=c}let l=d.apiVisibility;if(l!==void 0){if(l!=="owner"&&l!=="shared"&&l!=="open")throw new a("CONFIG_INVALID",`the daemon config file ${JSON.stringify(e)} declares an unknown apiVisibility ${JSON.stringify(l)}; expected "owner", "shared" or "open".`);r.apiVisibility=l}return r}function f(e,t){let i=e[t];if(i===void 0)return;let n=i.trim();return n===""?void 0:n}function F(e){if(e===void 0)return;let t=Number.parseInt(e,10);if(!Number.isInteger(t)||t<1||t>65535)throw new a("INCOHERENT_SELECTION",`OURS_PORT=${JSON.stringify(e)} is not a TCP port between 1 and 65535.`);return t}function P(e){return e.endsWith("/")?e.slice(0,-1):e}function E(e,t,i,n){return e!==void 0?{value:e,source:"explicit"}:t!==void 0?{value:t,source:"environment"}:i!==void 0?{value:i,source:"config-file"}:{value:n,source:"default"}}function V(e,t){if(e!==void 0)return{value:e,source:"explicit"};if(t!==void 0)return{value:t,source:"environment"}}async function $(e,t={}){let i=t.fetch??globalThis.fetch,n=new AbortController,d=setTimeout(()=>n.abort(),t.timeoutMs??5e3),r;try{let o=await i(`${e.baseUrl.value}/state-dir`,{signal:n.signal});if(!o.ok)throw new a("INCOHERENT_SELECTION",`${e.baseUrl.value}/state-dir answered HTTP ${o.status}, so the daemon at that address could not be identified. Refusing to send a credential to it.`);r=await o.json()}catch(o){throw o instanceof a?o:new S(e.baseUrl.value,e.expectStateDir,{cause:o})}finally{clearTimeout(d)}let s=typeof r.stateDir=="string"?p(r.stateDir):null;if(s===null)throw new a("INCOHERENT_SELECTION",`${e.baseUrl.value}/state-dir did not report a state directory, so this is not an ours daemon or not one this client understands. Refusing to send a credential to it.`);if(s!==e.expectStateDir)throw new a("INCOHERENT_SELECTION",`the daemon at ${e.baseUrl.value} owns state directory ${JSON.stringify(s)}, but this selection expects ${JSON.stringify(e.expectStateDir)}. The token belongs to the expected directory, so it is NOT being sent. Point the endpoint and the state directory at the same daemon.`)}async function j(e={}){let{leaseToken:t,clientPid:i,fetch:n,...d}=e,r=_(d);return await $(r,{fetch:n}),new O({url:r.baseUrl.value,leaseToken:t??I(32).toString("hex"),clientPid:i,apiToken:r.token?.value,fetch:n})}export{a,S as b,b as c,C as d,_ as e,K as f,$ as g,j as h};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{createHash as O,randomUUID as H}from"node:crypto";import*as o from"node:fs";import{dirname as y,join as
|
|
2
|
+
import{createHash as O,randomUUID as H}from"node:crypto";import*as o from"node:fs";import{dirname as y,join as l,resolve as R,sep as x}from"node:path";import A from"better-sqlite3";var m=200,C=50,b=2*1024*1024,D=8*1024*1024,M="history.sqlite3",N=1,p=new Map,f=new Map,E=new Map,U=t=>l(t.dir,M),Y=t=>l(t.dir,"blobs","sha256");function w(){return{write_failures:0,message_write_failures:0,file_write_failures:0,receipt_update_failures:0,last_failure_at_ms:null}}function $(t){return{...f.get(t.dir)??w()}}function K(t,e,r,s){let i=f.get(t.dir)??w();if(i.write_failures+=1,i.last_failure_at_ms=Date.now(),e==="message"?i.message_write_failures+=1:e==="file"?i.file_write_failures+=1:i.receipt_update_failures+=1,f.set(t.dir,i),s==="out"&&r){let n=E.get(t.dir);n||(n=new Set,E.set(t.dir,n)),n.add(r)}}function Q(t,e){let r=E.get(t.dir);return r?.delete(e)?(r.size===0&&E.delete(t.dir),!0):!1}function F(t){t.exec(`
|
|
3
3
|
CREATE TABLE IF NOT EXISTS history_meta (
|
|
4
4
|
key TEXT PRIMARY KEY,
|
|
5
5
|
value TEXT NOT NULL
|
|
@@ -79,7 +79,7 @@ import{createHash as O,randomUUID as H}from"node:crypto";import*as o from"node:f
|
|
|
79
79
|
inserted_at_ms INTEGER NOT NULL
|
|
80
80
|
);
|
|
81
81
|
CREATE INDEX IF NOT EXISTS control_pending_seq ON control_requests(queue_state, seq ASC);
|
|
82
|
-
`);let e=t.prepare("SELECT value FROM history_meta WHERE key = ?").pluck().get("schema_version");if(e!==void 0&&Number(e)!==N)throw new Error(`unsupported history database schema ${String(e)} (expected ${N})`);t.prepare("INSERT OR IGNORE INTO history_meta(key, value) VALUES (?, ?)").run("schema_version",String(N))}function d(t){let e=
|
|
82
|
+
`);let e=t.prepare("SELECT value FROM history_meta WHERE key = ?").pluck().get("schema_version");if(e!==void 0&&Number(e)!==N)throw new Error(`unsupported history database schema ${String(e)} (expected ${N})`);t.prepare("INSERT OR IGNORE INTO history_meta(key, value) VALUES (?, ?)").run("schema_version",String(N))}function d(t){let e=p.get(t.dir);if(e)return e;o.mkdirSync(t.dir,{recursive:!0,mode:448}),o.chmodSync(t.dir,448);let r=U(t),s=new A(r);try{o.chmodSync(r,384),s.pragma("journal_mode = WAL"),s.pragma("synchronous = NORMAL"),s.pragma("foreign_keys = ON"),s.pragma("busy_timeout = 5000"),F(s);for(let i of["","-wal","-shm"]){let n=`${r}${i}`;o.existsSync(n)&&o.chmodSync(n,384)}}catch(i){throw s.close(),i}return p.set(t.dir,s),s}function V(t){let e=p.get(t.dir);e&&(p.delete(t.dir),e.close())}function q(t){if(!t.wireId||t.wireId.length>256)throw new Error("invalid wire_id");if(!t.peerCid||t.peerCid.length>256)throw new Error("invalid peer cid");if(!t.peerName||t.peerName.length>512)throw new Error("invalid peer name");if(!Number.isSafeInteger(t.occurredAtMs)||t.occurredAtMs<0)throw new Error("invalid timestamp");if(t.replyToWireId!==void 0&&(!t.replyToWireId||t.replyToWireId.length>256))throw new Error("invalid reply wire_id");if(t.replyToSentence!==void 0&&(!Number.isSafeInteger(t.replyToSentence)||t.replyToSentence<1))throw new Error("invalid reply sentence")}function k(t){if(q(t),t.kind==="message"){if(Buffer.byteLength(t.body,"utf8")>b)throw new Error("message body exceeds host limit");return}if(!t.filename||t.filename.length>512||/[\0]/.test(t.filename))throw new Error("invalid filename");if(t.mime.length>512||/[\r\n\0]/.test(t.mime))throw new Error("invalid MIME type");if(t.bytes.byteLength>D)throw new Error("file exceeds host limit")}function h(t){return t.reply_to_wire_id?t.reply_to_sentence===null?{wire_id:t.reply_to_wire_id}:{wire_id:t.reply_to_wire_id,sentence:t.reply_to_sentence}:null}function I(t){return new Date(t).toISOString()}function S(t){let e={id:t.peer_cid,name:t.peer_name_snapshot};return{seq:t.seq,msg_id:t.seq,wire_id:t.wire_id,from:e,peer:e,direction:t.direction,text:t.body,body:t.body,occurred_at_ms:t.occurred_at_ms,date:I(t.occurred_at_ms),encryption:t.encryption,transport:t.encryption==="e2e"?"double_ratchet":"legacy_box",inbox_state:t.inbox_state,status:t.inbox_state,delivery_state:t.delivery_state,human_read_at_ms:t.human_read_at_ms,reply_to:h(t)}}function g(t,e){let r={id:e.peer_cid,name:e.peer_name_snapshot},s=e.mime||"application/octet-stream";return{seq:e.seq,file_id:e.seq,wire_id:e.wire_id,from:r,peer:r,direction:e.direction,filename:e.filename,mime:s,size:e.byte_length,byte_length:e.byte_length,sha256:e.sha256,occurred_at_ms:e.occurred_at_ms,date:I(e.occurred_at_ms),encryption:e.encryption,inbox_state:e.inbox_state,status:e.inbox_state,delivery_state:e.delivery_state,human_read_at_ms:e.human_read_at_ms,reply_to:h(e),blob_path:l(t.dir,e.blob_relpath),kind:s.startsWith("audio/")?"voice_message":"file"}}function X(t,e){let r=O("sha256").update(e).digest("hex"),s=l("blobs","sha256",r.slice(0,2),r),i=l(t.dir,s);if(o.mkdirSync(y(i),{recursive:!0,mode:448}),o.chmodSync(y(i),448),!o.existsSync(i)){let n=l(y(i),`.${r}.${process.pid}.${H()}.tmp`);try{o.writeFileSync(n,e,{flag:"wx",mode:384}),o.chmodSync(n,384);try{o.renameSync(n,i)}catch(a){if(!o.existsSync(i))throw a;o.rmSync(n,{force:!0})}}catch(a){try{o.rmSync(n,{force:!0})}catch{}throw a}}return o.chmodSync(i,384),{sha256:r,relpath:s}}function j(t,e){k(e);let r=d(t);if(e.direction==="out"&&e.inboxState!==void 0)throw new Error("outbound event cannot set inbox state");let s=e.direction==="in"?e.inboxState??"unread":"read",i=e.direction==="out"?"sent":null;if(e.kind==="message")return r.transaction(()=>r.prepare(`
|
|
83
83
|
INSERT INTO wire_items(wire_id, item_kind) VALUES (?, 'message')
|
|
84
84
|
ON CONFLICT(wire_id) DO NOTHING
|
|
85
85
|
`).run(e.wireId).changes!==1?!1:(r.prepare(`
|
|
@@ -88,7 +88,7 @@ import{createHash as O,randomUUID as H}from"node:crypto";import*as o from"node:f
|
|
|
88
88
|
reply_to_wire_id, reply_to_sentence, encryption, inbox_state,
|
|
89
89
|
delivery_state, human_read_at_ms, inserted_at_ms
|
|
90
90
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
91
|
-
`).run(e.wireId,e.peerCid,e.peerName,e.direction,e.body,e.occurredAtMs,e.replyToWireId??null,e.replyToSentence??null,e.encryption,
|
|
91
|
+
`).run(e.wireId,e.peerCid,e.peerName,e.direction,e.body,e.occurredAtMs,e.replyToWireId??null,e.replyToSentence??null,e.encryption,s,i,e.direction==="out"?e.occurredAtMs:null,Date.now()),!0))();if(r.prepare("SELECT 1 FROM wire_items WHERE wire_id = ?").get(e.wireId))return!1;let a=X(t,e.bytes);return r.transaction(()=>r.prepare(`
|
|
92
92
|
INSERT INTO wire_items(wire_id, item_kind) VALUES (?, 'file')
|
|
93
93
|
ON CONFLICT(wire_id) DO NOTHING
|
|
94
94
|
`).run(e.wireId).changes!==1?!1:(r.prepare(`
|
|
@@ -98,7 +98,7 @@ import{createHash as O,randomUUID as H}from"node:crypto";import*as o from"node:f
|
|
|
98
98
|
reply_to_sentence, encryption, inbox_state, delivery_state,
|
|
99
99
|
human_read_at_ms, inserted_at_ms
|
|
100
100
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
101
|
-
`).run(e.wireId,e.peerCid,e.peerName,e.direction,e.filename,e.mime||"application/octet-stream",e.bytes.byteLength,a.sha256,a.relpath,e.occurredAtMs,e.replyToWireId??null,e.replyToSentence??null,e.encryption,
|
|
101
|
+
`).run(e.wireId,e.peerCid,e.peerName,e.direction,e.filename,e.mime||"application/octet-stream",e.bytes.byteLength,a.sha256,a.relpath,e.occurredAtMs,e.replyToWireId??null,e.replyToSentence??null,e.encryption,s,i,e.direction==="out"?e.occurredAtMs:null,Date.now()),!0))()}function z(t,e){if(!e.itemId||!e.sourceCid||!e.sourceName||!e.peerCid||!e.peerName)throw new Error("invalid monitoring event metadata");if(!Number.isSafeInteger(e.occurredAtMs)||e.occurredAtMs<0)throw new Error("invalid monitoring timestamp");if(Buffer.byteLength(e.body,"utf8")>b)throw new Error("monitoring body exceeds host limit");return d(t).prepare(`
|
|
102
102
|
INSERT INTO monitoring_items (
|
|
103
103
|
item_id, source_cid, source_name_snapshot, direction, peer_cid,
|
|
104
104
|
peer_name_snapshot, body, occurred_at_ms, queue_state, inserted_at_ms
|
|
@@ -110,19 +110,19 @@ import{createHash as O,randomUUID as H}from"node:crypto";import*as o from"node:f
|
|
|
110
110
|
occurred_at_ms, queue_state, inserted_at_ms
|
|
111
111
|
) VALUES (?, ?, ?, ?, ?, 'pending', ?)
|
|
112
112
|
ON CONFLICT(item_id) DO NOTHING
|
|
113
|
-
`).run(e.itemId,e.senderCid,e.senderName,e.payload,e.occurredAtMs,Date.now()).changes===1}function Z(t,e){let r=d(t);return r.transaction(()=>{let
|
|
113
|
+
`).run(e.itemId,e.senderCid,e.senderName,e.payload,e.occurredAtMs,Date.now()).changes===1}function Z(t,e){let r=d(t);return r.transaction(()=>{let s=r.prepare(`
|
|
114
114
|
UPDATE messages SET inbox_state = 'unread'
|
|
115
115
|
WHERE direction = 'in' AND peer_cid = ? AND inbox_state = 'pending_introduction'
|
|
116
116
|
`).run(e).changes,i=r.prepare(`
|
|
117
117
|
UPDATE files SET inbox_state = 'unread'
|
|
118
118
|
WHERE direction = 'in' AND peer_cid = ? AND inbox_state = 'pending_introduction'
|
|
119
|
-
`).run(e).changes;return
|
|
119
|
+
`).run(e).changes;return s+i})()}function v(t,e){let r=d(t);return r.transaction(()=>{let s=r.prepare(`
|
|
120
120
|
DELETE FROM messages
|
|
121
121
|
WHERE direction = 'in' AND peer_cid = ? AND inbox_state = 'pending_introduction'
|
|
122
122
|
`).run(e).changes,i=r.prepare(`
|
|
123
123
|
DELETE FROM files
|
|
124
124
|
WHERE direction = 'in' AND peer_cid = ? AND inbox_state = 'pending_introduction'
|
|
125
|
-
`).run(e).changes;return
|
|
125
|
+
`).run(e).changes;return s+i})()}function ee(t){let e=d(t);return{pending_introductions:Number(e.prepare(`
|
|
126
126
|
SELECT
|
|
127
127
|
(SELECT COUNT(*) FROM messages WHERE inbox_state = 'pending_introduction') +
|
|
128
128
|
(SELECT COUNT(*) FROM files WHERE inbox_state = 'pending_introduction')
|
|
@@ -130,36 +130,42 @@ import{createHash as O,randomUUID as H}from"node:crypto";import*as o from"node:f
|
|
|
130
130
|
SELECT COUNT(*) FROM monitoring_items WHERE queue_state = 'pending'
|
|
131
131
|
`).pluck().get()),control_requests:Number(e.prepare(`
|
|
132
132
|
SELECT COUNT(*) FROM control_requests WHERE queue_state = 'pending'
|
|
133
|
-
`).pluck().get())}}function T(t){let e=t??C;if(!Number.isSafeInteger(e)||e<1||e>
|
|
133
|
+
`).pluck().get())}}function T(t){let e=t??C;if(!Number.isSafeInteger(e)||e<1||e>m)throw new Error(`limit must be an integer from 1 to ${m}`);return e}function te(t){return d(t).prepare(`
|
|
134
134
|
SELECT seq, wire_id, peer_cid, peer_name_snapshot, occurred_at_ms,
|
|
135
135
|
reply_to_wire_id, reply_to_sentence, encryption
|
|
136
136
|
FROM messages
|
|
137
137
|
WHERE direction = 'in' AND inbox_state = 'unread'
|
|
138
138
|
ORDER BY seq ASC
|
|
139
|
-
`).all().map(r=>({seq:r.seq,msg_id:r.seq,wire_id:r.wire_id,from:{id:r.peer_cid,name:r.peer_name_snapshot},occurred_at_ms:r.occurred_at_ms,date:
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
139
|
+
`).all().map(r=>({seq:r.seq,msg_id:r.seq,wire_id:r.wire_id,from:{id:r.peer_cid,name:r.peer_name_snapshot},occurred_at_ms:r.occurred_at_ms,date:I(r.occurred_at_ms),encryption:r.encryption,inbox_state:"unread",status:"unread",reply_to:h(r)}))}function re(t,e={}){let r=d(t),s=T(e.limit),i=e.wire_ids;return r.transaction(()=>{let n;if(i!==void 0){if(i.length<1||i.length>m)throw new Error(`wire_ids must contain 1-${m} items`);if(new Set(i).size!==i.length)throw new Error("wire_ids must not contain duplicates");let c=r.prepare(`
|
|
140
|
+
SELECT * FROM messages WHERE wire_id = ? AND direction = 'in' AND inbox_state = 'unread'
|
|
141
|
+
`);if(n=i.map(u=>c.get(u)).filter(u=>!!u),n.length!==i.length)throw new Error("selected message wire_id is unknown, stale, or no longer unread")}else n=r.prepare(`
|
|
142
|
+
SELECT * FROM messages
|
|
143
|
+
WHERE direction = 'in' AND inbox_state = 'unread'
|
|
144
|
+
ORDER BY seq ASC LIMIT ?
|
|
145
|
+
`).all(s);let a=r.prepare(`
|
|
144
146
|
UPDATE messages SET inbox_state = 'read'
|
|
145
147
|
WHERE seq = ? AND direction = 'in' AND inbox_state = 'unread'
|
|
146
|
-
`);for(let c of
|
|
148
|
+
`);for(let c of n){if(a.run(c.seq).changes!==1)throw new Error(`message row ${c.seq} changed during read batch`);c.inbox_state="read"}let _=Number(r.prepare(`
|
|
147
149
|
SELECT COUNT(*) FROM messages WHERE direction = 'in' AND inbox_state = 'unread'
|
|
148
|
-
`).pluck().get());return{messages:
|
|
150
|
+
`).pluck().get());return{messages:n.map(S),remaining:_}})()}function ie(t){return d(t).prepare(`
|
|
149
151
|
SELECT * FROM files WHERE direction = 'in' AND inbox_state = 'unread' ORDER BY seq ASC
|
|
150
|
-
`).all().map(r=>
|
|
152
|
+
`).all().map(r=>g(t,r))}function ne(t,e={}){let r=d(t),s=T(e.limit),i=e.wire_ids;return r.transaction(()=>{let n;if(i!==void 0){if(i.length<1||i.length>m)throw new Error(`wire_ids must contain 1-${m} items`);if(new Set(i).size!==i.length)throw new Error("wire_ids must not contain duplicates");let c=r.prepare(`
|
|
151
153
|
SELECT * FROM files WHERE wire_id = ? AND direction = 'in' AND inbox_state = 'unread'
|
|
152
|
-
`);if(
|
|
154
|
+
`);if(n=i.map(u=>c.get(u)).filter(u=>!!u),n.length!==i.length)throw new Error("selected file wire_id is unknown, stale, or no longer unread")}else n=r.prepare(`
|
|
153
155
|
SELECT * FROM files WHERE direction = 'in' AND inbox_state = 'unread'
|
|
154
156
|
ORDER BY seq ASC LIMIT ?
|
|
155
|
-
`).all(
|
|
157
|
+
`).all(s);let a=r.prepare(`
|
|
156
158
|
UPDATE files SET inbox_state = 'read'
|
|
157
159
|
WHERE seq = ? AND direction = 'in' AND inbox_state = 'unread'
|
|
158
|
-
`);for(let
|
|
160
|
+
`);for(let c of n){if(a.run(c.seq).changes!==1)throw new Error(`file row ${c.seq} changed during read batch`);c.inbox_state="read"}let _=Number(r.prepare(`
|
|
159
161
|
SELECT COUNT(*) FROM files WHERE direction = 'in' AND inbox_state = 'unread'
|
|
160
|
-
`).pluck().get());return{files:
|
|
161
|
-
|
|
162
|
+
`).pluck().get());return{files:n.map(c=>g(t,c)),remaining:_}})()}function L(t){let e=[],r=[];return t.peer_cid!==void 0&&(e.push("peer_cid = ?"),r.push(t.peer_cid)),t.direction!==void 0&&(e.push("direction = ?"),r.push(t.direction)),t.before_seq!==void 0&&(e.push("seq < ?"),r.push(t.before_seq)),{sql:e.length?`WHERE ${e.join(" AND ")}`:"",args:r}}function se(t,e={}){let r=d(t),s=T(e.limit),i=L(e),n=r.prepare(`SELECT * FROM messages ${i.sql} ORDER BY seq DESC LIMIT ?`).all(...i.args,s+1),a=n.length>s;return a&&n.pop(),{items:n.map(S),next_cursor:a?n.at(-1).seq:null}}function oe(t,e){let r=d(t).prepare("SELECT * FROM messages WHERE wire_id = ?").get(e);return r?S(r):null}function ae(t,e){let r=d(t).prepare(`
|
|
163
|
+
SELECT COUNT(*) AS total,
|
|
164
|
+
SUM(CASE WHEN direction = 'in' AND inbox_state = 'unread' THEN 1 ELSE 0 END) AS unread
|
|
165
|
+
FROM messages WHERE peer_cid = ?
|
|
166
|
+
`).get(e.peer_cid);return{total:Number(r.total),unread:Number(r.unread??0)}}function de(t,e={}){let r=d(t),s=T(e.limit),i=L(e),n=r.prepare(`SELECT * FROM files ${i.sql} ORDER BY seq DESC LIMIT ?`).all(...i.args,s+1),a=n.length>s;return a&&n.pop(),{items:n.map(_=>g(t,_)),next_cursor:a?n.at(-1).seq:null}}function P(t,e){let r=d(t).prepare("SELECT * FROM files WHERE wire_id = ?").get(e);return r?g(t,r):null}function ce(t,e){let r=P(t,e);if(!r||!o.existsSync(r.blob_path))return null;let s=R(t.dir),i=R(r.blob_path);return i.startsWith(`${s}${x}`)?i:null}function _e(t,e,r,s){let i=d(t),n=r==="read"?2:1;i.transaction(()=>{for(let _ of s)for(let c of["messages","files"])i.prepare(`
|
|
167
|
+
UPDATE ${c}
|
|
162
168
|
SET delivery_state = ?, human_read_at_ms = CASE WHEN ? = 'read' THEN COALESCE(human_read_at_ms, ?) ELSE human_read_at_ms END
|
|
163
169
|
WHERE wire_id = ? AND peer_cid = ? AND direction = 'out'
|
|
164
170
|
AND (CASE delivery_state WHEN 'read' THEN 2 WHEN 'delivered' THEN 1 WHEN 'sent' THEN 0 ELSE -1 END) < ?
|
|
165
|
-
`).run(r,r,Date.now(),
|
|
171
|
+
`).run(r,r,Date.now(),_,e,n)})()}function ue(t){let e=d(t);return{messages:Number(e.prepare("SELECT COUNT(*) FROM messages WHERE direction='in' AND inbox_state='unread'").pluck().get()),files:Number(e.prepare("SELECT COUNT(*) FROM files WHERE direction='in' AND inbox_state='unread'").pluck().get())}}export{U as a,Y as b,$ as c,K as d,Q as e,d as f,V as g,j as h,z as i,J as j,Z as k,v as l,ee as m,te as n,re as o,ie as p,ne as q,se as r,oe as s,ae as t,de as u,P as v,ce as w,_e as x,ue as y};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{e as a}from"./chunk-ZHH3PWEW.js";import{d as s,f as i,g as u,h as p}from"./chunk-WS6UFNKF.js";import{timingSafeEqual as d}from"node:crypto";var b="3.0.
|
|
2
|
+
import{e as a}from"./chunk-ZHH3PWEW.js";import{d as s,f as i,g as u,h as p}from"./chunk-WS6UFNKF.js";import{timingSafeEqual as d}from"node:crypto";var b="3.0.3",r=s(),_=r.stateDir,k=r.brokerUrl,g=process.env.OURS_TRANSPORT??"http",E=r.port,A=r.gcIntervalMs,c=r.apiVisibility,R=Number(process.env.OURS_TEST_STARTUP_HEARTBEAT_MS||"")||void 0,N=g==="http"?a(_,{heartbeatMs:R}):null,v=(...e)=>process.stderr.write(`ours: ${e.join(" ")}
|
|
3
3
|
`);function S(){if(c==="open")return null;if(c==="shared"){let e=u(r);if(!e)throw new Error(`apiVisibility=shared requires an operator-supplied token so it can be distributed to cross-user agents \u2014 set OURS_API_TOKEN or "apiToken" in config (${i(r)} is not used for shared mode). Use apiVisibility=owner for a same-user-only auto-token, or =open to disable auth.`);return e}return p(r,{generate:!0}).token}var f=S();function T(e){let t=e.headers["x-ours-api-token"];if(typeof t=="string"&&t)return t;let o=e.headers.authorization;if(typeof o=="string"){let n=/^Bearer\s+(.+)$/i.exec(o.trim());if(n)return n[1]}}function h(e){if(f===null)return!0;let t=T(e);if(!t)return!1;let o=Buffer.from(t),n=Buffer.from(f);return o.length===n.length&&d(o,n)}function P(e,t){return h(e)?!0:(t.writeHead(401,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"unauthorized"})),!1)}var O=/^[A-Za-z0-9 _.@-]{1,64}$/,l="contact-book";function y(e){return O.test(e)?e==="."||e===".."||e.includes("/")||e.includes("\\")?"invalid name":e===l?`"${l}" is reserved for the local contact book`:e==="root.json"||e==="bindings.json"?`"${e}" is reserved for daemon bookkeeping`:null:"name must be 1-64 chars of letters, digits, space, _ . @ or -"}export{b as a,r as b,_ as c,k as d,E as e,A as f,c as g,N as h,v as i,f as j,T as k,h as l,P as m,O as n,l as o,y as p};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{a as P,b,c as w,d as H,e as M,f as T,g as N,h as L,i as B,j}from"./chunk-LRMN6BSO.js";import{a as E,b as J,c as _}from"./chunk-PBLR7J42.js";import{a as $,b as U,c as V,d as X,e as q}from"./chunk-5KVWI5BW.js";import{a as z,b as D,c as G,d as K}from"./chunk-LPXPNZTS.js";import{a as Q,b as W,c as Y,d as Z}from"./chunk-JTQMUWPE.js";import{b as u,c as v,d as h,e as S,f as k,g as x,h as O,i as R,j as C,k as F}from"./chunk-SBKG5P7O.js";import{a as f}from"./chunk-65KGEJBX.js";import{c as d}from"./chunk-PMDY4YIZ.js";import{n as I}from"./chunk-ETBJ4VOK.js";import{i as m,m as g}from"./chunk-ZLCQNN5W.js";var ie="/api/v1/",e=i=>(t,n)=>i(t,n),s=i=>t=>i(t),ne=i=>(t,n)=>i(n),ee={createIdentity:e(u),createTemporaryIdentity:e(v),closeTemporaryIdentityOp:e(h),createRootIdentity:e(S),defineLocalIdentityFile:ne(k),chooseIdentity:e(x),listIdentities:s(O),currentIdentity:s(R),removeIdentity:e(C),releaseLease:s(F),generateInvite:e(P),listInvites:s(b),revokeInvite:e(w),addContact:e(H),listContacts:s(M),listLocalContactBook:s(T),setLocalBookPolicy:e(N),removeContact:e(L),renameContact:e(B),respondToIntroduction:e(j),setBio:e(Q),advertiseMigrate:s(W),readvertiseOnUpgrade:s(Z),setPersona:e(Y),sendMessage:e(z),sendFile:e(D),listIncomingMessages:s(G),getMessages:e(K),listHistory:e($),getHistoryItem:e(U),getHistorySummary:e(V),listFiles:e(X),getFileInfo:e(q),listIncomingFiles:s(E),getFiles:e(J),saveFileFallbackNotice:e(_)},l=new Map,te=(i,t)=>{let n=i.headers[t];return typeof n=="string"&&n!==""?n:void 0};function oe(i){let t=te(i,"x-ours-lease-token"),n=te(i,"x-ours-client-pid"),y=n?parseInt(n,10):NaN,a=Number.isInteger(y)?y:void 0,o=t?`api:${I(t)}`:"api:anonymous";return d.set(o,{token:t,pid:a}),l.set(o,(l.get(o)??0)+1),{ctx:{sessionId:()=>o,leaseToken:()=>d.get(o)?.token,clientPid:()=>d.get(o)?.pid},release:()=>{let r=(l.get(o)??1)-1;if(r>0){l.set(o,r);return}l.delete(o),d.delete(o)}}}var p=(i,t,n)=>{i.writableEnded||(i.writeHead(t,{"Content-Type":"application/json"}),i.end(JSON.stringify(n??null)))};async function ge(i,t,n,y){let a=n.slice(ie.length);if(!g(i,t))return;if(i.method!=="POST"){p(t,405,{error:"method not allowed: the typed API is POST-only"});return}let o=Object.prototype.hasOwnProperty.call(ee,a)?ee[a]:void 0;if(!o){p(t,404,{error:`unknown operation "${a}"`});return}let r;try{r=await y(i)}catch{p(t,400,{error:"the request body must be JSON"});return}if(r===null||typeof r!="object"||Array.isArray(r)){p(t,400,{error:"the request body must be a JSON object"});return}let A=oe(i);try{p(t,200,await o(A.ctx,r))}catch(c){if(c instanceof f){p(t,400,{error:{code:c.code,message:c.message}});return}m("api handler error:",a,String(c)),p(t,500,{error:`internal error in ${a}: ${String(c)}`})}finally{A.release()}}export{ie as a,ee as b,oe as c,ge as d};
|
package/dist/client/http.d.ts
CHANGED
|
@@ -142,6 +142,7 @@ export declare class OursClient {
|
|
|
142
142
|
getMessages(a?: Arg<typeof messagingApi.getMessages>): Promise<Res<typeof messagingApi.getMessages>>;
|
|
143
143
|
listHistory(a?: Arg<typeof historyApi.listHistory>): Promise<Res<typeof historyApi.listHistory>>;
|
|
144
144
|
getHistoryItem(a: Arg<typeof historyApi.getHistoryItem>): Promise<Res<typeof historyApi.getHistoryItem>>;
|
|
145
|
+
getHistorySummary(a: Arg<typeof historyApi.getHistorySummary>): Promise<Res<typeof historyApi.getHistorySummary>>;
|
|
145
146
|
listFiles(a?: Arg<typeof historyApi.listFiles>): Promise<Res<typeof historyApi.listFiles>>;
|
|
146
147
|
getFileInfo(a: Arg<typeof historyApi.getFileInfo>): Promise<Res<typeof historyApi.getFileInfo>>;
|
|
147
148
|
listIncomingFiles(): Promise<Res<typeof filesApi.listIncomingFiles>>;
|
package/dist/client/http.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{a}from"../chunk-
|
|
2
|
+
import{a}from"../chunk-HZCFYJAG.js";import"../chunk-65KGEJBX.js";import"../chunk-JTBQO6IT.js";export{a as OursClient};
|
package/dist/client/select.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{a,b,c,d,e,f,g,h}from"../chunk-
|
|
2
|
+
import{a,b,c,d,e,f,g,h}from"../chunk-SEZTXIKN.js";import"../chunk-HZCFYJAG.js";import"../chunk-65KGEJBX.js";import"../chunk-JTBQO6IT.js";import"../chunk-WS6UFNKF.js";export{d as DAEMON_TOKEN_FILE,c as DEFAULT_DAEMON_PORT,a as DaemonSelectionError,b as DaemonUnavailableError,g as assertDaemonStateDir,h as attachOursClient,f as describeDaemonConfig,e as resolveDaemonConfig};
|
package/dist/client.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{a as I,b as J,c as L,d as O,e as P,f as Q,g as T,h as V}from"./chunk-
|
|
2
|
+
import{a as I,b as J,c as L,d as O,e as P,f as Q,g as T,h as V}from"./chunk-SEZTXIKN.js";import{a as H}from"./chunk-HZCFYJAG.js";import{A as K,B as S,C as U,D as b,E as h,F as l,G as z,H as A,I as B,J as C,K as D,L as F,M as G,a as e,b as o,c as t,d as i,e as n,f as r,g as c,h as R,i as d,j as f,k as p,l as s,m as v,n as a,o as m,p as x,q as E,r as N,s as g,t as y,u as M,v as j,w as k,x as q,y as u,z as w}from"./chunk-65KGEJBX.js";import"./chunk-JTBQO6IT.js";import"./chunk-WS6UFNKF.js";export{O as DAEMON_TOKEN_FILE,L as DEFAULT_DAEMON_PORT,I as DaemonSelectionError,J as DaemonUnavailableError,H as OursClient,e as OursError,T as assertDaemonStateDir,V as attachOursClient,Q as describeDaemonConfig,t as errBindingReassigned,y as errBoundElsewhere,i as errBoundIdentityGone,D as errDuplicateId,l as errFileTooLarge,U as errFileUnreadable,j as errIdentityClosedWithError,q as errIdentityPartiallyRemoved,B as errInvalidSelection,C as errMalformedId,r as errNameTaken,c as errNoLeaseHeaders,x as errNoLeaseToken,w as errNoPolicyArgs,A as errNoRoot,m as errNoSuchIdentity,o as errNotBound,f as errNotBoundNoName,p as errNotTemporary,a as errPathNotAbsolute,u as errPublicInviteNamed,R as errRandomNameExhausted,d as errRootExists,k as errRootHasRoles,z as errSaveFileFallback,K as errSendFileArgs,S as errSendFileFilenameRequired,b as errSendFileUploadArgs,v as errTempClosedWithError,n as errTempClosingBound,E as errTempClosingChoose,s as errTempOwnedElsewhereClose,M as errTempOwnedElsewhereRemove,N as errTempOwnedLive,g as errTempStale,G as errTool,F as errUnknownOrStaleId,h as errUploadNotFound,P as resolveDaemonConfig};
|
package/dist/cluster/control.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{a,b,c,d}from"../chunk-
|
|
2
|
+
import{a,b,c,d}from"../chunk-M2WREVID.js";import"../chunk-PJ5F7BI6.js";import"../chunk-GJXNZNS6.js";import"../chunk-NODVUYDQ.js";import"../chunk-YRPUM6JG.js";import"../chunk-O3WRMYAS.js";import"../chunk-PMDY4YIZ.js";import"../chunk-ETBJ4VOK.js";import"../chunk-ZLCQNN5W.js";import"../chunk-ZHH3PWEW.js";import"../chunk-Y3VPZJTG.js";import"../chunk-TXAIJEXA.js";import"../chunk-JTBQO6IT.js";import"../chunk-WS6UFNKF.js";export{b as PROTOCOL_VERSION,c as clusterSweep,a as envelopeDispatch,d as startClusterSweep};
|
package/dist/cluster/manifest.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{a,b,c,d}from"../chunk-
|
|
2
|
+
import{a,b,c,d}from"../chunk-PJ5F7BI6.js";import"../chunk-GJXNZNS6.js";import"../chunk-NODVUYDQ.js";import"../chunk-YRPUM6JG.js";import"../chunk-O3WRMYAS.js";import"../chunk-PMDY4YIZ.js";import"../chunk-ETBJ4VOK.js";import"../chunk-ZLCQNN5W.js";import"../chunk-ZHH3PWEW.js";import"../chunk-Y3VPZJTG.js";import"../chunk-TXAIJEXA.js";import"../chunk-JTBQO6IT.js";import"../chunk-WS6UFNKF.js";export{b as buildManifest,d as findAgentOf,c as listAgentsFor,a as manifestCapabilities};
|
package/dist/connector.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{a as oe}from"./chunk-5EWCIQH6.js";import{mkdirSync as ie,writeFileSync as Me,readFileSync as Ae,readdirSync as Ie,statSync as z,unlinkSync as De,chmodSync as ae,createWriteStream as xe}from"node:fs";import{join as $,dirname as Ne,resolve as $e}from"node:path";import{homedir as Ue}from"node:os";import{Readable as Le}from"node:stream";import{pipeline as Ce}from"node:stream/promises";var Pe="3.0.
|
|
2
|
+
import{a as oe}from"./chunk-5EWCIQH6.js";import{mkdirSync as ie,writeFileSync as Me,readFileSync as Ae,readdirSync as Ie,statSync as z,unlinkSync as De,chmodSync as ae,createWriteStream as xe}from"node:fs";import{join as $,dirname as Ne,resolve as $e}from"node:path";import{homedir as Ue}from"node:os";import{Readable as Le}from"node:stream";import{pipeline as Ce}from"node:stream/promises";var Pe="3.0.3",Je=new Set(["choose_identity","create_identity","create_root_identity"]),Fe="save_file",He="get_files",ce=a=>new Promise(g=>setTimeout(g,a)),q=a=>typeof a?.method=="string"&&a.id!==void 0&&a.id!==null,je=a=>a&&typeof a=="object"&&!("method"in a)&&a.id!==void 0&&a.id!==null,de=a=>{let g=a.result;return!!a.error||!!(g&&g.isError)},ue=Number(process.env.OURS_RESTORE_TTL_MS)>0?Number(process.env.OURS_RESTORE_TTL_MS):7*24*60*60*1e3,le=["1","true","yes","on"].includes((process.env.OURS_NO_AUTORESTORE??"").trim().toLowerCase());async function Ye(a){let g=new URL(a.url),S=!1,o=(...e)=>{if(!S)try{process.stderr.write(`[ours-proxy] ${e.join(" ")}
|
|
3
3
|
`)}catch{S=!0,y(0)}},G=()=>{S=!0,y(0)};process.stderr.on("error",G),process.stdout.on("error",G);let B=e=>Number.isInteger(e)&&e>1,W=Number(process.env.OURS_CLIENT_PID),R=B(W)?W:B(process.ppid)?process.ppid:process.pid,Y=(process.env.CLAUDE_CODE_SESSION_ID??"").trim()||`client:${R}`,b=null,I=null,L,f=null,D=new Map,C=new Set,T=null,v=le?null:(process.env.CLAUDE_CODE_SESSION_ID??"").trim()||null,fe=a.stateDir??process.env.OURS_STATE_DIR??$(Ue(),".ours"),k=$(fe,"session-restore"),Q=v&&/^[A-Za-z0-9._-]{1,200}$/.test(v)?v:null,h=Q?$(k,`${Q}.json`):null,X=!1,P=null;function pe(e){if(h)try{ie(k,{recursive:!0,mode:448}),Me(h,JSON.stringify({claudeSessionId:v,identity:e,boundAt:new Date().toISOString()}),{mode:384}),ae(k,448),ae(h,384)}catch(n){o("restore persist failed (non-fatal):",String(n))}}function me(){if(!h)return null;try{if(Date.now()-z(h).mtimeMs>ue)return null;let e=JSON.parse(Ae(h,"utf8"));return(typeof e.identity=="string"?e.identity.trim():"")||null}catch{return null}}function ge(){try{let e=Date.now();for(let n of Ie(k)){if(!n.endsWith(".json"))continue;let t=$(k,n);try{e-z(t).mtimeMs>ue&&(De(t),o("session-restore: pruned expired record",n))}catch{}}}catch{}}let E=(()=>{let e=(process.env.OURS_REQUEST_TIMEOUT_MS??"").trim();if(e==="")return 12e4;let n=Number(e);return Number.isFinite(n)&&n>=0?n:12e4})(),p=new Map,x=new Map;function J(e,n,t){let i=p.get(e);if(!i)return;p.delete(e),i.progressToken!==void 0&&x.delete(i.progressToken);let s=Date.now()-i.sentAt;o(`FAILING BACK request id=${String(e)} method=${i.method} waited_ms=${s} reason=${t}`),m.send({jsonrpc:"2.0",id:e,error:{code:n,message:`ours proxy: no response from the ours daemon for "${i.method}" after ${s}ms (${t}). The request was NOT retried \u2014 retry it yourself if it is safe to repeat.`,data:{reason:t,method:i.method,waitedMs:s}}}).catch(r=>o("fail-back send failed:",String(r)))}E>0&&setInterval(()=>{let n=Date.now();for(let[t,i]of[...p])i.deadline<=n&&J(t,-32001,"watchdog timeout")},1e3).unref?.();let ye=6e4,Z=3,F=0,w=0;function he(e,n){m.send({jsonrpc:"2.0",method:"notifications/message",params:{level:e,logger:"ours-proxy",data:n}}).catch(t=>o("downstream notify failed:",String(t)))}let l=null,we=()=>l,N=!1,O=!1,_=!1,M=[],_e="__ours_proxy_init__",H=0,A=new Set,j=new Set,m=a.transports.createStdioServer();m.onmessage=e=>{let n=[],t=!1;for(let i of U(e)){let s=i;if(s.method==="notifications/initialized"&&(t=!0),q(s)){if(s.method==="initialize"&&(b=s,I)){o("absorbed re-initialize locally \u2014 upstream session kept stable"),m.send({jsonrpc:"2.0",id:s.id,result:I}).catch(r=>o("local initialize reply failed:",String(r)));continue}if(s.method==="tools/call"){let r=s.params;if(r&&Je.has(r.name??"")&&typeof r.arguments?.name=="string"&&D.set(s.id,r.arguments.name),r?.name===He&&C.add(s.id),r?.name===Fe){let c=s.params?.arguments??{};be(s.id,c);continue}}if(E>0){let r=s.id,c=s.params?._meta,d=Date.now();p.set(r,{method:typeof s.method=="string"?s.method:"unknown",sentAt:d,deadline:d+E,transport:null,progressToken:c?.progressToken}),c?.progressToken!==void 0&&x.set(c.progressToken,r)}}n.push(s)}if(n.length){let i=Array.isArray(e)?n:n[0];ee(i)}t&&Se()},m.onclose=()=>void y(0),m.onerror=e=>o("downstream error:",String(e));let K=e=>{o(`stdin ${e} \u2014 the client is gone; shutting down`),y(0)};process.stdin.once("end",()=>K("reached EOF")),process.stdin.once("close",()=>K("closed"));function Se(){if(X||!f)return;X=!0;let e=`__ours_proxy_restore_${++H}__`;A.add(e),P=e,o("session-restore: self-recovering bound identity",`"${f}"`),ee({jsonrpc:"2.0",id:e,method:"tools/call",params:{name:"choose_identity",arguments:{name:f}}})}function Re(e,n){if(!(E<=0))for(let t of U(e)){let i=t.id;if(i===void 0)continue;let s=p.get(i);s&&(s.transport=n)}}async function be(e,n){let t=String(n.wire_id??"").trim(),i=String(n.dest_path??"").trim(),s=(r,c=!1)=>m.send({jsonrpc:"2.0",id:e,result:{content:[{type:"text",text:r}],isError:c}}).catch(d=>o("save_file reply failed:",String(d)));if(!t||!i){await s("save_file: both `wire_id` and `dest_path` are required.",!0);return}if(!/^[A-Za-z0-9]+$/.test(t)){await s("save_file: invalid wire_id.",!0);return}try{let r=new URL(g.href);r.pathname=`/files/${encodeURIComponent(t)}`,r.search="";let c={"x-ours-lease-token":Y};a.apiToken&&(c["x-ours-api-token"]=a.apiToken);let d=await fetch(r,{headers:c});if(d.status===401||d.status===403){await s("save_file: ours daemon authentication failed; the monitor may be disarmed.",!0);return}if(d.status===404){await s(`save_file: no file with wire_id ${t} is available to the bound identity. Run get_files first; it may already be saved, or it belongs to another identity.`,!0);return}if(!d.ok||!d.body){await s(`save_file: ours daemon returned HTTP ${d.status}. Your ours daemon may be too old to support save_file \u2014 update it, or use get_files and copy the returned path yourself.`,!0);return}let u=$e(i);ie(Ne(u),{recursive:!0}),await Ce(Le.fromWeb(d.body),xe(u));let Oe=z(u).size;await s(`Saved file (wire_id ${t}) to ${u} (${Oe} bytes). The bytes were streamed daemon\u2192proxy\u2192disk and never entered this result.`)}catch(r){await s(`save_file failed: ${String(r)}`,!0)}}function ee(e){if(N&&l){let n=l;Re(e,n),l.send(e).catch(t=>{o("upstream send failed:",String(t));let i=U(e),s=i.filter(r=>!q(r));s.length&&M.push(Array.isArray(e)?s:s[0]);for(let r of i){let c=r;q(c)&&p.has(c.id)&&J(c.id,-32e3,"upstream send failed")}V(n,"send failed")})}else M.push(e)}function V(e,n){if(O||_||l!==null&&e!==l)return;o(`upstream dropped (${n}) \u2014 reconnecting`),N=!1;let t=l;l=null;try{t?.close?.()}catch{}if(t)for(let[i,s]of[...p])s.transport===t&&J(i,-32e3,`upstream dropped (${n})`);ke()}function Te(e){e.onmessage=n=>{let t=[];for(let i of U(n)){let s=i;if(s.method==="notifications/progress"){let r=s.params?.progressToken;if(r!==void 0){let c=x.get(r),d=c!==void 0?p.get(c):void 0;d&&(d.deadline=Date.now()+E)}}if(je(s)){let r=s.id,c=p.get(r);c&&(p.delete(r),c.progressToken!==void 0&&x.delete(c.progressToken));let d=s.result?.protocolVersion;if(d&&(j.has(r)||ne(r))){L=d;try{l?.setProtocolVersion?.(d)}catch{}if(I==null&&ne(r)&&!A.has(r)){let u=s.result??null;u&&T&&(u.instructions=`${u.instructions?u.instructions+`
|
|
4
4
|
|
|
5
5
|
`:""}${T}`),I=u}j.delete(r)}if(A.has(r)){A.delete(r),r===P&&(P=null,de(s)&&(f=null,o("session-restore: re-bind refused (identity live elsewhere) \u2014 staying unbound")));continue}if(C.has(r)&&(C.delete(r),a.annotateResult?.(s)&&o("get_files: daemon copy unreadable by this OS user \u2014 asked the agent for a destination")),D.has(r)){let u=D.get(r);D.delete(r),de(s)||(f=u,o("bound identity tracked:",u),pe(u))}}t.push(s)}if(t.length){let i=Array.isArray(n)?t:t[0];m.send(i).catch(s=>o("downstream send failed:",String(s)))}},e.onerror=n=>{let t=String(n);if(o("upstream error:",t),!/Maximum reconnection attempts \(\d+\) exceeded/.test(t))return;let i=Date.now();if(i-F<ye){o(`notification stream exhausted again within cooldown \u2014 not escalating (${Math.round((i-F)/1e3)}s since last)`);return}if(F=i,w++,w>Z){o(`NOTIFICATION STREAM DEAD \u2014 ${w-1} reconnect escalations exhausted; server\u2192client notifications are NOT arriving`),he("error",`ours proxy: the server\u2192client notification stream could not be re-established after ${w-1} attempts. Tool calls still work, but you will NOT receive new-mail or other server notifications until this session reconnects. Treat any "waiting for a message" as unreliable.`);return}o(`notification stream exhausted its retries \u2014 escalating to a full reconnect (${w}/${Z})`),V(e,"notification stream exhausted")},e.onclose=()=>V(e,"closed")}let ne=e=>b!=null&&b.id===e;async function te(){a.ensureDaemon&&await a.ensureDaemon().catch(n=>o("ensureDaemon:",String(n)));let e=a.transports.createHttpClient(g,{reconnectionOptions:{initialReconnectionDelay:1e3,maxReconnectionDelay:3e4,reconnectionDelayGrowFactor:1.5,maxRetries:5},requestInit:{headers:{"x-ours-lease-token":Y,"x-ours-client-pid":String(R),...a.apiToken?{"x-ours-api-token":a.apiToken}:{}}}});if(Te(e),await e.start(),L)try{e.setProtocolVersion?.(L)}catch{}l=e}async function se(e,n){n&&e.id!==void 0&&A.add(e.id),await l.send(e)}let ve=()=>{if(R===process.pid)return!0;try{return process.kill(R,0),!0}catch(e){return e.code!=="ESRCH"}};async function ke(){if(_||O)return;_=!0;let e=500;for(;;){if(O){_=!1;return}if(!ve()){o(`client pid ${R} is gone \u2014 abandoning reconnect instead of churning the daemon's sessions`),_=!1,y(0);return}try{if(await te(),b){let t=`${_e}${H}`;j.add(t),await se({...b,id:t},!0),await l.send({jsonrpc:"2.0",method:"notifications/initialized"})}if(f){let t=`__ours_proxy_rebind_${++H}__`;await se({jsonrpc:"2.0",id:t,method:"tools/call",params:{name:"choose_identity",arguments:{name:f}}},!0)}N=!0;let n=M.splice(0);for(let t of n)await l.send(t).catch(i=>o("flush failed:",String(i)));o("upstream reconnected",f?`(re-bound "${f}")`:""),w=0,_=!1;return}catch(n){o("reconnect attempt failed:",String(n)),await ce(e),e=Math.min(Math.floor(e*1.5),1e4)}}}async function y(e){if(!O){O=!0;try{await l?.close()}catch{}try{await m.close()}catch{}process.exit(e)}}process.on("SIGINT",()=>void y(0)),process.on("SIGTERM",()=>void y(0));let re=e=>{let n=e?.code;return n==="EPIPE"||n==="ECONNRESET"||n==="ERR_STREAM_DESTROYED"||n==="ERR_STREAM_WRITE_AFTER_END"};process.on("unhandledRejection",e=>{if(re(e)){S=!0,y(0);return}o("UNHANDLED REJECTION (proxy stays up):",e instanceof Error?e.stack??e.message:String(e))}),process.on("uncaughtException",e=>{if(re(e)){S=!0,y(0);return}o("UNCAUGHT EXCEPTION (proxy stays up):",e?.stack??String(e))});async function Ee(){let e=new URL(g.href);e.pathname="/state-dir";let n;try{n=await(await fetch(e,{signal:AbortSignal.timeout(3e3)})).json()}catch(t){o("compat handshake: could not read daemon /state-dir, proceeding:",String(t));return}T=oe({selfVersion:Pe,daemonVersion:typeof n?.version=="string"?n.version:null}),T&&o(T)}if((async()=>{a.ensureDaemon&&await a.ensureDaemon().catch(t=>o("ensureDaemon:",String(t))),await Ee();let e=500;for(;;)try{await te();break}catch(t){o("initial upstream connect failed, retrying:",String(t)),await ce(e),e=Math.min(Math.floor(e*1.5),1e4)}N=!0;let n=M.splice(0);for(let t=0;t<n.length;t++){let i=we();if(!i){M.unshift(...n.slice(t));break}await i.send(n[t]).catch(s=>o("flush failed:",String(s)))}o(`upstream ready \u2014 stdio \u21C4 ${g.href}`)})(),v){ge();let e=me();e&&(f=e,o("session-restore: found prior binding for this session \u2014 will self-recover",`"${e}"`))}else le&&o("session-restore: disabled via OURS_NO_AUTORESTORE \u2014 pure in-memory binding");await m.start(),o("proxy started (stdio transport up)")}function U(a){return Array.isArray(a)?a:[a]}export{Ye as runProxy};
|
package/dist/gc.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{a,b}from"./chunk-
|
|
2
|
+
import{a,b}from"./chunk-PXIK7DM2.js";import"./chunk-NODVUYDQ.js";import"./chunk-YRPUM6JG.js";import"./chunk-O3WRMYAS.js";import"./chunk-PMDY4YIZ.js";import"./chunk-ETBJ4VOK.js";import"./chunk-ZLCQNN5W.js";import"./chunk-ZHH3PWEW.js";import"./chunk-Y3VPZJTG.js";import"./chunk-TXAIJEXA.js";import"./chunk-JTBQO6IT.js";import"./chunk-WS6UFNKF.js";export{a as startGcTimer,b as stopGcTimer};
|
package/dist/history.d.ts
CHANGED
|
@@ -135,6 +135,10 @@ export interface HistoryPage<T> {
|
|
|
135
135
|
items: T[];
|
|
136
136
|
next_cursor: number | null;
|
|
137
137
|
}
|
|
138
|
+
export interface HistorySummary {
|
|
139
|
+
total: number;
|
|
140
|
+
unread: number;
|
|
141
|
+
}
|
|
138
142
|
export interface HistoryHealth {
|
|
139
143
|
write_failures: number;
|
|
140
144
|
message_write_failures: number;
|
|
@@ -162,6 +166,7 @@ export declare function rejectPendingIntroduction(id: Pick<Identity, 'dir'>, pee
|
|
|
162
166
|
export declare function secondaryQueueCounts(id: Pick<Identity, 'dir'>): SecondaryQueueCounts;
|
|
163
167
|
export declare function listIncomingMessages(id: Pick<Identity, 'dir'>): IncomingMessageMetadata[];
|
|
164
168
|
export declare function takeUnreadMessages(id: Pick<Identity, 'dir'>, input?: {
|
|
169
|
+
wire_ids?: string[];
|
|
165
170
|
limit?: number;
|
|
166
171
|
}): {
|
|
167
172
|
messages: HistoryMessage[];
|
|
@@ -177,6 +182,9 @@ export declare function takeUnreadFiles(id: Pick<Identity, 'dir'>, input?: {
|
|
|
177
182
|
};
|
|
178
183
|
export declare function listMessageHistory(id: Pick<Identity, 'dir'>, query?: HistoryQuery): HistoryPage<HistoryMessage>;
|
|
179
184
|
export declare function getMessageHistoryItem(id: Pick<Identity, 'dir'>, wireId: string): HistoryMessage | null;
|
|
185
|
+
export declare function getMessageHistorySummary(id: Pick<Identity, 'dir'>, input: {
|
|
186
|
+
peer_cid: string;
|
|
187
|
+
}): HistorySummary;
|
|
180
188
|
export declare function listFileHistory(id: Pick<Identity, 'dir'>, query?: HistoryQuery): HistoryPage<HistoryFile>;
|
|
181
189
|
export declare function getFileHistoryItem(id: Pick<Identity, 'dir'>, wireId: string): HistoryFile | null;
|
|
182
190
|
export declare function resolveStoredFile(id: Pick<Identity, 'dir'>, wireId: string): string | null;
|
package/dist/history.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x}from"./chunk-
|
|
2
|
+
import{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y}from"./chunk-TXAIJEXA.js";export{b as blobRoot,g as closeHistory,e as consumeOutboundHistoryFailure,v as getFileHistoryItem,s as getMessageHistoryItem,t as getMessageHistorySummary,c as historyHealth,a as historyPath,h as ingestApplicationEvent,j as ingestControlEvent,i as ingestMonitoringEvent,u as listFileHistory,p as listIncomingFiles,n as listIncomingMessages,r as listMessageHistory,d as noteHistoryFailure,f as openHistory,k as promotePendingIntroduction,l as rejectPendingIntroduction,w as resolveStoredFile,m as secondaryQueueCounts,q as takeUnreadFiles,o as takeUnreadMessages,y as unreadCounts,x as updateDeliveryState};
|
package/dist/http/api-routes.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{a,b,c,d}from"../chunk-
|
|
2
|
+
import{a,b,c,d}from"../chunk-ZPG5V73S.js";import"../chunk-LRMN6BSO.js";import"../chunk-PBLR7J42.js";import"../chunk-5KVWI5BW.js";import"../chunk-LPXPNZTS.js";import"../chunk-67DAPEUW.js";import"../chunk-VXVW4KJU.js";import"../chunk-5OAIOIQ2.js";import"../chunk-P55RJGZU.js";import"../chunk-JTQMUWPE.js";import"../chunk-SBKG5P7O.js";import"../chunk-J2Q2JDUS.js";import"../chunk-JOKNFUW3.js";import"../chunk-DIRW7I4S.js";import"../chunk-65KGEJBX.js";import"../chunk-M2WREVID.js";import"../chunk-PJ5F7BI6.js";import"../chunk-GJXNZNS6.js";import"../chunk-NODVUYDQ.js";import"../chunk-YRPUM6JG.js";import"../chunk-O3WRMYAS.js";import"../chunk-PMDY4YIZ.js";import"../chunk-ETBJ4VOK.js";import"../chunk-ZLCQNN5W.js";import"../chunk-ZHH3PWEW.js";import"../chunk-Y3VPZJTG.js";import"../chunk-TXAIJEXA.js";import"../chunk-JTBQO6IT.js";import"../chunk-WS6UFNKF.js";export{b as API_OPERATIONS,a as API_PREFIX,c as enterApiSession,d as serveApiOperation};
|
package/dist/http/server.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{a as ye}from"../chunk-NBEWKZG4.js";import{d as $}from"../chunk-V64IUVSS.js";import{a as G}from"../chunk-37D5PCFY.js";import{a as ue,b as z}from"../chunk-4DWIX7KY.js";import{a as ge,d as he}from"../chunk-VNZYANLS.js";import{b as me}from"../chunk-GVEBDMN6.js";import"../chunk-EHCBEY52.js";import"../chunk-O2QIPLR6.js";import"../chunk-WFONSX5L.js";import"../chunk-PLCNB2IO.js";import"../chunk-6XZYUNSM.js";import{e as le,f as pe,h as fe}from"../chunk-YBNUNQNM.js";import{b as ce}from"../chunk-VXVW4KJU.js";import"../chunk-54BIUFRS.js";import"../chunk-P55RJGZU.js";import"../chunk-WSEDMA2W.js";import"../chunk-Z5IFINRU.js";import{b as re,c as ae}from"../chunk-HEWVNFUK.js";import"../chunk-JOKNFUW3.js";import"../chunk-DIRW7I4S.js";import"../chunk-65KGEJBX.js";import{b as de}from"../chunk-K3NRXUJW.js";import"../chunk-S24UCZDR.js";import"../chunk-SQ4M4QQA.js";import{o as se}from"../chunk-YZJB6DZI.js";import"../chunk-YRPUM6JG.js";import{a as ne,b as U,n as oe,p as ie}from"../chunk-3NTV3JFP.js";import{a as M,b as ee,c as w,e as L,f as A,g as te}from"../chunk-5WE5G2CD.js";import{c as v,n as Z,t as q}from"../chunk-ZWUFPR6V.js";import{a as P,b as Q,c as H,d as W,e as N,g as X,h as b,i as l,m as I,p as Y}from"../chunk-IWY6MRSV.js";import"../chunk-ZHH3PWEW.js";import"../chunk-Y3VPZJTG.js";import"../chunk-DYQHWN7X.js";import"../chunk-JTBQO6IT.js";import"../chunk-WS6UFNKF.js";import{createServer as ke}from"node:http";import{randomUUID as Re}from"node:crypto";import*as D from"node:fs";ye();function Ne(r){if(!r||typeof r!="object"||Array.isArray(r))return!1;let f=r;return f.jsonrpc==="2.0"&&f.method==="initialize"}var Oe=["brokerUrl","port","stateDir","gcIntervalMs","apiVisibility"];function we(r){return new Promise((f,u)=>{let O="";r.on("data",g=>O+=g),r.on("end",()=>{try{f(JSON.parse(O))}catch(g){u(g)}}),r.on("error",u)})}async function Ve(r={}){try{return await Ce(r)}catch(f){throw b?.failed(),l(`fatal startup error: ${f?.stack??f}`),f}}async function Ce(r){let f=r.handleSignals!==!1;if(process.env.OURS_TEST_STARTUP_FAIL==="1")throw new Error("forced startup failure (OURS_TEST_STARTUP_FAIL)");if(r.config){let t=Oe.filter(e=>r.config[e]!==Q[e]);if(t.length>0)throw new Error(`startDaemon(config) disagrees with the config resolved at module load (${t.join(", ")}). The engine reads its config when src/runtime/env.ts is imported, so a later override cannot move the state dir, port or broker \u2014 set OURS_* env or config.json before importing the SDK.`)}let u=r.mcp,O=u?.isInitializeRequest??Ne,g=null;if(typeof r.onIdentityNotify=="function"){let t=r.onIdentityNotify;g=(e,i)=>{t(e,i,M.get(e)?.sid??null)},ne(g)}l("booting wrapper\u2026");try{await me(),ue()}catch(t){throw g&&U(g),z(),t}l(`wrapper ready (identities=${v.size}), starting HTTP server\u2026`),b?.update("server");let p={},T=new Map,k=new Map,Se=3e4,J=t=>{let e=k.get(t);e?e.n++:k.set(t,{n:1,since:Date.now()})},B=t=>{let e=k.get(t);e&&--e.n<=0&&k.delete(t)},F=()=>{let t=0;for(let e of[...T.keys()]){if(e==="stdio")continue;let i=w.get(e)?.pid;if(i===void 0||i<=1||L(i))continue;let n=k.get(e);if(n&&n.n>0&&Date.now()-n.since<Se)continue;let o=T.get(e);T.delete(e),delete p[e],w.delete(e),k.delete(e),o?.close().catch(()=>{}),u?.onSessionClosed?.(e),t++,l(`session ${e.slice(0,8)}\u2026 reaped (client pid ${i} dead)`)}return t},V=setInterval(()=>{F(),ae(),fe()},6e4);V.unref?.();let _=1e3,ve=10*6e4,h=new Map,Ie=(t,e)=>{let i=Array.isArray(e)?e:[e];for(let n of i){let o=n;!o||typeof o!="object"||o.id===void 0||o.id===null||typeof o.method!="string"||h.set(`${t}:${String(o.id)}`,{method:o.method,at:Date.now()})}if(h.size>_){let n=Date.now()-ve;for(let[o,a]of h)if(a.at<n&&h.delete(o),h.size<=_)break;for(;h.size>_;){let o=h.keys().next();if(o.done)break;h.delete(o.value)}}},Te=(t,e)=>{try{let i=e instanceof Error?e.message:String(e),n=/No connection established for request ID:\s*(\S+)/.exec(i);if(!n)return;let o=n[1],a=h.get(`${t}:${o}`);h.delete(`${t}:${o}`),l(`UNDELIVERABLE RESPONSE session=${t.slice(0,8)}\u2026 request_id=${o} method=${a?.method??"unknown"} age_ms=${a?Date.now()-a.at:"unknown"} at=${new Date().toISOString()} \u2014 the answer was produced but its stream was already gone`)}catch{}},S=ke(async(t,e)=>{let i=new URL(t.url,`http://localhost:${N}`);if(t.method==="GET"&&i.pathname==="/state-dir"){e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({stateDir:H,version:P,compat:1}));return}if(t.method==="GET"&&(i.pathname==="/version"||i.pathname==="/info")){e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({name:"ours",version:P,compat:1,protocol:de,pid:process.pid,stateDir:H}));return}if(t.method==="GET"&&i.pathname==="/identities"){if(!I(t,e))return;e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({identities:[...v.values()].map(n=>({name:n.name,...n.temp?{temporary:!0,stale:!L(n.temp.owner.pid)}:{}}))}));return}if(t.method==="GET"&&i.pathname==="/unread"){if(!I(t,e))return;e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(ie()));return}{let n=/^\/identities\/([^/]+)\/notifications$/.exec(i.pathname);if(t.method==="GET"&&n){if(!I(t,e))return;let o=decodeURIComponent(n[1]);if(Y(o)!==null){e.writeHead(400,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"invalid identity name"}));return}await oe(t,e,o,i.searchParams.get("since"),i.searchParams.get("kinds"));return}}if(t.method==="POST"&&i.pathname==="/files/upload"){if(!I(t,e))return;let n=t.headers["x-ours-lease-token"],o=typeof n=="string"&&n?A(n):void 0,a=o?v.get(o.identity):void 0;if(!a){e.writeHead(401,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no identity bound to this session"}));return}let y=t.headers["content-length"],d=typeof y=="string"?Number(y):NaN,m=t.headers["x-ours-filename"];try{let s=await pe(a,t,{filename:typeof m=="string"?decodeURIComponent(m):"",mime:typeof t.headers["content-type"]=="string"?t.headers["content-type"]:"",declaredBytes:Number.isInteger(d)&&d>=0?d:null,cap:ce()});e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(s))}catch(s){let R=s instanceof le?s.status:500;e.headersSent||(e.writeHead(R,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:s instanceof Error?s.message:String(s)})))}return}{let n=/^\/files\/([^/]+)$/.exec(i.pathname);if(t.method==="GET"&&n){if(!I(t,e))return;let o=decodeURIComponent(n[1]),a=t.headers["x-ours-lease-token"],y=typeof a=="string"&&a?A(a):void 0,d=y?v.get(y.identity):void 0;if(!d){e.writeHead(401,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no identity bound to this session"}));return}let m=q(d,o);if(!m){e.writeHead(404,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no such file for the bound identity (run get_files first, or it belongs to another identity)"}));return}try{let s=D.statSync(m);e.writeHead(200,{"Content-Type":"application/octet-stream","Content-Length":String(s.size)});let R=D.createReadStream(m);R.on("error",()=>{try{e.destroy()}catch{}}),R.pipe(e)}catch(s){e.writeHead(500,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:`failed to read file: ${String(s)}`}))}return}}if(i.pathname.startsWith(ge)){await he(t,e,i.pathname,we);return}if(i.pathname!=="/mcp"||!u){e.writeHead(404,{"Content-Type":"text/plain"}),e.end("Not found");return}if(I(t,e))try{if(t.method==="POST"){let n=await we(t),o=t.headers["mcp-session-id"],a=t.headers["x-ours-lease-token"],y=t.headers["x-ours-client-pid"],d=y?parseInt(y,10):void 0,m={token:a,pid:Number.isInteger(d)?d:void 0};if(o&&p[o]){w.set(o,m),Ie(o,n),J(o),$(e);try{await p[o].handleRequest(t,e,n)}finally{B(o)}}else if(!o&&O(n)){F();let s=u.createTransport({sessionIdGenerator:()=>Re(),onsessioninitialized:c=>{p[c]=s,w.set(c,m),T.set(c,E),u.onSessionInitialized?.(c,E),l(`session ${c.slice(0,8)}\u2026 initialized`)}}),R={sessionId:()=>s.sessionId??"pending",leaseToken:()=>w.get(s.sessionId??"pending")?.token,clientPid:()=>w.get(s.sessionId??"pending")?.pid},E=u.createServer(R);E.server.onerror=c=>Te(s.sessionId??"pending",c),s.onclose=()=>{let c=s.sessionId;c&&(delete p[c],T.delete(c),w.delete(c),u.onSessionClosed?.(c),l(`session ${c.slice(0,8)}\u2026 closed (lease kept)`))},await E.connect(s),$(e),await s.handleRequest(t,e,n)}else e.writeHead(400,{"Content-Type":"application/json"}),e.end(JSON.stringify({jsonrpc:"2.0",error:{code:-32e3,message:"Bad Request: No valid session ID"},id:null}))}else if(t.method==="GET"){let n=t.headers["mcp-session-id"];if(!n||!p[n]){e.writeHead(400,{"Content-Type":"text/plain"}),e.end("Invalid or missing session ID");return}J(n),$(e);try{await p[n].handleRequest(t,e)}finally{B(n)}}else if(t.method==="DELETE"){let n=t.headers["mcp-session-id"];if(!n||!p[n]){e.writeHead(400,{"Content-Type":"text/plain"}),e.end("Invalid or missing session ID");return}let o=w.get(n)?.token??t.headers["x-ours-lease-token"];if(o){for(let[a,y]of[...M]){if(y.token!==o)continue;M.delete(a);let d=v.get(a);d?.temp&&d.temp.owner.tokenHash===Z(o)&&!d.temp.closing&&re(d,"owning session released its lease").catch(m=>l(`[${a}] close on lease release failed:`,String(m)))}ee.delete(o),te(),l(`lease released by token \u2026${o.slice(-6)}`)}await p[n].handleRequest(t,e)}else e.writeHead(405,{"Content-Type":"text/plain"}),e.end("Method not allowed")}catch(n){l("HTTP handler error:",String(n)),e.headersSent||(e.writeHead(500,{"Content-Type":"application/json"}),e.end(JSON.stringify({jsonrpc:"2.0",error:{code:-32603,message:"Internal server error"},id:null})))}});S.requestTimeout=0;let K=!1,x=async()=>{if(!K){K=!0,clearInterval(V),z(),g&&U(g);for(let t of Object.keys(p)){try{await p[t].close()}catch{}delete p[t]}T.clear();for(let t of v.values())try{se(t)}catch(e){l(`[${t.name}] shutdown save failed:`,String(e))}S.closeAllConnections?.()}};try{await new Promise((t,e)=>{let i=n=>e(n);S.once("error",i),S.listen(N,"127.0.0.1",()=>{S.off("error",i),b?.ready(),l(`MCP server v${r.version??P} ready (transport=http, port=${N}, visibility=${X}, identities=${v.size}, state=${H}, broker=${W})`),t()})})}catch(t){throw await x(),t}let C=async()=>{l("shutting down\u2026"),await x(),S.close(),await r.onShutdown?.(),process.exit(0)};f&&(process.on("SIGINT",C),process.on("SIGTERM",C));let j=S.address();return{port:typeof j=="object"&&j!==null?j.port:N,close:async()=>{f&&(process.off("SIGINT",C),process.off("SIGTERM",C)),await x(),await new Promise(t=>S.close(()=>t()))}}}export{Ve as startDaemon};
|
|
2
|
+
import{a as ye}from"../chunk-NBEWKZG4.js";import{d as $}from"../chunk-V64IUVSS.js";import{a as G}from"../chunk-37D5PCFY.js";import{a as ue,b as z}from"../chunk-PXIK7DM2.js";import{a as ge,d as he}from"../chunk-ZPG5V73S.js";import{b as me}from"../chunk-2XOTJ6G3.js";import"../chunk-EHCBEY52.js";import"../chunk-LRMN6BSO.js";import"../chunk-PBLR7J42.js";import"../chunk-5KVWI5BW.js";import"../chunk-LPXPNZTS.js";import{e as le,f as pe,h as fe}from"../chunk-67DAPEUW.js";import{b as ce}from"../chunk-VXVW4KJU.js";import"../chunk-5OAIOIQ2.js";import"../chunk-P55RJGZU.js";import"../chunk-JTQMUWPE.js";import"../chunk-SBKG5P7O.js";import{b as re,c as ae}from"../chunk-J2Q2JDUS.js";import"../chunk-JOKNFUW3.js";import"../chunk-DIRW7I4S.js";import"../chunk-65KGEJBX.js";import{b as de}from"../chunk-M2WREVID.js";import"../chunk-PJ5F7BI6.js";import"../chunk-GJXNZNS6.js";import{o as se}from"../chunk-NODVUYDQ.js";import"../chunk-YRPUM6JG.js";import{a as ne,b as U,n as oe,p as ie}from"../chunk-O3WRMYAS.js";import{a as M,b as ee,c as w,e as L,f as A,g as te}from"../chunk-PMDY4YIZ.js";import{c as v,n as Z,t as q}from"../chunk-ETBJ4VOK.js";import{a as P,b as Q,c as H,d as W,e as N,g as X,h as b,i as l,m as I,p as Y}from"../chunk-ZLCQNN5W.js";import"../chunk-ZHH3PWEW.js";import"../chunk-Y3VPZJTG.js";import"../chunk-TXAIJEXA.js";import"../chunk-JTBQO6IT.js";import"../chunk-WS6UFNKF.js";import{createServer as ke}from"node:http";import{randomUUID as Re}from"node:crypto";import*as D from"node:fs";ye();function Ne(r){if(!r||typeof r!="object"||Array.isArray(r))return!1;let f=r;return f.jsonrpc==="2.0"&&f.method==="initialize"}var Oe=["brokerUrl","port","stateDir","gcIntervalMs","apiVisibility"];function we(r){return new Promise((f,u)=>{let O="";r.on("data",g=>O+=g),r.on("end",()=>{try{f(JSON.parse(O))}catch(g){u(g)}}),r.on("error",u)})}async function Ve(r={}){try{return await Ce(r)}catch(f){throw b?.failed(),l(`fatal startup error: ${f?.stack??f}`),f}}async function Ce(r){let f=r.handleSignals!==!1;if(process.env.OURS_TEST_STARTUP_FAIL==="1")throw new Error("forced startup failure (OURS_TEST_STARTUP_FAIL)");if(r.config){let t=Oe.filter(e=>r.config[e]!==Q[e]);if(t.length>0)throw new Error(`startDaemon(config) disagrees with the config resolved at module load (${t.join(", ")}). The engine reads its config when src/runtime/env.ts is imported, so a later override cannot move the state dir, port or broker \u2014 set OURS_* env or config.json before importing the SDK.`)}let u=r.mcp,O=u?.isInitializeRequest??Ne,g=null;if(typeof r.onIdentityNotify=="function"){let t=r.onIdentityNotify;g=(e,i)=>{t(e,i,M.get(e)?.sid??null)},ne(g)}l("booting wrapper\u2026");try{await me(),ue()}catch(t){throw g&&U(g),z(),t}l(`wrapper ready (identities=${v.size}), starting HTTP server\u2026`),b?.update("server");let p={},T=new Map,k=new Map,Se=3e4,J=t=>{let e=k.get(t);e?e.n++:k.set(t,{n:1,since:Date.now()})},B=t=>{let e=k.get(t);e&&--e.n<=0&&k.delete(t)},F=()=>{let t=0;for(let e of[...T.keys()]){if(e==="stdio")continue;let i=w.get(e)?.pid;if(i===void 0||i<=1||L(i))continue;let n=k.get(e);if(n&&n.n>0&&Date.now()-n.since<Se)continue;let o=T.get(e);T.delete(e),delete p[e],w.delete(e),k.delete(e),o?.close().catch(()=>{}),u?.onSessionClosed?.(e),t++,l(`session ${e.slice(0,8)}\u2026 reaped (client pid ${i} dead)`)}return t},V=setInterval(()=>{F(),ae(),fe()},6e4);V.unref?.();let _=1e3,ve=10*6e4,h=new Map,Ie=(t,e)=>{let i=Array.isArray(e)?e:[e];for(let n of i){let o=n;!o||typeof o!="object"||o.id===void 0||o.id===null||typeof o.method!="string"||h.set(`${t}:${String(o.id)}`,{method:o.method,at:Date.now()})}if(h.size>_){let n=Date.now()-ve;for(let[o,a]of h)if(a.at<n&&h.delete(o),h.size<=_)break;for(;h.size>_;){let o=h.keys().next();if(o.done)break;h.delete(o.value)}}},Te=(t,e)=>{try{let i=e instanceof Error?e.message:String(e),n=/No connection established for request ID:\s*(\S+)/.exec(i);if(!n)return;let o=n[1],a=h.get(`${t}:${o}`);h.delete(`${t}:${o}`),l(`UNDELIVERABLE RESPONSE session=${t.slice(0,8)}\u2026 request_id=${o} method=${a?.method??"unknown"} age_ms=${a?Date.now()-a.at:"unknown"} at=${new Date().toISOString()} \u2014 the answer was produced but its stream was already gone`)}catch{}},S=ke(async(t,e)=>{let i=new URL(t.url,`http://localhost:${N}`);if(t.method==="GET"&&i.pathname==="/state-dir"){e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({stateDir:H,version:P,compat:1}));return}if(t.method==="GET"&&(i.pathname==="/version"||i.pathname==="/info")){e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({name:"ours",version:P,compat:1,protocol:de,pid:process.pid,stateDir:H}));return}if(t.method==="GET"&&i.pathname==="/identities"){if(!I(t,e))return;e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({identities:[...v.values()].map(n=>({name:n.name,...n.temp?{temporary:!0,stale:!L(n.temp.owner.pid)}:{}}))}));return}if(t.method==="GET"&&i.pathname==="/unread"){if(!I(t,e))return;e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(ie()));return}{let n=/^\/identities\/([^/]+)\/notifications$/.exec(i.pathname);if(t.method==="GET"&&n){if(!I(t,e))return;let o=decodeURIComponent(n[1]);if(Y(o)!==null){e.writeHead(400,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"invalid identity name"}));return}await oe(t,e,o,i.searchParams.get("since"),i.searchParams.get("kinds"));return}}if(t.method==="POST"&&i.pathname==="/files/upload"){if(!I(t,e))return;let n=t.headers["x-ours-lease-token"],o=typeof n=="string"&&n?A(n):void 0,a=o?v.get(o.identity):void 0;if(!a){e.writeHead(401,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no identity bound to this session"}));return}let y=t.headers["content-length"],d=typeof y=="string"?Number(y):NaN,m=t.headers["x-ours-filename"];try{let s=await pe(a,t,{filename:typeof m=="string"?decodeURIComponent(m):"",mime:typeof t.headers["content-type"]=="string"?t.headers["content-type"]:"",declaredBytes:Number.isInteger(d)&&d>=0?d:null,cap:ce()});e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(s))}catch(s){let R=s instanceof le?s.status:500;e.headersSent||(e.writeHead(R,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:s instanceof Error?s.message:String(s)})))}return}{let n=/^\/files\/([^/]+)$/.exec(i.pathname);if(t.method==="GET"&&n){if(!I(t,e))return;let o=decodeURIComponent(n[1]),a=t.headers["x-ours-lease-token"],y=typeof a=="string"&&a?A(a):void 0,d=y?v.get(y.identity):void 0;if(!d){e.writeHead(401,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no identity bound to this session"}));return}let m=q(d,o);if(!m){e.writeHead(404,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no such file for the bound identity (run get_files first, or it belongs to another identity)"}));return}try{let s=D.statSync(m);e.writeHead(200,{"Content-Type":"application/octet-stream","Content-Length":String(s.size)});let R=D.createReadStream(m);R.on("error",()=>{try{e.destroy()}catch{}}),R.pipe(e)}catch(s){e.writeHead(500,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:`failed to read file: ${String(s)}`}))}return}}if(i.pathname.startsWith(ge)){await he(t,e,i.pathname,we);return}if(i.pathname!=="/mcp"||!u){e.writeHead(404,{"Content-Type":"text/plain"}),e.end("Not found");return}if(I(t,e))try{if(t.method==="POST"){let n=await we(t),o=t.headers["mcp-session-id"],a=t.headers["x-ours-lease-token"],y=t.headers["x-ours-client-pid"],d=y?parseInt(y,10):void 0,m={token:a,pid:Number.isInteger(d)?d:void 0};if(o&&p[o]){w.set(o,m),Ie(o,n),J(o),$(e);try{await p[o].handleRequest(t,e,n)}finally{B(o)}}else if(!o&&O(n)){F();let s=u.createTransport({sessionIdGenerator:()=>Re(),onsessioninitialized:c=>{p[c]=s,w.set(c,m),T.set(c,E),u.onSessionInitialized?.(c,E),l(`session ${c.slice(0,8)}\u2026 initialized`)}}),R={sessionId:()=>s.sessionId??"pending",leaseToken:()=>w.get(s.sessionId??"pending")?.token,clientPid:()=>w.get(s.sessionId??"pending")?.pid},E=u.createServer(R);E.server.onerror=c=>Te(s.sessionId??"pending",c),s.onclose=()=>{let c=s.sessionId;c&&(delete p[c],T.delete(c),w.delete(c),u.onSessionClosed?.(c),l(`session ${c.slice(0,8)}\u2026 closed (lease kept)`))},await E.connect(s),$(e),await s.handleRequest(t,e,n)}else e.writeHead(400,{"Content-Type":"application/json"}),e.end(JSON.stringify({jsonrpc:"2.0",error:{code:-32e3,message:"Bad Request: No valid session ID"},id:null}))}else if(t.method==="GET"){let n=t.headers["mcp-session-id"];if(!n||!p[n]){e.writeHead(400,{"Content-Type":"text/plain"}),e.end("Invalid or missing session ID");return}J(n),$(e);try{await p[n].handleRequest(t,e)}finally{B(n)}}else if(t.method==="DELETE"){let n=t.headers["mcp-session-id"];if(!n||!p[n]){e.writeHead(400,{"Content-Type":"text/plain"}),e.end("Invalid or missing session ID");return}let o=w.get(n)?.token??t.headers["x-ours-lease-token"];if(o){for(let[a,y]of[...M]){if(y.token!==o)continue;M.delete(a);let d=v.get(a);d?.temp&&d.temp.owner.tokenHash===Z(o)&&!d.temp.closing&&re(d,"owning session released its lease").catch(m=>l(`[${a}] close on lease release failed:`,String(m)))}ee.delete(o),te(),l(`lease released by token \u2026${o.slice(-6)}`)}await p[n].handleRequest(t,e)}else e.writeHead(405,{"Content-Type":"text/plain"}),e.end("Method not allowed")}catch(n){l("HTTP handler error:",String(n)),e.headersSent||(e.writeHead(500,{"Content-Type":"application/json"}),e.end(JSON.stringify({jsonrpc:"2.0",error:{code:-32603,message:"Internal server error"},id:null})))}});S.requestTimeout=0;let K=!1,x=async()=>{if(!K){K=!0,clearInterval(V),z(),g&&U(g);for(let t of Object.keys(p)){try{await p[t].close()}catch{}delete p[t]}T.clear();for(let t of v.values())try{se(t)}catch(e){l(`[${t.name}] shutdown save failed:`,String(e))}S.closeAllConnections?.()}};try{await new Promise((t,e)=>{let i=n=>e(n);S.once("error",i),S.listen(N,"127.0.0.1",()=>{S.off("error",i),b?.ready(),l(`MCP server v${r.version??P} ready (transport=http, port=${N}, visibility=${X}, identities=${v.size}, state=${H}, broker=${W})`),t()})})}catch(t){throw await x(),t}let C=async()=>{l("shutting down\u2026"),await x(),S.close(),await r.onShutdown?.(),process.exit(0)};f&&(process.on("SIGINT",C),process.on("SIGTERM",C));let j=S.address();return{port:typeof j=="object"&&j!==null?j.port:N,close:async()=>{f&&(process.off("SIGINT",C),process.off("SIGTERM",C)),await x(),await new Promise(t=>S.close(()=>t()))}}}export{Ve as startDaemon};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{a,b,c,d,e,f,g}from"../chunk-
|
|
2
|
+
import{a,b,c,d,e,f,g}from"../chunk-GJXNZNS6.js";import"../chunk-NODVUYDQ.js";import"../chunk-YRPUM6JG.js";import"../chunk-O3WRMYAS.js";import"../chunk-PMDY4YIZ.js";import"../chunk-ETBJ4VOK.js";import"../chunk-ZLCQNN5W.js";import"../chunk-ZHH3PWEW.js";import"../chunk-Y3VPZJTG.js";import"../chunk-TXAIJEXA.js";import"../chunk-JTBQO6IT.js";import"../chunk-WS6UFNKF.js";export{d as clearRootMarker,f as delegateRole,e as describeIdentity,g as establishRoot,c as readRootMarker,b as rootName,a as setRootName};
|
package/dist/identity/lease.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{a,b,c,d,e,f,g,h,i}from"../chunk-
|
|
2
|
+
import{a,b,c,d,e,f,g,h,i}from"../chunk-PMDY4YIZ.js";import"../chunk-ETBJ4VOK.js";import"../chunk-ZLCQNN5W.js";import"../chunk-ZHH3PWEW.js";import"../chunk-Y3VPZJTG.js";import"../chunk-TXAIJEXA.js";import"../chunk-WS6UFNKF.js";export{i as bindSession,f as leaseByToken,a as leases,d as outboundRemovalInFlight,g as persistBindings,e as pidAlive,h as resolveBound,c as sessionHeaders,b as tombstones};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{a,b,c,d}from"../chunk-
|
|
2
|
+
import{a,b,c,d}from"../chunk-J2Q2JDUS.js";import"../chunk-JOKNFUW3.js";import"../chunk-DIRW7I4S.js";import"../chunk-GJXNZNS6.js";import"../chunk-NODVUYDQ.js";import"../chunk-YRPUM6JG.js";import"../chunk-O3WRMYAS.js";import"../chunk-PMDY4YIZ.js";import"../chunk-ETBJ4VOK.js";import"../chunk-ZLCQNN5W.js";import"../chunk-ZHH3PWEW.js";import"../chunk-Y3VPZJTG.js";import"../chunk-TXAIJEXA.js";import"../chunk-JTBQO6IT.js";import"../chunk-WS6UFNKF.js";export{b as closeTemporaryIdentity,a as deleteIdentityCompletely,d as sweepOrphanTempDirs,c as sweepStaleTempIdentities};
|
package/dist/identity/model.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{a as b,b as c,c as d,d as e,e as f,f as g,g as h,h as i,i as j,j as k,k as l,l as m,m as n,n as o,o as p,p as q,q as r,r as s,s as t,t as u,u as v}from"../chunk-
|
|
2
|
+
import{a as b,b as c,c as d,d as e,e as f,f as g,g as h,h as i,i as j,j as k,k as l,l as m,m as n,n as o,o as p,p as q,q as r,r as s,s as t,t as u,u as v}from"../chunk-ETBJ4VOK.js";import"../chunk-ZLCQNN5W.js";import"../chunk-ZHH3PWEW.js";import{a}from"../chunk-Y3VPZJTG.js";import"../chunk-TXAIJEXA.js";import"../chunk-WS6UFNKF.js";export{a as FILE_SELECTION_CAP,k as dataPath,u as findIdentityFile,o as hashLeaseToken,d as identities,i as identityDir,t as isSelectableWireId,s as isWireId,j as keyPath,v as listPersistedNames,l as notifyLogPath,q as readTempMetaFile,e as registrar,f as registrarAdBlob,g as setRegistrar,h as setRegistrarAdBlob,c as setWrapper,n as tempMetaPath,r as tightenIdentityPerms,m as unreadPath,b as wrapper,p as writeTempMetaFile};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{i as a,j as b,k as c,l as d}from"../chunk-
|
|
2
|
+
import{i as a,j as b,k as c,l as d}from"../chunk-NODVUYDQ.js";import"../chunk-YRPUM6JG.js";import"../chunk-O3WRMYAS.js";import"../chunk-PMDY4YIZ.js";import"../chunk-ETBJ4VOK.js";import"../chunk-ZLCQNN5W.js";import"../chunk-ZHH3PWEW.js";import"../chunk-Y3VPZJTG.js";import"../chunk-TXAIJEXA.js";import"../chunk-JTBQO6IT.js";import"../chunk-WS6UFNKF.js";export{a as createPacket,c as provisionIdentity,b as reservedNames,d as restoreIdentity};
|
package/dist/index.d.ts
CHANGED
|
@@ -3,4 +3,5 @@ export * from './client/http.js';
|
|
|
3
3
|
export * from './client/select.js';
|
|
4
4
|
export * from './version-advisory.js';
|
|
5
5
|
export { FILE_SELECTION_CAP } from './constants.js';
|
|
6
|
+
export type { HistoryFile, HistoryMessage, HistoryPage, HistoryQuery, HistorySummary, } from './history.js';
|
|
6
7
|
export type { MessageReceivedRecord, MessengerNotificationEvent, NotificationEvent, ReceiptKind, ReceiptReceivedRecord, SyncRequiredRecord, UnknownNotificationEvent, } from './events.js';
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{a as
|
|
2
|
+
import{a as U,b,c as z,d as B,e as D,f as G,g as J,h as V}from"./chunk-SEZTXIKN.js";import{a as T}from"./chunk-HZCFYJAG.js";import{a as W}from"./chunk-5EWCIQH6.js";import{A as I,B as L,C as P,D as _,E as h,F as k,G as l,H as q,I as w,J as A,K,L as O,M as Q,a as o,b as r,c as t,d as i,e as s,f as n,g as c,h as p,i as y,j as f,k as m,l as R,m as a,n as d,o as x,p as v,q as E,r as H,s as g,t as N,u,v as M,w as S,x as j,y as C,z as F}from"./chunk-65KGEJBX.js";import{a as e}from"./chunk-Y3VPZJTG.js";import"./chunk-JTBQO6IT.js";import"./chunk-WS6UFNKF.js";export{B as DAEMON_TOKEN_FILE,z as DEFAULT_DAEMON_PORT,U as DaemonSelectionError,b as DaemonUnavailableError,e as FILE_SELECTION_CAP,T as OursClient,o as OursError,J as assertDaemonStateDir,V as attachOursClient,G as describeDaemonConfig,t as errBindingReassigned,N as errBoundElsewhere,i as errBoundIdentityGone,K as errDuplicateId,k as errFileTooLarge,P as errFileUnreadable,M as errIdentityClosedWithError,j as errIdentityPartiallyRemoved,w as errInvalidSelection,A as errMalformedId,n as errNameTaken,c as errNoLeaseHeaders,v as errNoLeaseToken,F as errNoPolicyArgs,q as errNoRoot,x as errNoSuchIdentity,r as errNotBound,f as errNotBoundNoName,m as errNotTemporary,d as errPathNotAbsolute,C as errPublicInviteNamed,p as errRandomNameExhausted,y as errRootExists,S as errRootHasRoles,l as errSaveFileFallback,I as errSendFileArgs,L as errSendFileFilenameRequired,_ as errSendFileUploadArgs,a as errTempClosedWithError,s as errTempClosingBound,E as errTempClosingChoose,R as errTempOwnedElsewhereClose,u as errTempOwnedElsewhereRemove,H as errTempOwnedLive,g as errTempStale,Q as errTool,O as errUnknownOrStaleId,h as errUploadNotFound,W as formatVersionAdvisory,D as resolveDaemonConfig};
|
package/dist/messaging/send.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{a,b,c,d}from"../chunk-
|
|
2
|
+
import{a,b,c,d}from"../chunk-5OAIOIQ2.js";import"../chunk-GJXNZNS6.js";import"../chunk-NODVUYDQ.js";import"../chunk-YRPUM6JG.js";import"../chunk-O3WRMYAS.js";import"../chunk-PMDY4YIZ.js";import"../chunk-ETBJ4VOK.js";import"../chunk-ZLCQNN5W.js";import"../chunk-ZHH3PWEW.js";import"../chunk-Y3VPZJTG.js";import"../chunk-TXAIJEXA.js";import"../chunk-JTBQO6IT.js";import"../chunk-WS6UFNKF.js";export{a as findSibling,d as parseSendVerdict,c as sendViaLocalBook,b as sendViaSibling};
|
package/dist/mufl/handlers.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{h as a}from"../chunk-
|
|
2
|
+
import{h as a}from"../chunk-NODVUYDQ.js";import"../chunk-YRPUM6JG.js";import"../chunk-O3WRMYAS.js";import"../chunk-PMDY4YIZ.js";import"../chunk-ETBJ4VOK.js";import"../chunk-ZLCQNN5W.js";import"../chunk-ZHH3PWEW.js";import"../chunk-Y3VPZJTG.js";import"../chunk-TXAIJEXA.js";import"../chunk-JTBQO6IT.js";import"../chunk-WS6UFNKF.js";export{a as wireHandlers};
|
package/dist/mufl/tx.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
-
import{q as a,r as b,s as c,t as d,u as e,v as f}from"../chunk-
|
|
2
|
+
import{q as a,r as b,s as c,t as d,u as e,v as f}from"../chunk-NODVUYDQ.js";import"../chunk-YRPUM6JG.js";import"../chunk-O3WRMYAS.js";import"../chunk-PMDY4YIZ.js";import"../chunk-ETBJ4VOK.js";import"../chunk-ZLCQNN5W.js";import"../chunk-ZHH3PWEW.js";import"../chunk-Y3VPZJTG.js";import"../chunk-TXAIJEXA.js";import"../chunk-JTBQO6IT.js";import"../chunk-WS6UFNKF.js";export{e as enqueueMutation,f as mutatingTx,c as readonlyTx,d as withLock,a as withScope,b as withScopeAsync};
|