@ours.network/sdk 0.1.1
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/LICENSE +98 -0
- package/README.md +41 -0
- package/dist/api/contacts.d.ts +31 -0
- package/dist/api/contacts.js +2 -0
- package/dist/api/files.d.ts +10 -0
- package/dist/api/files.js +2 -0
- package/dist/api/identity.d.ts +44 -0
- package/dist/api/identity.js +2 -0
- package/dist/api/messaging.d.ts +23 -0
- package/dist/api/messaging.js +2 -0
- package/dist/api/profile.d.ts +9 -0
- package/dist/api/profile.js +2 -0
- package/dist/api/types.d.ts +177 -0
- package/dist/api/types.js +1 -0
- package/dist/book.d.ts +22 -0
- package/dist/book.js +2 -0
- package/dist/boot.d.ts +1 -0
- package/dist/boot.js +2 -0
- package/dist/chunk-37D5PCFY.js +2 -0
- package/dist/chunk-3DQSMLVZ.js +2 -0
- package/dist/chunk-5EWCIQH6.js +2 -0
- package/dist/chunk-7UUFYO6G.js +2 -0
- package/dist/chunk-A3SXVUOC.js +2 -0
- package/dist/chunk-AJQIWYXG.js +2 -0
- package/dist/chunk-DIRW7I4S.js +2 -0
- package/dist/chunk-HCIVLHKC.js +2 -0
- package/dist/chunk-HSVIKO4D.js +3 -0
- package/dist/chunk-IB2U7K6Y.js +5 -0
- package/dist/chunk-KZMPGVQM.js +2 -0
- package/dist/chunk-LKFYUCN7.js +2 -0
- package/dist/chunk-NMYSFQBL.js +2 -0
- package/dist/chunk-NQQ4GSVI.js +5 -0
- package/dist/chunk-NSPYN5TT.js +2 -0
- package/dist/chunk-P55RJGZU.js +2 -0
- package/dist/chunk-PCHN744Y.js +2 -0
- package/dist/chunk-Q3UVLSCX.js +2 -0
- package/dist/chunk-RAGUBE4Y.js +2 -0
- package/dist/chunk-T25JIPX5.js +2 -0
- package/dist/chunk-TZBRSDND.js +2 -0
- package/dist/chunk-UELGY557.js +2 -0
- package/dist/chunk-UJGRFV4J.js +2 -0
- package/dist/chunk-UM73BGFH.js +2 -0
- package/dist/chunk-V64IUVSS.js +4 -0
- package/dist/chunk-VOYMK2OO.js +2 -0
- package/dist/chunk-VW2KWXSJ.js +2 -0
- package/dist/chunk-X4RVJ5VL.js +6 -0
- package/dist/chunk-YRPUM6JG.js +2 -0
- package/dist/chunk-ZAXRB5MO.js +2 -0
- package/dist/chunk-ZHH3PWEW.js +4 -0
- package/dist/client/http.d.ts +178 -0
- package/dist/client/http.js +2 -0
- package/dist/cluster/control.d.ts +5 -0
- package/dist/cluster/control.js +2 -0
- package/dist/cluster/manifest.d.ts +12 -0
- package/dist/cluster/manifest.js +2 -0
- package/dist/config.d.ts +37 -0
- package/dist/config.js +2 -0
- package/dist/connector.d.ts +68 -0
- package/dist/connector.js +5 -0
- package/dist/daemon.d.ts +5 -0
- package/dist/daemon.js +2 -0
- package/dist/errors.d.ts +40 -0
- package/dist/errors.js +2 -0
- package/dist/events.d.ts +144 -0
- package/dist/events.js +2 -0
- package/dist/files.d.ts +2 -0
- package/dist/files.js +2 -0
- package/dist/gc.d.ts +2 -0
- package/dist/gc.js +2 -0
- package/dist/http/api-routes.d.ts +63 -0
- package/dist/http/api-routes.js +2 -0
- package/dist/http/server.d.ts +120 -0
- package/dist/http/server.js +2 -0
- package/dist/identity/hierarchy.d.ts +20 -0
- package/dist/identity/hierarchy.js +2 -0
- package/dist/identity/lease.d.ts +29 -0
- package/dist/identity/lease.js +2 -0
- package/dist/identity/lifecycle.d.ts +5 -0
- package/dist/identity/lifecycle.js +2 -0
- package/dist/identity/model.d.ts +67 -0
- package/dist/identity/model.js +2 -0
- package/dist/identity/provision.d.ts +12 -0
- package/dist/identity/provision.js +2 -0
- package/dist/inbox.d.ts +38 -0
- package/dist/inbox.js +2 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +2 -0
- package/dist/messaging/send.d.ts +28 -0
- package/dist/messaging/send.js +2 -0
- package/dist/mufl/handlers.d.ts +5 -0
- package/dist/mufl/handlers.js +2 -0
- package/dist/mufl/tx.d.ts +9 -0
- package/dist/mufl/tx.js +2 -0
- package/dist/mufl_code/8ED6356B41CC689C75DA3302AD7856058131661A6ABBAC961E71BA838D8C97A3.muflo +0 -0
- package/dist/notify.d.ts +24 -0
- package/dist/notify.js +2 -0
- package/dist/process-state.d.ts +2 -0
- package/dist/process-state.js +2 -0
- package/dist/protocol.d.ts +1 -0
- package/dist/protocol.js +2 -0
- package/dist/render/adapt-to-json.d.ts +83 -0
- package/dist/render/adapt-to-json.js +2 -0
- package/dist/runtime/env.d.ts +18 -0
- package/dist/runtime/env.js +2 -0
- package/dist/runtime/unit.d.ts +15 -0
- package/dist/runtime/unit.js +2 -0
- package/dist/sse-keepalive.d.ts +18 -0
- package/dist/sse-keepalive.js +2 -0
- package/dist/startup-progress.d.ts +54 -0
- package/dist/startup-progress.js +2 -0
- package/dist/state.d.ts +5 -0
- package/dist/state.js +2 -0
- package/dist/sweeps.d.ts +18 -0
- package/dist/sweeps.js +2 -0
- package/dist/transcribe.d.ts +113 -0
- package/dist/transcribe.js +2 -0
- package/dist/version-advisory.d.ts +4 -0
- package/dist/version-advisory.js +2 -0
- package/dist/voice-setup.d.ts +44 -0
- package/dist/voice-setup.js +28 -0
- package/package.json +49 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{a as ne}from"./chunk-5EWCIQH6.js";import{mkdirSync as te,writeFileSync as Te,readFileSync as ve,readdirSync as ke,statSync as j,unlinkSync as Oe,chmodSync as se,createWriteStream as Me}from"node:fs";import{join as x,dirname as Ie,resolve as Ae}from"node:path";import{homedir as Ee}from"node:os";import{Readable as xe}from"node:stream";import{pipeline as De}from"node:stream/promises";var $e="0.1.1",Ne=new Set(["choose_identity","create_identity","create_root_identity"]),Ue="save_file",Le="get_files",re=a=>new Promise(g=>setTimeout(g,a)),V=a=>typeof a?.method=="string"&&a.id!==void 0&&a.id!==null,Ce=a=>a&&typeof a=="object"&&!("method"in a)&&a.id!==void 0&&a.id!==null,oe=a=>{let g=a.result;return!!a.error||!!(g&&g.isError)},ie=Number(process.env.OURS_RESTORE_TTL_MS)>0?Number(process.env.OURS_RESTORE_TTL_MS):7*24*60*60*1e3,ae=["1","true","yes","on"].includes((process.env.OURS_NO_AUTORESTORE??"").trim().toLowerCase());async function ze(a){let g=new URL(a.url),i=(...e)=>process.stderr.write(`[ours-proxy] ${e.join(" ")}
|
|
3
|
+
`),z=e=>Number.isInteger(e)&&e>1,q=Number(process.env.OURS_CLIENT_PID),G=z(q)?q:z(process.ppid)?process.ppid:process.pid,B=(process.env.CLAUDE_CODE_SESSION_ID??"").trim()||`client:${G}`,w=null,M=null,$,f=null,I=new Map,N=new Set,_=null,S=ae?null:(process.env.CLAUDE_CODE_SESSION_ID??"").trim()||null,ce=a.stateDir??process.env.OURS_STATE_DIR??x(Ee(),".ours"),R=x(ce,"session-restore"),W=S&&/^[A-Za-z0-9._-]{1,200}$/.test(S)?S:null,y=W?x(R,`${W}.json`):null,Q=!1,U=null;function de(e){if(y)try{te(R,{recursive:!0,mode:448}),Te(y,JSON.stringify({claudeSessionId:S,identity:e,boundAt:new Date().toISOString()}),{mode:384}),se(R,448),se(y,384)}catch(t){i("restore persist failed (non-fatal):",String(t))}}function ue(){if(!y)return null;try{if(Date.now()-j(y).mtimeMs>ie)return null;let e=JSON.parse(ve(y,"utf8"));return(typeof e.identity=="string"?e.identity.trim():"")||null}catch{return null}}function le(){try{let e=Date.now();for(let t of ke(R)){if(!t.endsWith(".json"))continue;let n=x(R,t);try{e-j(n).mtimeMs>ie&&(Oe(n),i("session-restore: pruned expired record",t))}catch{}}}catch{}}let b=(()=>{let e=(process.env.OURS_REQUEST_TIMEOUT_MS??"").trim();if(e==="")return 12e4;let t=Number(e);return Number.isFinite(t)&&t>=0?t:12e4})(),p=new Map,A=new Map;function L(e,t,n){let o=p.get(e);if(!o)return;p.delete(e),o.progressToken!==void 0&&A.delete(o.progressToken);let s=Date.now()-o.sentAt;i(`FAILING BACK request id=${String(e)} method=${o.method} waited_ms=${s} reason=${n}`),m.send({jsonrpc:"2.0",id:e,error:{code:t,message:`ours proxy: no response from the ours daemon for "${o.method}" after ${s}ms (${n}). The request was NOT retried \u2014 retry it yourself if it is safe to repeat.`,data:{reason:n,method:o.method,waitedMs:s}}}).catch(r=>i("fail-back send failed:",String(r)))}b>0&&setInterval(()=>{let t=Date.now();for(let[n,o]of[...p])o.deadline<=t&&L(n,-32001,"watchdog timeout")},1e3).unref?.();let fe=6e4,X=3,C=0,h=0;function pe(e,t){m.send({jsonrpc:"2.0",method:"notifications/message",params:{level:e,logger:"ours-proxy",data:t}}).catch(n=>i("downstream notify failed:",String(n)))}let l=null,me=()=>l,E=!1,T=!1,v=!1,k=[],ge="__ours_proxy_init__",P=0,O=new Set,J=new Set,m=a.transports.createStdioServer();m.onmessage=e=>{let t=[],n=!1;for(let o of D(e)){let s=o;if(s.method==="notifications/initialized"&&(n=!0),V(s)){if(s.method==="initialize"&&(w=s,M)){i("absorbed re-initialize locally \u2014 upstream session kept stable"),m.send({jsonrpc:"2.0",id:s.id,result:M}).catch(r=>i("local initialize reply failed:",String(r)));continue}if(s.method==="tools/call"){let r=s.params;if(r&&Ne.has(r.name??"")&&typeof r.arguments?.name=="string"&&I.set(s.id,r.arguments.name),r?.name===Le&&N.add(s.id),r?.name===Ue){let c=s.params?.arguments??{};we(s.id,c);continue}}if(b>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+b,transport:null,progressToken:c?.progressToken}),c?.progressToken!==void 0&&A.set(c.progressToken,r)}}t.push(s)}if(t.length){let o=Array.isArray(e)?t:t[0];Y(o)}n&&ye()},m.onclose=()=>void H(0),m.onerror=e=>i("downstream error:",String(e));function ye(){if(Q||!f)return;Q=!0;let e=`__ours_proxy_restore_${++P}__`;O.add(e),U=e,i("session-restore: self-recovering bound identity",`"${f}"`),Y({jsonrpc:"2.0",id:e,method:"tools/call",params:{name:"choose_identity",arguments:{name:f}}})}function he(e,t){if(!(b<=0))for(let n of D(e)){let o=n.id;if(o===void 0)continue;let s=p.get(o);s&&(s.transport=t)}}async function we(e,t){let n=String(t.wire_id??"").trim(),o=String(t.dest_path??"").trim(),s=(r,c=!1)=>m.send({jsonrpc:"2.0",id:e,result:{content:[{type:"text",text:r}],isError:c}}).catch(d=>i("save_file reply failed:",String(d)));if(!n||!o){await s("save_file: both `wire_id` and `dest_path` are required.",!0);return}if(!/^[A-Za-z0-9]+$/.test(n)){await s("save_file: invalid wire_id.",!0);return}try{let r=new URL(g.href);r.pathname=`/files/${encodeURIComponent(n)}`,r.search="";let c={"x-ours-lease-token":B};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 ${n} 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=Ae(o);te(Ie(u),{recursive:!0}),await De(xe.fromWeb(d.body),Me(u));let be=j(u).size;await s(`Saved file (wire_id ${n}) to ${u} (${be} bytes). The bytes were streamed daemon\u2192proxy\u2192disk and never entered this result.`)}catch(r){await s(`save_file failed: ${String(r)}`,!0)}}function Y(e){if(E&&l){let t=l;he(e,t),l.send(e).catch(n=>{i("upstream send failed:",String(n));let o=D(e),s=o.filter(r=>!V(r));s.length&&k.push(Array.isArray(e)?s:s[0]);for(let r of o){let c=r;V(c)&&p.has(c.id)&&L(c.id,-32e3,"upstream send failed")}F(t,"send failed")})}else k.push(e)}function F(e,t){if(T||v||l!==null&&e!==l)return;i(`upstream dropped (${t}) \u2014 reconnecting`),E=!1;let n=l;l=null;try{n?.close?.()}catch{}if(n)for(let[o,s]of[...p])s.transport===n&&L(o,-32e3,`upstream dropped (${t})`);Se()}function _e(e){e.onmessage=t=>{let n=[];for(let o of D(t)){let s=o;if(s.method==="notifications/progress"){let r=s.params?.progressToken;if(r!==void 0){let c=A.get(r),d=c!==void 0?p.get(c):void 0;d&&(d.deadline=Date.now()+b)}}if(Ce(s)){let r=s.id,c=p.get(r);c&&(p.delete(r),c.progressToken!==void 0&&A.delete(c.progressToken));let d=s.result?.protocolVersion;if(d&&(J.has(r)||Z(r))){$=d;try{l?.setProtocolVersion?.(d)}catch{}if(M==null&&Z(r)&&!O.has(r)){let u=s.result??null;u&&_&&(u.instructions=`${u.instructions?u.instructions+`
|
|
4
|
+
|
|
5
|
+
`:""}${_}`),M=u}J.delete(r)}if(O.has(r)){O.delete(r),r===U&&(U=null,oe(s)&&(f=null,i("session-restore: re-bind refused (identity live elsewhere) \u2014 staying unbound")));continue}if(N.has(r)&&(N.delete(r),a.annotateResult?.(s)&&i("get_files: daemon copy unreadable by this OS user \u2014 asked the agent for a destination")),I.has(r)){let u=I.get(r);I.delete(r),oe(s)||(f=u,i("bound identity tracked:",u),de(u))}}n.push(s)}if(n.length){let o=Array.isArray(t)?n:n[0];m.send(o).catch(s=>i("downstream send failed:",String(s)))}},e.onerror=t=>{let n=String(t);if(i("upstream error:",n),!/Maximum reconnection attempts \(\d+\) exceeded/.test(n))return;let o=Date.now();if(o-C<fe){i(`notification stream exhausted again within cooldown \u2014 not escalating (${Math.round((o-C)/1e3)}s since last)`);return}if(C=o,h++,h>X){i(`NOTIFICATION STREAM DEAD \u2014 ${h-1} reconnect escalations exhausted; server\u2192client notifications are NOT arriving`),pe("error",`ours proxy: the server\u2192client notification stream could not be re-established after ${h-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}i(`notification stream exhausted its retries \u2014 escalating to a full reconnect (${h}/${X})`),F(e,"notification stream exhausted")},e.onclose=()=>F(e,"closed")}let Z=e=>w!=null&&w.id===e;async function K(){a.ensureDaemon&&await a.ensureDaemon().catch(t=>i("ensureDaemon:",String(t)));let e=a.transports.createHttpClient(g,{reconnectionOptions:{initialReconnectionDelay:1e3,maxReconnectionDelay:3e4,reconnectionDelayGrowFactor:1.5,maxRetries:5},requestInit:{headers:{"x-ours-lease-token":B,"x-ours-client-pid":String(G),...a.apiToken?{"x-ours-api-token":a.apiToken}:{}}}});if(_e(e),await e.start(),$)try{e.setProtocolVersion?.($)}catch{}l=e}async function ee(e,t){t&&e.id!==void 0&&O.add(e.id),await l.send(e)}async function Se(){if(v||T)return;v=!0;let e=500;for(;;){if(T){v=!1;return}try{if(await K(),w){let n=`${ge}${P}`;J.add(n),await ee({...w,id:n},!0),await l.send({jsonrpc:"2.0",method:"notifications/initialized"})}if(f){let n=`__ours_proxy_rebind_${++P}__`;await ee({jsonrpc:"2.0",id:n,method:"tools/call",params:{name:"choose_identity",arguments:{name:f}}},!0)}E=!0;let t=k.splice(0);for(let n of t)await l.send(n).catch(o=>i("flush failed:",String(o)));i("upstream reconnected",f?`(re-bound "${f}")`:""),h=0,v=!1;return}catch(t){i("reconnect attempt failed:",String(t)),await re(e),e=Math.min(Math.floor(e*1.5),1e4)}}}async function H(e){if(!T){T=!0;try{await l?.close()}catch{}try{await m.close()}catch{}process.exit(e)}}process.on("SIGINT",()=>void H(0)),process.on("SIGTERM",()=>void H(0)),process.on("unhandledRejection",e=>{i("UNHANDLED REJECTION (proxy stays up):",e instanceof Error?e.stack??e.message:String(e))}),process.on("uncaughtException",e=>{i("UNCAUGHT EXCEPTION (proxy stays up):",e?.stack??String(e))});async function Re(){let e=new URL(g.href);e.pathname="/state-dir";let t;try{t=await(await fetch(e,{signal:AbortSignal.timeout(3e3)})).json()}catch(n){i("compat handshake: could not read daemon /state-dir, proceeding:",String(n));return}_=ne({selfVersion:$e,daemonVersion:typeof t?.version=="string"?t.version:null}),_&&i(_)}if((async()=>{a.ensureDaemon&&await a.ensureDaemon().catch(n=>i("ensureDaemon:",String(n))),await Re();let e=500;for(;;)try{await K();break}catch(n){i("initial upstream connect failed, retrying:",String(n)),await re(e),e=Math.min(Math.floor(e*1.5),1e4)}E=!0;let t=k.splice(0);for(let n=0;n<t.length;n++){let o=me();if(!o){k.unshift(...t.slice(n));break}await o.send(t[n]).catch(s=>i("flush failed:",String(s)))}i(`upstream ready \u2014 stdio \u21C4 ${g.href}`)})(),S){le();let e=ue();e&&(f=e,i("session-restore: found prior binding for this session \u2014 will self-recover",`"${e}"`))}else ae&&i("session-restore: disabled via OURS_NO_AUTORESTORE \u2014 pure in-memory binding");await m.start(),i("proxy started (stdio transport up)")}function D(a){return Array.isArray(a)?a:[a]}export{ze as runProxy};
|
package/dist/daemon.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { bootWrapper } from './boot.js';
|
|
2
|
+
export { startDaemon } from './http/server.js';
|
|
3
|
+
export { startupProgress } from './runtime/env.js';
|
|
4
|
+
export type { StartupProgressReporter } from './startup-progress.js';
|
|
5
|
+
export type { DaemonHandle, DaemonOptions, McpIntegration, McpServerLike, McpTransportInit, McpTransportLike, } from './http/server.js';
|
package/dist/daemon.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{a as e}from"./chunk-PCHN744Y.js";import"./chunk-37D5PCFY.js";import"./chunk-V64IUVSS.js";import"./chunk-ZAXRB5MO.js";import"./chunk-UELGY557.js";import"./chunk-KZMPGVQM.js";import"./chunk-AJQIWYXG.js";import"./chunk-NSPYN5TT.js";import"./chunk-VW2KWXSJ.js";import"./chunk-3DQSMLVZ.js";import"./chunk-7UUFYO6G.js";import"./chunk-UM73BGFH.js";import{a as t}from"./chunk-A3SXVUOC.js";import"./chunk-NMYSFQBL.js";import"./chunk-VOYMK2OO.js";import"./chunk-T25JIPX5.js";import"./chunk-HCIVLHKC.js";import"./chunk-NQQ4GSVI.js";import"./chunk-X4RVJ5VL.js";import"./chunk-DIRW7I4S.js";import"./chunk-YRPUM6JG.js";import"./chunk-LKFYUCN7.js";import"./chunk-P55RJGZU.js";import"./chunk-RAGUBE4Y.js";import"./chunk-Q3UVLSCX.js";import{h as r}from"./chunk-HSVIKO4D.js";import"./chunk-ZHH3PWEW.js";import"./chunk-IB2U7K6Y.js";import"./chunk-UJGRFV4J.js";export{t as bootWrapper,e as startDaemon,r as startupProgress};
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export type OursErrorCode = 'NOT_BOUND' | 'BINDING_REASSIGNED' | 'BOUND_IDENTITY_GONE' | 'TEMP_CLOSING' | 'NAME_INVALID' | 'NAME_TAKEN' | 'PROVISION_FAILED' | 'NO_LEASE_HEADERS' | 'NO_LEASE_TOKEN' | 'RANDOM_NAME_EXHAUSTED' | 'NOT_BOUND_NO_NAME' | 'NOT_TEMPORARY' | 'TEMP_OWNED_ELSEWHERE' | 'TEMP_STALE' | 'BOUND_ELSEWHERE' | 'DELETE_PARTIAL' | 'CLOSE_FAILED' | 'ROOT_EXISTS' | 'ROOT_HAS_ROLES' | 'NO_SUCH_IDENTITY' | 'PATH_NOT_ABSOLUTE' | 'WRITE_FAILED' | 'PUBLIC_INVITE_NAMED' | 'INVITE_MALFORMED' | 'NO_POLICY_ARGS' | 'SEND_ARGS' | 'FILE_UNREADABLE' | 'FALLBACK_FAILED' | 'CONNECTOR_TOO_OLD' | 'NO_ROOT' | 'TX_FAILED' | 'INVALID_SELECTION' | 'MALFORMED_ID' | 'DUPLICATE_ID' | 'UNKNOWN_OR_STALE_ID';
|
|
2
|
+
export declare class OursError extends Error {
|
|
3
|
+
readonly code: OursErrorCode;
|
|
4
|
+
constructor(code: OursErrorCode, message: string);
|
|
5
|
+
}
|
|
6
|
+
export declare const errNotBound: () => OursError;
|
|
7
|
+
export declare const errBindingReassigned: () => OursError;
|
|
8
|
+
export declare const errBoundIdentityGone: (name: string) => OursError;
|
|
9
|
+
export declare const errTempClosingBound: (name: string) => OursError;
|
|
10
|
+
export declare const errNameTaken: (tool: string, name: string) => OursError;
|
|
11
|
+
export declare const errNoLeaseHeaders: () => OursError;
|
|
12
|
+
export declare const errRandomNameExhausted: () => OursError;
|
|
13
|
+
export declare const errRootExists: (rootName: string) => OursError;
|
|
14
|
+
export declare const errNotBoundNoName: () => OursError;
|
|
15
|
+
export declare const errNotTemporary: (name: string) => OursError;
|
|
16
|
+
export declare const errTempOwnedElsewhereClose: (name: string, pid: number) => OursError;
|
|
17
|
+
export declare const errTempClosedWithError: (name: string, deleteError: string, remote: string) => OursError;
|
|
18
|
+
export declare const errPathNotAbsolute: (path: string) => OursError;
|
|
19
|
+
export declare const errNoSuchIdentity: (name: string) => OursError;
|
|
20
|
+
export declare const errNoLeaseToken: () => OursError;
|
|
21
|
+
export declare const errTempClosingChoose: (name: string) => OursError;
|
|
22
|
+
export declare const errTempOwnedLive: (name: string, pid: number) => OursError;
|
|
23
|
+
export declare const errTempStale: (name: string, pid: number) => OursError;
|
|
24
|
+
export declare const errBoundElsewhere: (name: string) => OursError;
|
|
25
|
+
export declare const errTempOwnedElsewhereRemove: (name: string, pid: number) => OursError;
|
|
26
|
+
export declare const errIdentityClosedWithError: (name: string, deleteError: string, remote: string) => OursError;
|
|
27
|
+
export declare const errRootHasRoles: (name: string, roles: string[]) => OursError;
|
|
28
|
+
export declare const errIdentityPartiallyRemoved: (name: string, fail: string) => OursError;
|
|
29
|
+
export declare const errPublicInviteNamed: () => OursError;
|
|
30
|
+
export declare const errNoPolicyArgs: () => OursError;
|
|
31
|
+
export declare const errSendFileArgs: () => OursError;
|
|
32
|
+
export declare const errSendFileFilenameRequired: () => OursError;
|
|
33
|
+
export declare const errFileUnreadable: (detail: string) => OursError;
|
|
34
|
+
export declare const errSaveFileFallback: (wireId: string, existsOnDisk: boolean) => OursError;
|
|
35
|
+
export declare const errNoRoot: () => OursError;
|
|
36
|
+
export declare const errInvalidSelection: (cap: number) => OursError;
|
|
37
|
+
export declare const errMalformedId: () => OursError;
|
|
38
|
+
export declare const errDuplicateId: () => OursError;
|
|
39
|
+
export declare const errUnknownOrStaleId: () => OursError;
|
|
40
|
+
export declare const errTool: (tool: string, detail: string, code?: OursErrorCode) => OursError;
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{A,B,C,D,E,F,G,H,I,J,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,z}from"./chunk-UM73BGFH.js";export{a as OursError,c as errBindingReassigned,t as errBoundElsewhere,d as errBoundIdentityGone,H as errDuplicateId,C as errFileUnreadable,v as errIdentityClosedWithError,x as errIdentityPartiallyRemoved,F as errInvalidSelection,G as errMalformedId,f as errNameTaken,g as errNoLeaseHeaders,p as errNoLeaseToken,z as errNoPolicyArgs,E as errNoRoot,o as errNoSuchIdentity,b as errNotBound,j as errNotBoundNoName,k as errNotTemporary,n as errPathNotAbsolute,y as errPublicInviteNamed,h as errRandomNameExhausted,i as errRootExists,w as errRootHasRoles,D as errSaveFileFallback,A as errSendFileArgs,B as errSendFileFilenameRequired,m as errTempClosedWithError,e as errTempClosingBound,q as errTempClosingChoose,l as errTempOwnedElsewhereClose,u as errTempOwnedElsewhereRemove,r as errTempOwnedLive,s as errTempStale,J as errTool,I as errUnknownOrStaleId};
|
package/dist/events.d.ts
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import type { Identity } from './identity/model.js';
|
|
2
|
+
export interface DaemonEvent {
|
|
3
|
+
/** The identity the event belongs to. Resolve sessions from this at FIRE time. */
|
|
4
|
+
identity: string;
|
|
5
|
+
/** The event name — the same string written to notifications.log. */
|
|
6
|
+
event: string;
|
|
7
|
+
/** The content-free record. Shapes for the measured events are below. */
|
|
8
|
+
record: Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
/** `on_message_received` (actor.mu:347) — emitted at +19/+31, saved at +20/+32. */
|
|
11
|
+
export interface MessageReceivedRecord {
|
|
12
|
+
event: 'message_received';
|
|
13
|
+
from: string;
|
|
14
|
+
msg_id: string;
|
|
15
|
+
date: string;
|
|
16
|
+
}
|
|
17
|
+
/** `on_message_received`'s pre-introduction arm (actor.mu:347, emit +19). */
|
|
18
|
+
export interface PendingMessageRecord {
|
|
19
|
+
event: 'pending_message';
|
|
20
|
+
from: string;
|
|
21
|
+
queued: string;
|
|
22
|
+
}
|
|
23
|
+
/** `on_file_received` (actor.mu:399) — emitted at +16, saved at +17. */
|
|
24
|
+
export interface FileReceivedRecord {
|
|
25
|
+
event: 'file_received';
|
|
26
|
+
from: string;
|
|
27
|
+
sender_id: string;
|
|
28
|
+
file_id: string;
|
|
29
|
+
wire_id: string;
|
|
30
|
+
filename: string;
|
|
31
|
+
mime: string;
|
|
32
|
+
bytes: string;
|
|
33
|
+
date: string;
|
|
34
|
+
}
|
|
35
|
+
/** `on_contact_removed` (actor.mu:392) — emit only, there is no state write. */
|
|
36
|
+
export interface ContactRemovedRecord {
|
|
37
|
+
event: 'contact_removed';
|
|
38
|
+
cid: string;
|
|
39
|
+
by: 'local' | 'peer';
|
|
40
|
+
}
|
|
41
|
+
export interface DaemonEventHandlers {
|
|
42
|
+
/**
|
|
43
|
+
* Every structured event appended to notifications.log, delivered
|
|
44
|
+
* SYNCHRONOUSLY at the point of the append.
|
|
45
|
+
*
|
|
46
|
+
* THROWING HERE IS A VETO for the events in VETOABLE_EVENTS: the throw
|
|
47
|
+
* reaches the ADAPT wrapper's action loop, which withholds the transaction's
|
|
48
|
+
* sends and never reaches the `_save_state` entry that follows the emit in the
|
|
49
|
+
* same action list. The arrival is NOT durable when this runs. It is also NOT
|
|
50
|
+
* undone — see "a veto is not a rollback" in the header.
|
|
51
|
+
*
|
|
52
|
+
* For every other event the throw simply propagates to whatever called
|
|
53
|
+
* appendNotifyLog, and TWO OF THOSE CALLERS BITE BACK:
|
|
54
|
+
*
|
|
55
|
+
* `persist_recovered` — emitted inside `saveStateFailClosed`'s own `try`
|
|
56
|
+
* (src/state.ts). A throw there is caught by that function's `catch`,
|
|
57
|
+
* which sets `id.persistFailed = true`. SO THROWING ON persist_recovered
|
|
58
|
+
* QUARANTINES THE IDENTITY — every subsequent mutation is rejected — for a
|
|
59
|
+
* persist failure that did not happen. There is no signal that your
|
|
60
|
+
* handler caused it.
|
|
61
|
+
*
|
|
62
|
+
* `e2e_restore_rejected` — the one event emitted from BOTH sides. Check
|
|
63
|
+
* `record.origin === 'restore'`: that is the boot/restore emit
|
|
64
|
+
* (src/identity/provision.ts), where a throw is an ordinary exception on
|
|
65
|
+
* the restore path. Without that marker you are inside the action loop and
|
|
66
|
+
* a throw is a veto. The marker exists for exactly this question; it is
|
|
67
|
+
* asserted by test/daemon-events.test.mjs so it cannot quietly disappear.
|
|
68
|
+
*
|
|
69
|
+
* WORKED EXAMPLE, because this one is not a footnote. Suppose you register a
|
|
70
|
+
* handler that mirrors every event to an external service and lets errors
|
|
71
|
+
* propagate. The service goes down. Your handler throws on `message_received`,
|
|
72
|
+
* which vetoes that transaction — and the veto returns to the daemon through
|
|
73
|
+
* `on_transaction_failure`, which emits `inbound_error`. Your handler is
|
|
74
|
+
* called again, for the event describing its own veto, and throws again. Every
|
|
75
|
+
* inbound message now costs two throws and lands unacknowledged, and nothing
|
|
76
|
+
* in the logs points at your handler. Catch your own errors unless throwing is
|
|
77
|
+
* the decision you meant to make.
|
|
78
|
+
*/
|
|
79
|
+
event(e: DaemonEvent): void;
|
|
80
|
+
/**
|
|
81
|
+
* The human-readable summary channel — what `setNotifyHook` was.
|
|
82
|
+
*
|
|
83
|
+
* DEFERRED, THEREFORE NOT VETOABLE. All 17 call sites fire inside
|
|
84
|
+
* `process.nextTick` (16 in src/mufl/handlers.ts, one in src/state.ts), so by
|
|
85
|
+
* the time this runs the action loop has finished. A throw here is an
|
|
86
|
+
* UNCAUGHT EXCEPTION that takes the process down — it is not a veto and it is
|
|
87
|
+
* not swallowed. Catch your own errors in this one.
|
|
88
|
+
*
|
|
89
|
+
* The identity name is the only routing key on purpose: a host that resolves a
|
|
90
|
+
* session must do it HERE, at fire time, because a rebind between enqueue and
|
|
91
|
+
* delivery must route to the new session. No session id appears in this
|
|
92
|
+
* contract at all, which is what makes the eager version unrepresentable
|
|
93
|
+
* rather than merely discouraged.
|
|
94
|
+
*/
|
|
95
|
+
notification(identityName: string, summary: string): void;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Events emitted from inside `wireHandlers`' `on_return_data` — i.e. inside the
|
|
99
|
+
* ADAPT wrapper's action loop, where a handler throw is a veto.
|
|
100
|
+
*
|
|
101
|
+
* DERIVED FROM THE SOURCE, NOT MAINTAINED BY HAND: every entry is an
|
|
102
|
+
* `appendNotifyLog` call site in src/mufl/handlers.ts, and
|
|
103
|
+
* test/daemon-events.test.mjs re-derives this set from that file and fails if it
|
|
104
|
+
* drifts. Do not edit it to make a test pass.
|
|
105
|
+
*
|
|
106
|
+
* TWO TRAPS, because "not in this set" does not mean "harmless":
|
|
107
|
+
*
|
|
108
|
+
* 1. `e2e_restore_rejected` is emitted from BOTH src/mufl/handlers.ts (inside
|
|
109
|
+
* the loop — vetoable) and src/identity/provision.ts (at boot — not). The
|
|
110
|
+
* same event name is vetoable or not depending on where it came from, and
|
|
111
|
+
* the record does not say which.
|
|
112
|
+
* 2. `persist_recovered` is emitted inside `saveStateFailClosed`'s own `try`
|
|
113
|
+
* (src/state.ts:127). A handler that throws there is caught by that
|
|
114
|
+
* function's `catch`, which sets `id.persistFailed = true` — so throwing on
|
|
115
|
+
* persist_recovered QUARANTINES THE IDENTITY for a persist failure that did
|
|
116
|
+
* not happen. `persist_failed` (:133) is inside a nested try/catch and a
|
|
117
|
+
* throw there is swallowed entirely.
|
|
118
|
+
*
|
|
119
|
+
* Trap 1 now has an answer rather than only a warning: the boot-side emit
|
|
120
|
+
* carries `origin: 'restore'`, so a handler can tell the two apart. Trap 2 has
|
|
121
|
+
* no such fix and is a genuine footgun; it is repeated on `event` above, at the
|
|
122
|
+
* point where a handler is registered, because that is where it will be read.
|
|
123
|
+
*/
|
|
124
|
+
export declare const VETOABLE_EVENTS: ReadonlySet<string>;
|
|
125
|
+
/**
|
|
126
|
+
* Override one entry. Returns an "uninstall mine, if it is still the installed
|
|
127
|
+
* one" function — closing a daemon must not silently tear down a handler
|
|
128
|
+
* somebody else installed over it afterwards.
|
|
129
|
+
*/
|
|
130
|
+
export declare function setDaemonEventHandler<K extends keyof DaemonEventHandlers>(name: K, handler: DaemonEventHandlers[K]): () => void;
|
|
131
|
+
/** Restore every entry to its neutral default. For tests and daemon teardown. */
|
|
132
|
+
export declare function resetDaemonEventHandlers(): void;
|
|
133
|
+
/** Is this entry still the neutral default? Used by the inertness assertions. */
|
|
134
|
+
export declare function isDefaultHandler<K extends keyof DaemonEventHandlers>(name: K): boolean;
|
|
135
|
+
/**
|
|
136
|
+
* Dispatch a structured event. SYNCHRONOUS AND UNGUARDED ON PURPOSE — the throw
|
|
137
|
+
* is the veto, so there is no try/catch here and there must never be one.
|
|
138
|
+
*
|
|
139
|
+
* Read on every call rather than closed over, so re-installing a handler between
|
|
140
|
+
* one event and the next is honoured.
|
|
141
|
+
*/
|
|
142
|
+
export declare function emitDaemonEvent(id: Identity, record: Record<string, unknown>): void;
|
|
143
|
+
/** Dispatch a summary. Deferred by every caller; see the contract above. */
|
|
144
|
+
export declare function emitDaemonNotification(identityName: string, summary: string): void;
|
package/dist/events.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{a,b,c,d,e,f}from"./chunk-UJGRFV4J.js";export{a as VETOABLE_EVENTS,e as emitDaemonEvent,f as emitDaemonNotification,d as isDefaultHandler,c as resetDaemonEventHandlers,b as setDaemonEventHandler};
|
package/dist/files.d.ts
ADDED
package/dist/files.js
ADDED
package/dist/gc.d.ts
ADDED
package/dist/gc.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{a,b}from"./chunk-ZAXRB5MO.js";import"./chunk-NQQ4GSVI.js";import"./chunk-X4RVJ5VL.js";import"./chunk-DIRW7I4S.js";import"./chunk-YRPUM6JG.js";import"./chunk-LKFYUCN7.js";import"./chunk-P55RJGZU.js";import"./chunk-RAGUBE4Y.js";import"./chunk-Q3UVLSCX.js";import"./chunk-HSVIKO4D.js";import"./chunk-ZHH3PWEW.js";import"./chunk-IB2U7K6Y.js";import"./chunk-UJGRFV4J.js";export{a as startGcTimer,b as stopGcTimer};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import type { SessionContext } from '../api/types.js';
|
|
3
|
+
/** Everything under this prefix belongs to the typed surface. */
|
|
4
|
+
export declare const API_PREFIX = "/api/v1/";
|
|
5
|
+
type ApiHandler = (ctx: SessionContext, body: unknown) => unknown;
|
|
6
|
+
/**
|
|
7
|
+
* The dispatch table — one entry per `OursApi` operation, keyed by its exported
|
|
8
|
+
* name. test/client-parity.test.mjs asserts BOTH directions of completeness:
|
|
9
|
+
* every operation exported from dist/api/*.js appears here, and every key here
|
|
10
|
+
* has a matching method on `OursClient`. Adding an operation without a route,
|
|
11
|
+
* or a route without a client method, is a test failure rather than a silent
|
|
12
|
+
* hole in the remote surface.
|
|
13
|
+
*/
|
|
14
|
+
export declare const API_OPERATIONS: {
|
|
15
|
+
createIdentity: ApiHandler;
|
|
16
|
+
createTemporaryIdentity: ApiHandler;
|
|
17
|
+
closeTemporaryIdentityOp: ApiHandler;
|
|
18
|
+
createRootIdentity: ApiHandler;
|
|
19
|
+
defineLocalIdentityFile: ApiHandler;
|
|
20
|
+
chooseIdentity: ApiHandler;
|
|
21
|
+
listIdentities: ApiHandler;
|
|
22
|
+
currentIdentity: ApiHandler;
|
|
23
|
+
removeIdentity: ApiHandler;
|
|
24
|
+
releaseLease: ApiHandler;
|
|
25
|
+
generateInvite: ApiHandler;
|
|
26
|
+
listInvites: ApiHandler;
|
|
27
|
+
revokeInvite: ApiHandler;
|
|
28
|
+
addContact: ApiHandler;
|
|
29
|
+
listContacts: ApiHandler;
|
|
30
|
+
listLocalContactBook: ApiHandler;
|
|
31
|
+
setLocalBookPolicy: ApiHandler;
|
|
32
|
+
removeContact: ApiHandler;
|
|
33
|
+
renameContact: ApiHandler;
|
|
34
|
+
respondToIntroduction: ApiHandler;
|
|
35
|
+
setBio: ApiHandler;
|
|
36
|
+
advertiseMigrate: ApiHandler;
|
|
37
|
+
setPersona: ApiHandler;
|
|
38
|
+
sendMessage: ApiHandler;
|
|
39
|
+
sendFile: ApiHandler;
|
|
40
|
+
listIncomingMessages: ApiHandler;
|
|
41
|
+
getMessages: ApiHandler;
|
|
42
|
+
deferMessages: ApiHandler;
|
|
43
|
+
listIncomingFiles: ApiHandler;
|
|
44
|
+
getFiles: ApiHandler;
|
|
45
|
+
saveFileFallbackNotice: ApiHandler;
|
|
46
|
+
};
|
|
47
|
+
/** The operation names `POST /api/v1/<op>` accepts. */
|
|
48
|
+
export type ApiOperation = keyof typeof API_OPERATIONS;
|
|
49
|
+
interface ApiSession {
|
|
50
|
+
ctx: SessionContext;
|
|
51
|
+
release(): void;
|
|
52
|
+
}
|
|
53
|
+
export declare function enterApiSession(req: IncomingMessage): ApiSession;
|
|
54
|
+
/**
|
|
55
|
+
* Serve one `POST /api/v1/<operation>`. Owns its own auth check, method check
|
|
56
|
+
* and error handling, so the caller in src/http/server.ts is a single branch
|
|
57
|
+
* that cannot throw into the shared handler.
|
|
58
|
+
*
|
|
59
|
+
* `readBody` is passed in rather than re-implemented: src/http/server.ts holds
|
|
60
|
+
* the one verbatim copy of the baseline parser (index.ts:5095-5109).
|
|
61
|
+
*/
|
|
62
|
+
export declare function serveApiOperation(req: IncomingMessage, res: ServerResponse, pathname: string, readBody: (req: IncomingMessage) => Promise<unknown>): Promise<void>;
|
|
63
|
+
export {};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{a,b,c,d}from"../chunk-UELGY557.js";import"../chunk-KZMPGVQM.js";import"../chunk-AJQIWYXG.js";import"../chunk-NSPYN5TT.js";import"../chunk-VW2KWXSJ.js";import"../chunk-3DQSMLVZ.js";import"../chunk-7UUFYO6G.js";import"../chunk-UM73BGFH.js";import"../chunk-NMYSFQBL.js";import"../chunk-VOYMK2OO.js";import"../chunk-T25JIPX5.js";import"../chunk-HCIVLHKC.js";import"../chunk-NQQ4GSVI.js";import"../chunk-X4RVJ5VL.js";import"../chunk-DIRW7I4S.js";import"../chunk-YRPUM6JG.js";import"../chunk-LKFYUCN7.js";import"../chunk-P55RJGZU.js";import"../chunk-RAGUBE4Y.js";import"../chunk-Q3UVLSCX.js";import"../chunk-HSVIKO4D.js";import"../chunk-ZHH3PWEW.js";import"../chunk-IB2U7K6Y.js";import"../chunk-UJGRFV4J.js";export{b as API_OPERATIONS,a as API_PREFIX,c as enterApiSession,d as serveApiOperation};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { type IncomingMessage, type ServerResponse } from 'node:http';
|
|
2
|
+
import type { OursConfig } from '../config.js';
|
|
3
|
+
import type { SessionContext } from '../api/types.js';
|
|
4
|
+
/**
|
|
5
|
+
* The subset of `McpServer` this daemon touches, described structurally.
|
|
6
|
+
*
|
|
7
|
+
* ONLY WHAT THE SDK ACTUALLY CALLS BELONGS HERE. `sendLoggingMessage` used to be
|
|
8
|
+
* declared too, on the reasoning that pinning the host's contract in one place
|
|
9
|
+
* "keeps the two sides honest". It did the opposite: the SDK never calls it, so
|
|
10
|
+
* nothing here checked the hand-written signature, and it did not match the real
|
|
11
|
+
* class — `McpServer.sendLoggingMessage` takes a narrow `level` UNION where this
|
|
12
|
+
* said `string`. The result was an interface that REJECTED the very class it was
|
|
13
|
+
* written to describe:
|
|
14
|
+
*
|
|
15
|
+
* error TS2322: Type '(ctx: SessionContext) => McpServer' is not assignable to
|
|
16
|
+
* type '(ctx: SessionContext) => McpServerLike'.
|
|
17
|
+
* Types of property 'level' are incompatible.
|
|
18
|
+
* Type 'string' is not assignable to type '"error" | "warning" | …'.
|
|
19
|
+
*
|
|
20
|
+
* ours-mcp hit that on its first attempt to pass a real server to `createServer`.
|
|
21
|
+
* A structural type describing a dependency the SDK does not have can only be
|
|
22
|
+
* validated by a consumer, so it must claim the MINIMUM that makes the SDK work —
|
|
23
|
+
* every extra member is an unchecked guess that can only ever cost a consumer.
|
|
24
|
+
* `server.sendResourceUpdated` stays because the daemon's own session bookkeeping
|
|
25
|
+
* hands it out; `connect`/`close` stay because the daemon calls both.
|
|
26
|
+
*/
|
|
27
|
+
export interface McpServerLike {
|
|
28
|
+
connect(transport: unknown): Promise<void>;
|
|
29
|
+
close(): Promise<void>;
|
|
30
|
+
server: {
|
|
31
|
+
onerror?: (e: Error) => void;
|
|
32
|
+
sendResourceUpdated(a: {
|
|
33
|
+
uri: string;
|
|
34
|
+
}): void;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** The subset of a Streamable-HTTP MCP transport this daemon touches. */
|
|
38
|
+
export interface McpTransportLike {
|
|
39
|
+
readonly sessionId?: string;
|
|
40
|
+
onclose?: () => void;
|
|
41
|
+
handleRequest(req: IncomingMessage, res: ServerResponse, parsedBody?: unknown): Promise<void>;
|
|
42
|
+
close(): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
/** The construction arguments the daemon supplies for each new session. */
|
|
45
|
+
export interface McpTransportInit {
|
|
46
|
+
sessionIdGenerator: () => string;
|
|
47
|
+
onsessioninitialized: (sid: string) => void;
|
|
48
|
+
}
|
|
49
|
+
export interface McpIntegration {
|
|
50
|
+
/**
|
|
51
|
+
* Build the per-session MCP server. `ctx` resolves the session id, lease
|
|
52
|
+
* token and client pid LAZILY — the transport has no session id until the
|
|
53
|
+
* initialize response, and the headers change on every request.
|
|
54
|
+
*/
|
|
55
|
+
createServer(ctx: SessionContext): McpServerLike;
|
|
56
|
+
/** Build the transport. See THE MCP SEAM above for why this is injected. */
|
|
57
|
+
createTransport(init: McpTransportInit): McpTransportLike;
|
|
58
|
+
/**
|
|
59
|
+
* The MCP SDK's `isInitializeRequest`. Optional: without it the daemon uses
|
|
60
|
+
* the zod-free structural check below, which is deliberately lenient about
|
|
61
|
+
* `params` (a stricter re-implementation would risk rejecting a request the
|
|
62
|
+
* real predicate accepts). Hosts that have the MCP SDK should pass the real
|
|
63
|
+
* one so the two sides cannot drift.
|
|
64
|
+
*/
|
|
65
|
+
isInitializeRequest?(body: unknown): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Called the moment a session id EXISTS, with the server built for it.
|
|
68
|
+
*
|
|
69
|
+
* THIS EXISTS BECAUSE ITS ABSENCE WAS A SILENT BUG, and the shape of the bug
|
|
70
|
+
* is worth keeping written down. `createServer(ctx)` runs BEFORE the
|
|
71
|
+
* initialize response, so `ctx.sessionId()` still answers 'pending' there —
|
|
72
|
+
* every host that tried to key its own registry inside createServer keyed
|
|
73
|
+
* nothing. ours-mcp did exactly that, guarded with `if (sid !== 'pending')`,
|
|
74
|
+
* so its serversBySession map stayed EMPTY for the whole life of the daemon
|
|
75
|
+
* and no inbox resource update ever reached an HTTP client. Nothing errored;
|
|
76
|
+
* the notify log printed the same line it prints on success.
|
|
77
|
+
*
|
|
78
|
+
* `onSessionClosed` had no counterpart, which is what made the gap easy to
|
|
79
|
+
* miss — a registry with a teardown hook and no setup hook looks complete.
|
|
80
|
+
* The server is passed rather than left for the host to correlate, because
|
|
81
|
+
* correlating "the server I made most recently" with "the session that just
|
|
82
|
+
* initialized" is a race as soon as two clients connect at once.
|
|
83
|
+
*
|
|
84
|
+
* ours-mcp's test/resource-updated.test.mjs is the end-to-end proof.
|
|
85
|
+
*/
|
|
86
|
+
onSessionInitialized?(sid: string, server: McpServerLike): void;
|
|
87
|
+
/**
|
|
88
|
+
* Called once a session is gone (transport close, or dead-client reap) so the
|
|
89
|
+
* host can drop its own per-session registry. The SDK does not know about
|
|
90
|
+
* ours-mcp's serversBySession map; this is how it stays in step.
|
|
91
|
+
*/
|
|
92
|
+
onSessionClosed?(sid: string): void;
|
|
93
|
+
}
|
|
94
|
+
export interface DaemonOptions {
|
|
95
|
+
/**
|
|
96
|
+
* The resolved runtime config. The SDK's engine modules read their config at
|
|
97
|
+
* MODULE LOAD (src/runtime/env.ts), so passing a different one here cannot
|
|
98
|
+
* retroactively move the state dir or the broker — set OURS_* / config.json
|
|
99
|
+
* BEFORE importing the SDK. Supplying a config that disagrees with the loaded
|
|
100
|
+
* one therefore throws rather than being silently half-applied.
|
|
101
|
+
*/
|
|
102
|
+
config?: OursConfig;
|
|
103
|
+
mcp?: McpIntegration;
|
|
104
|
+
/**
|
|
105
|
+
* The HOST package's version, for the startup line. Without it the daemon
|
|
106
|
+
* announces the SDK's version, which is not the number a user installed.
|
|
107
|
+
*/
|
|
108
|
+
version?: string;
|
|
109
|
+
/**
|
|
110
|
+
* Notification sink. Wired into src/notify.ts's `setNotifyHook`; the third
|
|
111
|
+
* argument is `leases.get(identityName)?.sid ?? null`, RESOLVED WHEN THE
|
|
112
|
+
* CALLBACK FIRES (see the wiring below).
|
|
113
|
+
*/
|
|
114
|
+
onIdentityNotify?(identityName: string, summary: string, boundSessionId: string | null): void;
|
|
115
|
+
}
|
|
116
|
+
export interface DaemonHandle {
|
|
117
|
+
port: number;
|
|
118
|
+
close(): Promise<void>;
|
|
119
|
+
}
|
|
120
|
+
export declare function startDaemon(opts?: DaemonOptions): Promise<DaemonHandle>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{a}from"../chunk-PCHN744Y.js";import"../chunk-37D5PCFY.js";import"../chunk-V64IUVSS.js";import"../chunk-ZAXRB5MO.js";import"../chunk-UELGY557.js";import"../chunk-KZMPGVQM.js";import"../chunk-AJQIWYXG.js";import"../chunk-NSPYN5TT.js";import"../chunk-VW2KWXSJ.js";import"../chunk-3DQSMLVZ.js";import"../chunk-7UUFYO6G.js";import"../chunk-UM73BGFH.js";import"../chunk-A3SXVUOC.js";import"../chunk-NMYSFQBL.js";import"../chunk-VOYMK2OO.js";import"../chunk-T25JIPX5.js";import"../chunk-HCIVLHKC.js";import"../chunk-NQQ4GSVI.js";import"../chunk-X4RVJ5VL.js";import"../chunk-DIRW7I4S.js";import"../chunk-YRPUM6JG.js";import"../chunk-LKFYUCN7.js";import"../chunk-P55RJGZU.js";import"../chunk-RAGUBE4Y.js";import"../chunk-Q3UVLSCX.js";import"../chunk-HSVIKO4D.js";import"../chunk-ZHH3PWEW.js";import"../chunk-IB2U7K6Y.js";import"../chunk-UJGRFV4J.js";export{a as startDaemon};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type Identity } from './model.js';
|
|
2
|
+
export declare function setRootName(name: string | null): void;
|
|
3
|
+
export declare let rootName: string | null;
|
|
4
|
+
export declare function readRootMarker(): string | null;
|
|
5
|
+
export declare function clearRootMarker(): void;
|
|
6
|
+
export interface IdentityInfo {
|
|
7
|
+
bio: string;
|
|
8
|
+
persona: string;
|
|
9
|
+
hasCert: boolean;
|
|
10
|
+
roleId: string;
|
|
11
|
+
rootCid: string;
|
|
12
|
+
rootName: string;
|
|
13
|
+
monitoringEnabled: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function describeIdentity(id: Identity): IdentityInfo;
|
|
16
|
+
export declare function delegateRole(root: Identity, role: Identity): Promise<void>;
|
|
17
|
+
export declare function establishRoot(id: Identity): Promise<{
|
|
18
|
+
adopted: string[];
|
|
19
|
+
failed: string[];
|
|
20
|
+
}>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{a,b,c,d,e,f,g}from"../chunk-HCIVLHKC.js";import"../chunk-NQQ4GSVI.js";import"../chunk-X4RVJ5VL.js";import"../chunk-DIRW7I4S.js";import"../chunk-YRPUM6JG.js";import"../chunk-LKFYUCN7.js";import"../chunk-P55RJGZU.js";import"../chunk-RAGUBE4Y.js";import"../chunk-Q3UVLSCX.js";import"../chunk-HSVIKO4D.js";import"../chunk-ZHH3PWEW.js";import"../chunk-IB2U7K6Y.js";import"../chunk-UJGRFV4J.js";export{d as clearRootMarker,f as delegateRole,e as describeIdentity,g as establishRoot,c as readRootMarker,b as rootName,a as setRootName};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type Identity } from './model.js';
|
|
2
|
+
import type { OursErrorCode } from '../errors.js';
|
|
3
|
+
export interface Lease {
|
|
4
|
+
identity: string;
|
|
5
|
+
token: string;
|
|
6
|
+
pid: number;
|
|
7
|
+
sid: string;
|
|
8
|
+
epoch: number;
|
|
9
|
+
boundAt: number;
|
|
10
|
+
}
|
|
11
|
+
export declare const leases: Map<string, Lease>;
|
|
12
|
+
export declare const tombstones: Set<string>;
|
|
13
|
+
export declare const sessionHeaders: Map<string, {
|
|
14
|
+
token?: string;
|
|
15
|
+
pid?: number;
|
|
16
|
+
}>;
|
|
17
|
+
export declare const outboundRemovalInFlight: Set<string>;
|
|
18
|
+
export declare function pidAlive(pid: number): boolean;
|
|
19
|
+
export declare function leaseByToken(token: string): Lease | undefined;
|
|
20
|
+
export declare function persistBindings(): void;
|
|
21
|
+
type Bound = {
|
|
22
|
+
id: Identity;
|
|
23
|
+
} | {
|
|
24
|
+
error: string;
|
|
25
|
+
code: OursErrorCode;
|
|
26
|
+
};
|
|
27
|
+
export declare function resolveBound(sid: string): Bound;
|
|
28
|
+
export declare function bindSession(sid: string, name: string): void;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,2 @@
|
|
|
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-RAGUBE4Y.js";import"../chunk-Q3UVLSCX.js";import"../chunk-HSVIKO4D.js";import"../chunk-ZHH3PWEW.js";import"../chunk-IB2U7K6Y.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};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type Identity, type TempCloseResult } from './model.js';
|
|
2
|
+
export declare function deleteIdentityCompletely(id: Identity): string | null;
|
|
3
|
+
export declare function closeTemporaryIdentity(id: Identity, cause: string): Promise<TempCloseResult>;
|
|
4
|
+
export declare function sweepStaleTempIdentities(): void;
|
|
5
|
+
export declare function sweepOrphanTempDirs(): void;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{a,b,c,d}from"../chunk-NMYSFQBL.js";import"../chunk-HCIVLHKC.js";import"../chunk-NQQ4GSVI.js";import"../chunk-X4RVJ5VL.js";import"../chunk-DIRW7I4S.js";import"../chunk-YRPUM6JG.js";import"../chunk-LKFYUCN7.js";import"../chunk-P55RJGZU.js";import"../chunk-RAGUBE4Y.js";import"../chunk-Q3UVLSCX.js";import"../chunk-HSVIKO4D.js";import"../chunk-ZHH3PWEW.js";import"../chunk-IB2U7K6Y.js";import"../chunk-UJGRFV4J.js";export{b as closeTemporaryIdentity,a as deleteIdentityCompletely,d as sweepOrphanTempDirs,c as sweepStaleTempIdentities};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { AdaptWrapper, AdaptPacketWrapper } from '@adapt-toolkit/sdk/wrappers';
|
|
2
|
+
import type { AdaptValue } from '@adapt-toolkit/sdk/backend';
|
|
3
|
+
type Pending = {
|
|
4
|
+
resolve: (v: AdaptValue) => void;
|
|
5
|
+
reject: (e: Error) => void;
|
|
6
|
+
timer: ReturnType<typeof setTimeout>;
|
|
7
|
+
};
|
|
8
|
+
export interface TempMeta {
|
|
9
|
+
owner: {
|
|
10
|
+
tokenHash: string;
|
|
11
|
+
pid: number;
|
|
12
|
+
};
|
|
13
|
+
createdAt: number;
|
|
14
|
+
closing?: Promise<TempCloseResult>;
|
|
15
|
+
}
|
|
16
|
+
export interface TempCloseResult {
|
|
17
|
+
attempted: number;
|
|
18
|
+
notified: number;
|
|
19
|
+
failed: number;
|
|
20
|
+
deleteError: string | null;
|
|
21
|
+
}
|
|
22
|
+
export interface Identity {
|
|
23
|
+
name: string;
|
|
24
|
+
cid: string;
|
|
25
|
+
pw: AdaptPacketWrapper;
|
|
26
|
+
dir: string;
|
|
27
|
+
pending: Pending[];
|
|
28
|
+
lock: Promise<void>;
|
|
29
|
+
persistFailed?: boolean;
|
|
30
|
+
temp?: TempMeta;
|
|
31
|
+
}
|
|
32
|
+
export declare let wrapper: AdaptWrapper;
|
|
33
|
+
export declare function setWrapper(w: AdaptWrapper): void;
|
|
34
|
+
export declare const identities: Map<string, Identity>;
|
|
35
|
+
export declare let registrar: Identity | null;
|
|
36
|
+
export declare let registrarAdBlob: Buffer | null;
|
|
37
|
+
export declare function setRegistrar(id: Identity | null): void;
|
|
38
|
+
export declare function setRegistrarAdBlob(blob: Buffer | null): void;
|
|
39
|
+
export declare const identityDir: (name: string) => string;
|
|
40
|
+
export declare const keyPath: (dir: string) => string;
|
|
41
|
+
export declare const dataPath: (dir: string) => string;
|
|
42
|
+
export declare const notifyLogPath: (dir: string) => string;
|
|
43
|
+
export declare const unreadPath: (dir: string) => string;
|
|
44
|
+
export declare const filesDirFor: (id: Identity) => string;
|
|
45
|
+
export declare const tempMetaPath: (dir: string) => string;
|
|
46
|
+
export declare const hashLeaseToken: (token: string) => string;
|
|
47
|
+
export declare function writeTempMetaFile(dir: string, meta: {
|
|
48
|
+
owner: {
|
|
49
|
+
tokenHash: string;
|
|
50
|
+
pid: number;
|
|
51
|
+
};
|
|
52
|
+
createdAt: number;
|
|
53
|
+
}): void;
|
|
54
|
+
export declare function readTempMetaFile(dir: string): {
|
|
55
|
+
owner: {
|
|
56
|
+
tokenHash: string;
|
|
57
|
+
pid: number;
|
|
58
|
+
};
|
|
59
|
+
createdAt: number;
|
|
60
|
+
} | null;
|
|
61
|
+
export declare function tightenIdentityPerms(): void;
|
|
62
|
+
export declare const isWireId: (s: string) => boolean;
|
|
63
|
+
export declare const isSelectableWireId: (s: string) => boolean;
|
|
64
|
+
export declare const FILE_SELECTION_CAP = 32;
|
|
65
|
+
export declare function findIdentityFile(id: Identity, wireId: string): string | null;
|
|
66
|
+
export declare function listPersistedNames(): string[];
|
|
67
|
+
export {};
|
|
@@ -0,0 +1,2 @@
|
|
|
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}from"../chunk-Q3UVLSCX.js";import"../chunk-HSVIKO4D.js";import"../chunk-ZHH3PWEW.js";import"../chunk-IB2U7K6Y.js";export{u as FILE_SELECTION_CAP,j as dataPath,m as filesDirFor,v as findIdentityFile,o as hashLeaseToken,c as identities,h as identityDir,t as isSelectableWireId,s as isWireId,i as keyPath,w as listPersistedNames,k as notifyLogPath,q as readTempMetaFile,d as registrar,e as registrarAdBlob,f as setRegistrar,g as setRegistrarAdBlob,b as setWrapper,n as tempMetaPath,r as tightenIdentityPerms,l as unreadPath,a as wrapper,p as writeTempMetaFile};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type Identity } from './model.js';
|
|
2
|
+
export declare function createPacket(name: string, seed: string, dir: string, track?: boolean, signingSecret?: string, deferExposure?: boolean): Promise<Identity>;
|
|
3
|
+
export declare const reservedNames: Set<string>;
|
|
4
|
+
export declare function provisionIdentity(name: string, opts?: {
|
|
5
|
+
exposeLocal: boolean;
|
|
6
|
+
localAutoAccept: boolean;
|
|
7
|
+
temp?: {
|
|
8
|
+
tokenHash: string;
|
|
9
|
+
pid: number;
|
|
10
|
+
};
|
|
11
|
+
}): Promise<Identity>;
|
|
12
|
+
export declare function restoreIdentity(name: string): Promise<Identity>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{w as a,x as b,y as c,z as d}from"../chunk-NQQ4GSVI.js";import"../chunk-X4RVJ5VL.js";import"../chunk-DIRW7I4S.js";import"../chunk-YRPUM6JG.js";import"../chunk-LKFYUCN7.js";import"../chunk-P55RJGZU.js";import"../chunk-RAGUBE4Y.js";import"../chunk-Q3UVLSCX.js";import"../chunk-HSVIKO4D.js";import"../chunk-ZHH3PWEW.js";import"../chunk-IB2U7K6Y.js";import"../chunk-UJGRFV4J.js";export{a as createPacket,c as provisionIdentity,b as reservedNames,d as restoreIdentity};
|