@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,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{a as E,b as k,d as A}from"./chunk-HCIVLHKC.js";import{E as T,F as I,G as _,J as R,S as x,x as y}from"./chunk-NQQ4GSVI.js";import{a as S}from"./chunk-X4RVJ5VL.js";import{a as l,d as u,e as d,g as w}from"./chunk-RAGUBE4Y.js";import{a as $,c as m,q as v}from"./chunk-Q3UVLSCX.js";import{c as s,i as r}from"./chunk-HSVIKO4D.js";import{join as b}from"node:path";import*as i from"node:fs";function D(e){try{$.remove_packet(e.cid)}catch(t){r(`remove_packet(${e.cid}) failed:`,String(t))}m.delete(e.name);try{x(e)}catch(t){r(`failed to unpublish "${e.name}" from the contact book:`,String(t))}l.has(e.name)&&(l.delete(e.name),w()),e.name===k&&(E(null),A());try{i.rmSync(e.dir,{recursive:!0,force:!0}),y.delete(e.name)}catch(t){return`deleting ${e.dir} failed: ${String(t)}`}return null}function F(e,t){let n=e.temp;return n?(n.closing||(n.closing=(async()=>{r(`[${e.name}] closing temporary identity (${t})`);let o=[];try{o=T(a=>S(_(e,"::a2a_messaging::list_contacts",a)))}catch(a){r(`[${e.name}] contact snapshot failed during close (continuing with local cleanup):`,String(a))}let p=0,c=0;u.add(e.name);try{for(let a of o)try{await I(async C=>{let h=(await R(e,"::a2a_messaging::remove_contact",{contact:a.container_id},C)).Reduce("notified");return h.IsNil()?!1:h.GetBoolean()})?p++:c++}catch(g){c++,r(`[${e.name}] remove-me to ${a.container_id} failed (continuing):`,String(g))}}finally{u.delete(e.name)}let f=D(e);return f?r(`[${e.name}] temporary identity close: LOCAL DELETE FAILED \u2014 ${f}`):r(`[${e.name}] temporary identity closed: ${o.length} contact(s), ${p} remove-me notice(s) queued, ${c} not sent (delivery unverified by design)`),{attempted:o.length,notified:p,failed:c,deleteError:f}})()),n.closing):Promise.reject(new Error(`identity "${e.name}" is not temporary`))}function H(){for(let e of[...m.values()]){let t=e.temp;if(!t||t.closing||d(t.owner.pid))continue;let n=l.get(e.name);n&&d(n.pid)||F(e,`stale lease \u2014 owner pid ${t.owner.pid} is dead`).catch(o=>r(`[${e.name}] stale-temp reclaim failed:`,String(o)))}}function J(){if(i.existsSync(s))for(let e of i.readdirSync(s,{withFileTypes:!0})){if(!e.isDirectory()||m.has(e.name))continue;let t=b(s,e.name),n=v(t);if(!(!n||d(n.owner.pid)))try{i.rmSync(t,{recursive:!0,force:!0}),y.delete(e.name),r(`[${e.name}] removed orphaned temporary-identity dir (owner pid ${n.owner.pid} dead, no live packet)`)}catch(o){r(`[${e.name}] failed to remove orphaned temporary-identity dir:`,String(o))}}}export{D as a,F as b,H as c,J as d};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{c as pe}from"./chunk-X4RVJ5VL.js";import{b as M}from"./chunk-YRPUM6JG.js";import{a as de}from"./chunk-LKFYUCN7.js";import{d as ce}from"./chunk-RAGUBE4Y.js";import{a as j,c as N,d as b,e as W,f as ne,g as oe,h as J,i as O,j as k,k as L,l as B,p as se,w as ae}from"./chunk-Q3UVLSCX.js";import{c as T,i as l,o as F,p as re}from"./chunk-HSVIKO4D.js";import{b as ue,e as le,f as fe}from"./chunk-UJGRFV4J.js";import{join as be}from"node:path";import*as _ from"node:fs";import{AdaptObjectLifetime as Re}from"@adapt-toolkit/sdk/common";import{object_to_adapt_value as $e}from"@adapt-toolkit/sdk/wrapper";import*as m from"node:fs";import{randomBytes as Ve}from"node:crypto";import*as $ from"node:fs";import{randomBytes as Ie}from"node:crypto";import{PacketWrapperConfigurator as Te}from"@adapt-toolkit/sdk/wrappers";import{AdaptObjectLifetime as Ne}from"@adapt-toolkit/sdk/common";function He(e){let t=[],s=e.Reduce("degraded");if(s.IsNil())return t;for(let r=0;;r++){let a=s.Reduce(r);if(a.IsNil())break;t.push({cid:a.Reduce("container_id").Visualize(),name:a.Reduce("name").Visualize(),attempts:Number(a.Reduce("attempts").Visualize()),queued:Number(a.Reduce("queued").Visualize())})}return t}function ke(e){let t=[],s=e.Reduce("queues");if(s.IsNil())return t;for(let r=0;;r++){let a=s.Reduce(r);if(a.IsNil())break;t.push({cid:a.Reduce("container_id").Visualize(),queued:Number(a.Reduce("queued").Visualize()),degraded:a.Reduce("degraded").GetBoolean()})}return t}async function K(e,t){try{let s=await w(async r=>{let a=await h(e,"::a2a_messaging::flush_deferred",{contact:t},r);return Number(a.Reduce("flushed").Visualize())});s>0&&l(`[${e.name}] flushed ${s} deferred message(s) to ${t.slice(0,12)}\u2026`)}catch(s){l(`[${e.name}] deferred flush to ${t.slice(0,12)}\u2026 failed:`,String(s))}}async function me(e){try{let t=await w(async r=>{let a=await h(e,"::a2a_messaging::restore_degraded_contacts",{},r);return Number(a.Reduce("requested").Visualize())});t>0&&l(`[${e.name}] contact restore requested for ${t} degraded contact(s)`);let s=S(r=>ke(R(e,"::a2a_messaging::list_deferred_queues",r)));for(let r of s)r.degraded||await K(e,r.cid)}catch(t){l(`[${e.name}] contact-restore sweep failed:`,String(t))}}async function xe(e){try{let t=await w(async s=>{let r=await h(e,"::a2a_messaging::reconcile_advertise",{},s),a=d=>r.Reduce(d).IsNil()?0:Number(r.Reduce(d).Visualize());return{changed:/true/i.test(r.Reduce("changed").Visualize()),capabilityAdvertised:a("capability_advertised"),legacyReadvertised:a("legacy_readvertised")}});(t.capabilityAdvertised>0||t.legacyReadvertised>0)&&l(`[${e.name}] capability reconcile: changed=${t.changed} advertised=${t.capabilityAdvertised} legacy_migration_bootstrap=${t.legacyReadvertised}`)}catch(t){l(`[${e.name}] capability reconcile sweep failed:`,String(t))}}var G=new Set;function H(e){if(!G.has(e.name)){G.add(e.name);for(let t of[2e3,15e3])setTimeout(()=>{t===15e3&&G.delete(e.name);let s=N.get(e.name);s&&xe(s)},t)}}async function qe(e){try{let t=await w(async s=>{let r=await h(e,"::a2a_messaging::readvertise_e2e_recovery",{},s);return Number(r.Reduce("readvertised").Visualize())});t>0&&l(`[${e.name}] re-advertised fresh AD to ${t} e2e contact(s) (session recovery)`)}catch(t){l(`[${e.name}] e2e recovery re-advertise failed:`,String(t))}try{await w(async t=>{await h(e,"::a2a_messaging::sweep_e2e_migrations",{},t)})}catch(t){l(`[${e.name}] e2e migration sweep failed:`,String(t))}try{let t=await w(async s=>{let r=await h(e,"::a2a_messaging::redrive_unacked_sweep",{},s),a=d=>r.Reduce(d).IsNil()?0:Number(r.Reduce(d).Visualize());return{redriven:a("redriven_contacts"),purged:a("purged_contacts"),deferred:a("deferred_contacts")}});(t.redriven>0||t.purged>0||t.deferred>0)&&l(`[${e.name}] unacked sweep: redriven=${t.redriven} ttl_purged=${t.purged} deferred=${t.deferred} contact(s)`)}catch(t){l(`[${e.name}] unacked redrive sweep failed:`,String(t))}}function ge(e,t){e.pw.on_return_data=s=>{let r=new Ne;s.Attach(r);try{let a=s.Reduce("kind").Visualize();if(a==="save_state"){z(e);return}if(a==="notify_agent"){let i=s.Reduce("payload"),f=i.Reduce("event").Visualize();if(f==="message_received"){let o=i.Reduce("sender_name").Visualize(),n=i.Reduce("msg_id").Visualize(),c=i.Reduce("date").Visualize();g(e,{event:"message_received",from:o,msg_id:n,date:c}),P(e),process.nextTick(()=>t.onNotify(e.name,`[${e.name}] new message from ${o} (#${n})`))}else if(f==="file_received"){let o=i.Reduce("sender_name").Visualize(),n=i.Reduce("sender_id").Visualize(),c=i.Reduce("file_id").Visualize(),u=i.Reduce("wire_id").Visualize(),p=i.Reduce("filename").Visualize(),y=i.Reduce("mime").Visualize(),v=i.Reduce("bytes").Visualize(),I=i.Reduce("date").Visualize();g(e,{event:"file_received",from:o,sender_id:n,file_id:c,wire_id:u,filename:p,mime:y,bytes:v,date:I}),P(e),process.nextTick(()=>t.onNotify(e.name,`[${e.name}] new file ${p} (${v} B) from ${o} (sender_id ${n}, file_id ${c}, wire_id ${u})`))}else if(f==="contact_accepted"){let o=i.Reduce("name").Visualize(),n=i.Reduce("container_id").Visualize();H(e),process.nextTick(()=>t.onNotify(e.name,`[${e.name}] contact "${o}" (${n}) accepted your invite.`))}else if(f==="local_contact_added"){let o=i.Reduce("name").Visualize(),n=i.Reduce("container_id").Visualize();H(e),process.nextTick(()=>t.onNotify(e.name,`[${e.name}] local contact "${o}" (${n}) connected via the contact book.`))}else if(f==="contact_name_collision"){let o=i.Reduce("message").Visualize(),n=i.Reduce("desired").Visualize(),c=i.Reduce("assigned").Visualize(),u=i.Reduce("existing_container_id").Visualize(),p=i.Reduce("container_id").Visualize();g(e,{event:"contact_name_collision",desired:n,assigned:c,existing_container_id:u,container_id:p}),l(`[${e.name}] CONTACT NAME COLLISION \u2014 ${o}`),process.nextTick(()=>t.onNotify(e.name,`[${e.name}] \u26A0 ${o}`))}else if(f==="sibling_contact_added"){let o=i.Reduce("name").Visualize(),n=i.Reduce("container_id").Visualize();g(e,{event:"sibling_contact_added",from:o}),H(e),process.nextTick(()=>t.onNotify(e.name,`[${e.name}] sibling "${o}" (${n}) connected (intra-root auto-accept).`))}else if(f==="local_contact_request"){let o=i.Reduce("name").Visualize(),n=i.Reduce("container_id").Visualize();g(e,{event:"local_contact_request",from:o}),process.nextTick(()=>t.onNotify(e.name,`[${e.name}] pending local introduction from "${o}" (${n}) \u2014 approve or reject with respond_to_introduction.`))}else if(f==="pending_message"){let o=i.Reduce("sender_name").Visualize(),n=i.Reduce("queued").Visualize();g(e,{event:"pending_message",from:o,queued:n}),process.nextTick(()=>t.onNotify(e.name,`[${e.name}] "${o}" queued a message awaiting introduction approval (${n} queued).`))}else if(f==="e2e_restore_rejected")g(e,{event:"e2e_restore_rejected"}),l(`[${e.name}] E2E RESTORE REJECTED \u2014 corrupt session blob failed pickle_key validation; reset to empty e2e state, self-heal fallback will re-establish`),process.nextTick(()=>t.onNotify(e.name,`[${e.name}] persisted e2e sessions were corrupt \u2014 rejected cleanly, sessions re-establishing`));else if(f==="contact_restored"){let o=i.Reduce("name").Visualize(),n=i.Reduce("container_id").Visualize();g(e,{event:"contact_restored",from:o}),l(`[${e.name}] contact "${o}" restored (re-keyed)`),process.nextTick(()=>void K(e,String(n)))}else if(f==="migration_active"){let o=i.Reduce("cid").Visualize(),n=i.Reduce("role").Visualize(),c=V(i,"epoch"),u=V(i,"session_id");g(e,{event:"migration_active",cid:String(o),role:String(n),...c?{epoch:c}:{},...u?{session_id:u}:{}}),l(`[migration] active cid=${o} role=${n}${c?` epoch=${c}`:""}${u?` session_id=${u}`:""}`)}else if(f==="e2e_app_send"){let o=i.Reduce("cid").Visualize(),n=V(i,"session_id"),c=i.Reduce("olm_type").Visualize(),u=i.Reduce("wire_id").Visualize(),p=i.Reduce("retained").IsNil()?void 0:i.Reduce("retained").GetBoolean(),y=[],v=i.Reduce("evicted");if(!v.IsNil())for(let I=0;;I++){let ie=v.Reduce(I);if(ie.IsNil())break;y.push(String(ie.Visualize()))}g(e,{event:"e2e_app_send",cid:String(o),session_id:n,olm_type:String(c),wire_id:String(u),...p===!1?{retained:!1}:{},...y.length?{evicted:y}:{}}),l(`[${e.name}] [e2e-app] send cid=${o} session_id=${n} olm_type=${c} wire_id=${u}${p===!1?" retained=false":""}${y.length?` evicted=${y.join(",")}`:""}`),y.length&&process.nextTick(()=>t.onNotify(e.name,`[${e.name}] redrive window overflow: ${y.length} older unacked send(s) lost their auto-resend guarantee (${y.join(", ")})`))}else if(f==="dedup_degraded"){let o=i.Reduce("cid").Visualize(),n=i.Reduce("dropped_wire_id").Visualize();g(e,{event:"dedup_degraded",cid:String(o),dropped_wire_id:String(n)}),l(`[${e.name}] [e2e-app] DEDUP DEGRADED cid=${o} dropped_wire_id=${n} (storage ceiling \u2014 a late redrive of that id could re-deposit)`),process.nextTick(()=>t.onNotify(e.name,`[${e.name}] dedup window overflowed for ${String(o).slice(0,12)}\u2026 \u2014 one oldest entry dropped (guarantee loss surfaced)`))}else if(f==="e2e_delivery_expired"){let o=i.Reduce("cid").Visualize(),n=[],c=i.Reduce("wire_ids");if(!c.IsNil())for(let u=0;;u++){let p=c.Reduce(u);if(p.IsNil())break;n.push(String(p.Visualize()))}g(e,{event:"e2e_delivery_expired",cid:String(o),wire_ids:n}),l(`[${e.name}] [e2e-app] delivery EXPIRED (2-day TTL, receipt never arrived) cid=${o} wire_ids=${n.join(",")}`),process.nextTick(()=>t.onNotify(e.name,`[${e.name}] ${n.length} message(s)/file(s) to ${String(o).slice(0,12)}\u2026 expired undelivered (no receipt within 2 days)`))}else if(f==="e2e_app_recv"){let o=i.Reduce("cid").Visualize(),n=V(i,"session_id"),c=i.Reduce("ok").GetBoolean(),u=i.Reduce("wire_id").Visualize(),p=i.Reduce("code").IsNil()?void 0:String(i.Reduce("code").Visualize()),y=!i.Reduce("duplicate").IsNil(),v=!i.Reduce("file").IsNil();g(e,{event:"e2e_app_recv",cid:String(o),session_id:n,ok:c,wire_id:String(u),...p?{code:p}:{},...y?{duplicate:!0}:{},...v?{file:!0}:{}}),l(`[${e.name}] [e2e-app] recv cid=${o} session_id=${n} ok=${c} wire_id=${u}${p?` code=${p}`:""}${y?" duplicate=true":""}${v?" file=true":""}`)}else if(f==="e2e_rekey"){let o=i.Reduce("cid").Visualize(),n=i.Reduce("role").Visualize(),c=V(i,"session_id"),u=i.Reduce("attempts").IsNil()?void 0:String(i.Reduce("attempts").Visualize()),p=i.Reduce("peer_supports").IsNil()?void 0:String(i.Reduce("peer_supports").Visualize()),y=i.Reduce("rejected").IsNil()?void 0:String(i.Reduce("rejected").Visualize());g(e,{event:"e2e_rekey",cid:String(o),role:String(n),...c?{session_id:c}:{},...u?{attempts:u}:{},...p?{peer_supports:p}:{},...y?{rejected:y}:{}}),l(`[${e.name}] [e2e-rekey] cid=${o} role=${n}${c?` session_id=${c}`:""}${u?` attempts=${u}`:""}${p?` peer_supports=${p}`:""}${y?` rejected=${y}`:""}`)}else if(f==="migration_deferred_flush"){let o=i.Reduce("cid").Visualize(),n=i.Reduce("wire_id").Visualize();g(e,{event:"migration_deferred_flush",cid:String(o),wire_id:String(n)}),l(`[migration] flush-notify cid=${o} wire_id=${n} (deferred\u2192e2e; core delivers)`)}else if(f==="migration_stalled"){let o=i.Reduce("cid").Visualize(),n=i.Reduce("phase").Visualize(),c=i.Reduce("attempts").Visualize();g(e,{event:"migration_stalled",cid:String(o),phase:String(n),attempts:String(c)}),l(`[migration] stalled-notify cid=${o} phase=${n} attempts=${c} (core re-drives via sweep)`)}else if(f==="downgrade_refused"){let o=i.Reduce("cid").Visualize(),n=i.Reduce("wire_id"),c=n.IsNil()?"":String(n.Visualize());g(e,{event:"downgrade_refused",cid:String(o),...c?{wire_id:c}:{}}),l(`[e2e-route] downgrade-dropped cid=${o}${c?` wire_id=${c}`:""} (legacy plaintext from a migrated peer \u2014 dropped by core)`),process.nextTick(()=>t.onNotify(e.name,`[${e.name}] a message from a migrated contact was rejected as an unsafe downgrade (dropped).`))}else if(f==="contact_removed"){let o=String(i.Reduce("cid").Visualize()),n=ce.has(e.name);g(e,{event:"contact_removed",cid:o,by:n?"local":"peer"}),n||(l(`[${e.name}] contact ${o} removed you (authenticated peer removal notice) \u2014 dropped from contacts`),process.nextTick(()=>t.onNotify(e.name,`[${e.name}] contact ${o.slice(0,12)}\u2026 removed you as a contact (the removal was applied locally too).`)))}else if(f==="monitoring_disabled"){let o=String(i.Reduce("cid").Visualize()),n=i.Reduce("cause"),c=n.IsNil()?"":String(n.Visualize());g(e,{event:"monitoring_disabled",cid:o,...c?{cause:c}:{}}),l(`[${e.name}] monitoring disabled (cid=${o}${c?` cause=${c}`:""})`),process.nextTick(()=>t.onNotify(e.name,`[${e.name}] the monitoring/control-plane binding was disabled${c==="control_plane_removed_contact"?" \u2014 the control plane removed you as a contact":""}.`))}else(f==="control_request"||f==="host_provision_child"||f==="host_destroy_child"||f==="host_mint_child_invite"||f==="host_set_child_monitoring")&&l(`[${e.name}] ${f}: the daemon-side control plane is removed \u2014 ignoring`);return}let d=e.pending.shift();if(!d)return;clearTimeout(d.timer),d.resolve(s.Reduce("payload").Detach())}finally{r.Finalize()}},e.pw.on_transaction_failure=s=>{let r=e.pending.shift();r?(clearTimeout(r.timer),r.reject(new Error(s))):(l(`[${e.name}] inbound transaction rejected:`,s),g(e,{event:"inbound_error",message:s}),process.nextTick(()=>t.onNotify(e.name,`[${e.name}] inbound transaction rejected: ${s}`)))}}import{join as X}from"node:path";import*as x from"node:fs";var E=()=>X(T,F),Q=()=>X(E(),"registrar.key"),Y=()=>X(E(),"book.json");function ye(){try{let e=JSON.parse(x.readFileSync(Y(),"utf8"));return e&&typeof e.entries=="object"?e.entries:{}}catch{return{}}}function _e(e){x.mkdirSync(E(),{recursive:!0});let t=`${Y()}.tmp`;x.writeFileSync(t,JSON.stringify({v:1,entries:e},null,2),{mode:384}),x.renameSync(t,Y())}function Z(e){return S(t=>Buffer.from(R(e,"::actor::export_address_document",t).GetBinary()))}function q(e){return S(t=>Buffer.from(R(e,"::actor::export_signing_secret",t).Serialize()).toString("hex"))}async function we(e){if(!b)throw new Error("registrar is not available");let t=Z(e),s=await w(async a=>{let d=await h(b,"::actor::sign_book_entry",{name:e.name,ad:b.pw.packet.NewBinaryFromBuffer(t).Attach(a)},a);return Buffer.from(d.Reduce("sig").GetBinary()).toString("base64url")}),r=ye();r[e.name]={v:1,name:e.name,container_id:e.cid,address_document:t.toString("base64url"),published_at:new Date().toISOString(),registrar_sig:s},_e(r),l(`[${e.name}] published to the local contact book`)}function it(e){let t=ye(),s=Object.entries(t).find(([,r])=>r.container_id===e.cid);s&&(delete t[s[0]],_e(t),l(`[${e.name}] removed from the local contact book (entry "${s[0]}")`))}async function he(e){if(!W)throw new Error("registrar is not available");await w(async t=>{await h(e,"::actor::pin_registrar",{registrar_ad:e.pw.packet.NewBinaryFromBuffer(W).Attach(t)},t)})}function C(e,t,s,r=!0,a,d=!1){let i=new Te;i.deferred_exposure=d;let f=["--unit_hash",M.hash,"--seed_phrase",t,"--unit_dir_path",M.dir];return a&&f.push("--init_trn_argument",JSON.stringify(a)),i.process_arguments(f),new Promise((o,n)=>{let c=setTimeout(()=>n(new Error(`packet creation for "${e}" timed out`)),3e4);j.packet_manager.create_packet(i,u=>{clearTimeout(c);let p={name:e,cid:S(y=>u.packet.GetContainerID().Attach(y).Visualize()),pw:u,dir:s,pending:[],lock:Promise.resolve()};ge(p,ve),r&&N.set(e,p),l(`[${e}] packet created \u2014 container id ${p.cid}`),o(p)},M.contents)})}var A=new Set(ae());A.size>0&&l(`reserved ${A.size} persisted identity name(s) at module load: ${[...A].join(", ")}`);async function gt(e,t={exposeLocal:!0,localAutoAccept:!0}){if(A.has(e)||N.has(e))throw new Error(`identity name "${e}" is reserved \u2014 a persisted identity with this name is restoring, present, or being provisioned; refusing to provision over it`);A.add(e);try{let s=J(e);$.mkdirSync(s,{recursive:!0,mode:448});let r;t.temp&&(r={owner:{tokenHash:t.temp.tokenHash,pid:t.temp.pid},createdAt:Date.now()},se(s,r));let a=Ie(24).toString("hex"),d=await C(e,a,s);return r&&(d.temp=r),$.writeFileSync(O(s),q(d),{mode:384}),await w(async i=>{await h(d,"::a2a_messaging::set_my_name",{name:e},i)}),await he(d),t.localAutoAccept||await w(async i=>{await h(d,"::actor::set_local_policy",{auto_accept:!1},i)}),t.exposeLocal&&await we(d),z(d),d}catch(s){throw A.delete(e),s}}async function yt(e){let t=J(e),s=$.readFileSync(O(t),"utf8").trim(),r=await C(e,"",t,!1,s,!0);l(`[${e}] created QUARANTINED (no routing/broker registration, not client-bindable) \u2014 importing state before exposure`);let a=Number(process.env.OURS_TEST_RESTORE_HOLD_MS||"")||0;a>0&&(l(`[${e}] TEST HOLD: keeping restore open ${a}ms (OURS_TEST_RESTORE_HOLD_MS)`),await new Promise(o=>setTimeout(o,a)));let d=o=>/timed out waiting for the transaction result/.test(String(o)),i=(o,n,c)=>{l(`[${e}] ${o} ${n} \u2014 identity left UNEXPOSED and UNTRACKED (fail-closed)`);try{g(r,{event:"restore_fail_closed",step:o,error:String(c).slice(0,300)})}catch{}N.delete(e);try{j.remove_packet(r.cid)}catch(u){l(`[${e}] quarantined-packet teardown failed:`,String(u))}throw new Error(`identity "${e}": ${o} failed during restore (${n}) \u2014 left unexposed (fail-closed)`)},f=(o,n)=>i(o,"outcome UNKNOWN (timeout): the transaction may still execute and exposure would race it",n);if(Se(t)){let o=!1;try{if(process.env.OURS_TEST_FORCE_IMPORT_TIMEOUT==="1")throw new Error("timed out waiting for the transaction result (forced by OURS_TEST_FORCE_IMPORT_TIMEOUT)");let n=$.readFileSync(k(t));await w(async c=>{let u=r.pw.packet.ParseValue(new Uint8Array(n)).Attach(c),p=Number(process.env.OURS_IMPORT_TIMEOUT_MS||"")||void 0;await h(r,"::actor::import_state",u,c,p)}),o=!0,l(`[${e}] state import completed (positively observed)`)}catch(n){d(n)&&f("import_state",n),l(`[${e}] FAILED TO IMPORT SAVED STATE \u2014 continuing with the reseeded identity; surviving contacts (if the blob was partially migrated) self-heal via contact restore:`,String(n)),g(r,{event:"state_import_failed",error:String(n).slice(0,300)});try{let c=`${k(t)}.failed-${Date.now()}`;$.renameSync(k(t),c),$.chmodSync(c,384),l(`[${e}] unreadable state blob preserved as state_data.bin.failed-*`)}catch{}}if(o){try{let u=await w(async p=>{let y=await h(r,"::a2a_messaging::commit_e2e_restore",{},p),v=y.Reduce("status").Visualize(),I=y.Reduce("sessions").IsNil()?"0":y.Reduce("sessions").Visualize();return{status:String(v),sessions:String(I)}});l(`[${e}] e2e restore commit: status=${u.status} sessions=${u.sessions}`)}catch(u){d(u)&&f("commit_e2e_restore",u),l(`[${e}] E2E RESTORE REJECTED \u2014 staged session blob failed pickle_key validation; discarding it, fresh account + self-heal fallback take over: ${String(u).slice(0,260)}`),g(r,{event:"e2e_restore_rejected",origin:"restore",error:String(u).slice(0,300)});try{await w(async p=>{await h(r,"::a2a_messaging::reject_e2e_restore",{},p)})}catch(p){d(p)&&f("reject_e2e_restore",p),l(`[${e}] reject_e2e_restore failed (staging is transient; continuing):`,String(p))}}try{r.pw.refresh_identity_proof_document(),l(`[${e}] transport IPD refreshed from post-import state`)}catch(u){i("ipd_refresh","FAILED (IPD would advertise a stale bundle)",u)}let n=!1,c="";try{if(process.env.OURS_TEST_FORCE_IPD_INCOHERENT==="1")throw new Error("forced incoherent (OURS_TEST_FORCE_IPD_INCOHERENT)");let u=S(v=>String(R(r,"::a2a_messaging::e2e_self_fp",v).Reduce("ik").Visualize())),p=r.pw.identity_proof_document.Visualize(),y=u.replace(/^0x/i,"");n=y.length>=32&&p.toLowerCase().includes(y.toLowerCase()),c=u.slice(0,18),g(r,{event:"ipd_coherence",ik:u,coherent:n})}catch(u){i("ipd_coherence","probe FAILED (coherence unprovable)",u)}l(`[${e}] IPD/e2e coherence: account_ik=${c}\u2026 ipd_advertises_it=${n}`),n||i("ipd_coherence","IPD does NOT advertise the live account ik",new Error("incoherent transport IPD"))}}return j.expose_packet(r.cid),N.set(e,r),l(`[${e}] EXPOSED (routing + broker registration) \u2014 import phase complete`),await me(r),P(r),r}async function kt(){m.mkdirSync(E(),{recursive:!0});let e;try{e=m.readFileSync(Q(),"utf8").trim()}catch{}let t=Ve(24).toString("hex");ne(await C(F,t,E(),!1,e)),e||m.writeFileSync(Q(),q(b),{mode:384}),oe(Z(b)),l(`contact-book registrar ready (${b.cid})`)}function Se(e){try{return m.existsSync(k(e))&&m.statSync(k(e)).size>0}catch{return!1}}function ze(e){let t=S(d=>Buffer.from(R(e,"::actor::export_state",d).Serialize()));m.mkdirSync(e.dir,{recursive:!0,mode:448});let s=k(e.dir),r=`${s}.tmp`,a;try{a=m.openSync(r,"w",384),m.fchmodSync(a,384),m.writeFileSync(a,t),m.fsyncSync(a),m.closeSync(a),a=void 0,m.renameSync(r,s),m.chmodSync(s,384);try{m.chmodSync(O(e.dir),384)}catch{}let d=m.openSync(e.dir,"r");try{m.fsyncSync(d)}finally{m.closeSync(d)}}catch(d){if(a!==void 0)try{m.closeSync(a)}catch{}try{m.rmSync(r,{force:!0})}catch{}throw d}}function z(e){try{ze(e),e.persistFailed&&(e.persistFailed=!1,l(`[${e.name}] persist recovered \u2014 quarantine lifted`),g(e,{event:"persist_recovered"}))}catch(t){e.persistFailed=!0,l(`[${e.name}] PERSIST FAILED \u2014 identity quarantined (fail-closed), outbound of this txn withheld:`,String(t));try{g(e,{event:"persist_failed",error:String(t).slice(0,300)})}catch{}throw process.nextTick(()=>ee(e.name,`[${e.name}] PERSIST FAILED \u2014 messaging quarantined until the state file is writable again`)),t}}function S(e){let t=new Re;try{return e(t)}finally{t.Finalize()}}async function w(e){let t=new Re;try{return await e(t)}finally{t.Finalize()}}function R(e,t,s){let r=$e({name:t,targ:void 0}),a=e.pw.packet.ExecuteTransaction(r);return r.Destroy(),s?a.Attach(s):a}async function Ee(e,t){let s=e.lock,r;e.lock=new Promise(a=>r=a),await s;try{return await t()}finally{r()}}function Ae(e,t,s=25e3){return new Promise((r,a)=>{let d=setTimeout(()=>{let i=e.pending.findIndex(f=>f.timer===d);i>=0&&e.pending.splice(i,1),a(new Error("timed out waiting for the transaction result"))},s);e.pending.push({resolve:r,reject:a,timer:d}),e.pw.add_client_message(t)})}function h(e,t,s,r,a){if(e.persistFailed)try{z(e)}catch(i){return Promise.reject(new Error(`identity "${e.name}" is quarantined: state persist is failing (${String(i)}) \u2014 mutations are rejected until state_data.bin is writable again`))}let d=$e({name:t,targ:s});return Ee(e,()=>Ae(e,d,a)).then(i=>{if(d.Destroy(),e.persistFailed){try{i.Destroy()}catch{}throw new Error(`identity "${e.name}": state persist FAILED \u2014 this transaction's outbound was withheld (fail-closed); fix the state directory and retry`)}return r?i.Attach(r):i},i=>{try{d.Destroy()}catch{}throw i})}var D=null;function jt(e){D?.uninstall(),D=e===null?null:{hook:e,uninstall:ue("notification",e)}}function Lt(e){D?.hook===e&&(D.uninstall(),D=null)}function ee(e,t){fe(e,t)}var ve={onNotify:(e,t)=>ee(e,t)},U=new Map;function Oe(e){let t=U.get(e);if(!(!t||t.size===0))for(let s of[...t])try{s()}catch{}}function Pe(e,t){return new Promise(s=>{let r=U.get(e);r||(r=new Set,U.set(e,r));let a=!1,d=()=>{a||(a=!0,r.delete(i),r.size===0&&U.delete(e),clearTimeout(f),s())},i=d,f=setTimeout(d,t);r.add(i)})}function g(e,t){try{_.mkdirSync(e.dir,{recursive:!0,mode:448}),_.appendFileSync(L(e.dir),JSON.stringify(t)+`
|
|
3
|
+
`)}catch(s){l(`[${e.name}] failed to append notifications.log:`,String(s))}Oe(e.name),le(e,t)}function Bt(e){let t=L(e.dir),s="";try{s=_.readFileSync(t,"utf8")}catch{return new Set}let r=[];for(let a of s.split(`
|
|
4
|
+
`))if(a.trim())try{r.push(JSON.parse(a))}catch{}return de(r)}function V(e,t){let s=e.Reduce(t);return s.IsNil()?"":Buffer.from(s.GetBinary()).toString("hex")}var De=Number(process.env.OURS_NOTIFY_LONGPOLL_MS)>0?Number(process.env.OURS_NOTIFY_LONGPOLL_MS):25e3,Fe=250;function te(e){try{return _.statSync(e).size}catch{return 0}}function je(e,t,s){if(s<=t)return{events:[],cursor:t};let r=Buffer.alloc(s-t),a=0;try{let o=_.openSync(e,"r");try{a=_.readSync(o,r,0,r.length,t)}finally{_.closeSync(o)}}catch{return{events:[],cursor:t}}let d=r.subarray(0,a),i=d.lastIndexOf(10);if(i===-1)return{events:[],cursor:t};let f=[];for(let o of d.subarray(0,i+1).toString("utf8").split(`
|
|
5
|
+
`))if(o.trim())try{f.push(JSON.parse(o))}catch{}return{events:f,cursor:t+i+1}}async function Mt(e,t,s,r){let a=L(be(T,s)),d=(n,c)=>{t.writableEnded||(t.writeHead(200,{"Content-Type":"application/json"}),t.end(JSON.stringify({cursor:n,events:c})))};if(r===null||r==="tip"){d(te(a),[]);return}let i=parseInt(r,10);if(!Number.isFinite(i)||i<0){t.writableEnded||(t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"invalid since cursor"})));return}let f=!1;e.on("close",()=>{f=!0});let o=Date.now()+De;for(;!f;){let n=te(a);if(i>n&&(i=0),n>i){let{events:c,cursor:u}=je(a,i,n);if(c.length>0){d(u,c);return}i=u}if(Date.now()>=o)break;await Pe(s,Math.min(Fe,o-Date.now()))}f||d(te(a),[])}function P(e){try{let{unread:t,unreadFiles:s}=S(d=>{let f=pe(R(e,"::actor::list_incoming_messages",d)).filter(c=>c.status==="unread"),o=R(e,"::actor::list_incoming_files",d),n=[];if(!o.IsNil())for(let c=0;;c++){let u=o.Reduce(c);if(u.IsNil())break;u.Reduce("status").Visualize()==="unread"&&n.push({file_id:u.Reduce("file_id").Visualize(),sender_id:u.Reduce("sender_id").Visualize(),from:u.Reduce("sender_name").Visualize(),filename:u.Reduce("filename").Visualize(),mime:u.Reduce("mime").Visualize(),bytes:u.Reduce("size").Visualize(),date:u.Reduce("date").Visualize(),wire_id:u.Reduce("wire_id").Visualize()})}return{unread:f,unreadFiles:n}}),r={count:t.length,recent:t.slice(-10).map(d=>({from:d.sender_name,msg_id:d.msg_id,date:d.date})),files:s.length,unread_files:s.slice(-10)};_.mkdirSync(e.dir,{recursive:!0,mode:448});let a=`${B(e.dir)}.tmp`;_.writeFileSync(a,JSON.stringify(r)),_.renameSync(a,B(e.dir))}catch(t){l(`[${e.name}] failed to refresh unread snapshot:`,String(t))}}function Ht(){let e=[],t=[];try{t=_.readdirSync(T,{withFileTypes:!0})}catch{return{identities:e}}for(let s of t){if(!s.isDirectory()||re(s.name)!==null)continue;let r;try{r=JSON.parse(_.readFileSync(B(be(T,s.name)),"utf8"))}catch{continue}let a=Number.isSafeInteger(r.count)&&Number(r.count)>=0?Number(r.count):0,d=Number.isSafeInteger(r.files)&&Number(r.files)>=0?Number(r.files):0;if(a===0&&d===0)continue;let i=Array.isArray(r.recent)?r.recent.slice(-10).flatMap(o=>{if(!o||typeof o!="object")return[];let n=o;return typeof n.from!="string"||!["string","number"].includes(typeof n.msg_id)||typeof n.date!="string"?[]:[{from:n.from,msg_id:n.msg_id,date:n.date}]}):[],f=Array.isArray(r.unread_files)?r.unread_files.slice(-10).flatMap(o=>{if(!o||typeof o!="object")return[];let n=o;return typeof n.from!="string"||typeof n.filename!="string"||typeof n.mime!="string"||typeof n.wire_id!="string"?[]:[{from:n.from,filename:n.filename,mime:n.mime,wire_id:n.wire_id,...typeof n.sender_id=="string"?{sender_id:n.sender_id}:{},...["string","number"].includes(typeof n.file_id)?{file_id:n.file_id}:{},...["string","number"].includes(typeof n.bytes)?{bytes:n.bytes}:{},...typeof n.date=="string"?{date:n.date}:{}}]}):[];e.push({name:s.name,count:a,recent:i,files:d,unread_files:f})}return e.sort((s,r)=>String(s.name).localeCompare(String(r.name))),{identities:e}}export{jt as a,Lt as b,ee as c,ve as d,Oe as e,Pe as f,g,Bt as h,V as i,te as j,je as k,Mt as l,P as m,Ht as n,He as o,ke as p,K as q,me as r,xe as s,H as t,qe as u,ge as v,C as w,A as x,gt as y,yt as z,kt as A,Se as B,ze as C,z as D,S as E,w as F,R as G,Ee as H,Ae as I,h as J,E as K,Q as L,Y as M,ye as N,_e as O,Z as P,q as Q,we as R,it as S,he as T};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{a as P,b as B,c as C,d as b}from"./chunk-VW2KWXSJ.js";import{a as g}from"./chunk-7UUFYO6G.js";import{A as M,B as A,C as E,J as m,a as R}from"./chunk-UM73BGFH.js";import{E as v,F as u,G as F,J as _,g as p,h as $,m as y}from"./chunk-NQQ4GSVI.js";import{c as w}from"./chunk-X4RVJ5VL.js";import{d as k}from"./chunk-LKFYUCN7.js";import{a as I}from"./chunk-P55RJGZU.js";import{i as c}from"./chunk-HSVIKO4D.js";import{readFile as q}from"node:fs/promises";import{basename as N}from"node:path";function O(s,r){if(s)return r!==void 0?{wire_id:s,sentence:r}:{wire_id:s}}async function Q(s,r){let e=g(s),{contact:o,text:n}=r,a=O(r.reply_to_wire_id,r.reply_to_sentence);try{let t=await u(async d=>b(await _(e,"::a2a_messaging::send_message",{contact:o,text:n,...a?{reply_to:a}:{}},d)));switch(t.kind){case"refused":c(`[e2e-route] refused cid=${t.cid} wire_id=${t.wireId} (downgrade_refused)`);break;case"migrating":c(`[migration] queued cid=${t.cid} wire_id=${t.wireId} (migrating, ${t.queued} queued)`);break;case"e2e":c(`[e2e-route] cid=${t.cid} wire_id=${t.wireId} verdict=e2e (core delivered over migrated session)${t.notRetained?" NOT RETAINED (oversized)":""}`),t.notRetained&&p(e,{event:"send_not_retained",wire_id:t.wireId,kind:"message"});break;default:break}return t}catch(t){if(!/Unknown contact/.test(String(t)))throw m("send_message",String(t));try{let d=P(e,o);return{kind:"introduced",text:d?await B(e,d,n):await C(e,o,n)}}catch(d){throw m("send_message",String(d),"FALLBACK_FAILED")}}}async function X(s,r){let e=g(s),{contact:o,path:n,data_base64:a,filename:t,mime:d}=r;if((n?1:0)+(a?1:0)!=1)throw M();let f,l;try{if(n)f=await q(n),l=t??N(n);else{if(!t)throw A();f=Buffer.from(a,"base64"),l=t}}catch(i){throw i instanceof R?i:E(String(i))}let h=d??(n?I(n):""),S=O(r.reply_to_wire_id,r.reply_to_sentence);try{let i=await u(async x=>{let T=e.pw.packet.NewBinaryFromBuffer(f).Attach(x);return b(await _(e,"::a2a_messaging::send_file",{contact:o,filename:l,mime:h,data:T,...S?{reply_to:S}:{}},x))});switch(i.kind){case"refused":c(`[e2e-route] refused cid=${i.cid} wire_id=${i.wireId} (downgrade_refused, file)`);break;case"migrating":c(`[migration] file-defer cid=${i.cid} wire_id=${i.wireId} (migrating, not queued)`);break;case"e2e":c(`[e2e-route] cid=${i.cid} wire_id=${i.wireId} verdict=e2e file (core delivered over migrated session)${i.notRetained?" NOT RETAINED (oversized)":""}`),i.notRetained&&p(e,{event:"send_not_retained",wire_id:i.wireId,kind:"file"});break;default:break}return{...i,filename:l,bytes:f.length,mime:h}}catch(i){throw m("send_file",String(i))}}async function Y(s){let r=g(s);try{return v(e=>w(F(r,"::actor::list_incoming_messages",e)))}catch(e){throw m("list_incoming_messages",String(e))}}async function Z(s){let r=g(s);try{let e=await u(async n=>{let a=await _(r,"::actor::get_messages",{},n);return w(a.Reduce("messages"))});y(r);let o=$(r);return k(e,o)}catch(e){throw m("get_messages",String(e))}}async function ee(s,r){let e=g(s),{msg_ids:o}=r;try{let n=await u(async a=>(await _(e,"::actor::defer_messages",{msg_ids:o},a)).Reduce("deferred").Visualize());return y(e),{deferred:n}}catch(n){throw m("defer_messages",String(n))}}export{Q as a,X as b,Y as c,Z as d,ee as e};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{basename as e,extname as a}from"node:path";var p={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml",".bmp":"image/bmp",".ico":"image/x-icon",".pdf":"application/pdf",".txt":"text/plain",".md":"text/markdown",".json":"application/json",".csv":"text/csv",".html":"text/html",".xml":"application/xml",".zip":"application/zip",".gz":"application/gzip",".tar":"application/x-tar",".mp3":"audio/mpeg",".wav":"audio/wav",".mp4":"video/mp4",".mov":"video/quicktime"};function m(i){return p[a(i).toLowerCase()]??"application/octet-stream"}function o(i){let t=e(i).replace(/[^A-Za-z0-9._-]/g,"_");return t.length?t.slice(0,200):"file"}export{m as a,o as b};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{a as L}from"./chunk-37D5PCFY.js";import{d as D}from"./chunk-V64IUVSS.js";import{a as de,b as ce}from"./chunk-ZAXRB5MO.js";import{a as pe,d as le}from"./chunk-UELGY557.js";import{a as ae}from"./chunk-A3SXVUOC.js";import{b as ie,c as se}from"./chunk-NMYSFQBL.js";import{b as re}from"./chunk-VOYMK2OO.js";import{C as oe,a as q,b as ee,l as te,n as ne}from"./chunk-NQQ4GSVI.js";import{a as $,b as X,c as u,e as x,f as Y,g as Z}from"./chunk-RAGUBE4Y.js";import{c as I,o as Q,v as W}from"./chunk-Q3UVLSCX.js";import{a as N,b as B,c as M,d as F,e as k,g as V,h as P,i as p,m as T,p as K}from"./chunk-HSVIKO4D.js";import{createServer as he}from"node:http";import{randomUUID as we}from"node:crypto";import*as H from"node:fs";function Ie(s){if(!s||typeof s!="object"||Array.isArray(s))return!1;let r=s;return r.jsonrpc==="2.0"&&r.method==="initialize"}var Se=["brokerUrl","port","stateDir","gcIntervalMs","apiVisibility"];function fe(s){return new Promise((r,R)=>{let h="";s.on("data",a=>h+=a),s.on("end",()=>{try{r(JSON.parse(h))}catch(a){R(a)}}),s.on("error",R)})}async function Le(s={}){try{return await ve(s)}catch(r){throw P?.failed(),p(`fatal startup error: ${r?.stack??r}`),r}}async function ve(s){if(process.env.OURS_TEST_STARTUP_FAIL==="1")throw new Error("forced startup failure (OURS_TEST_STARTUP_FAIL)");if(s.config){let t=Se.filter(e=>s.config[e]!==B[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 r=s.mcp,R=r?.isInitializeRequest??Ie,h=null;if(typeof s.onIdentityNotify=="function"){let t=s.onIdentityNotify;h=(e,i)=>{t(e,i,$.get(e)?.sid??null)},q(h)}p("booting wrapper\u2026"),await ae(),de(),p(`wrapper ready (identities=${I.size}), starting HTTP server\u2026`),P?.update("server");let a={},S=new Map,v=new Map,me=3e4,j=t=>{let e=v.get(t);e?e.n++:v.set(t,{n:1,since:Date.now()})},A=t=>{let e=v.get(t);e&&--e.n<=0&&v.delete(t)},G=()=>{let t=0;for(let e of[...S.keys()]){if(e==="stdio")continue;let i=u.get(e)?.pid;if(i===void 0||i<=1||x(i))continue;let n=v.get(e);if(n&&n.n>0&&Date.now()-n.since<me)continue;let o=S.get(e);S.delete(e),delete a[e],u.delete(e),v.delete(e),o?.close().catch(()=>{}),r?.onSessionClosed?.(e),t++,p(`session ${e.slice(0,8)}\u2026 reaped (client pid ${i} dead)`)}return t},U=setInterval(()=>{G(),se()},6e4);U.unref?.();let _=1e3,ue=10*6e4,f=new Map,ge=(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"||f.set(`${t}:${String(o.id)}`,{method:o.method,at:Date.now()})}if(f.size>_){let n=Date.now()-ue;for(let[o,d]of f)if(d.at<n&&f.delete(o),f.size<=_)break;for(;f.size>_;){let o=f.keys().next();if(o.done)break;f.delete(o.value)}}},ye=(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],d=f.get(`${t}:${o}`);f.delete(`${t}:${o}`),p(`UNDELIVERABLE RESPONSE session=${t.slice(0,8)}\u2026 request_id=${o} method=${d?.method??"unknown"} age_ms=${d?Date.now()-d.at:"unknown"} at=${new Date().toISOString()} \u2014 the answer was produced but its stream was already gone`)}catch{}},g=he(async(t,e)=>{let i=new URL(t.url,`http://localhost:${k}`);if(t.method==="GET"&&i.pathname==="/state-dir"){e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({stateDir:M,version:N,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:N,compat:1,protocol:re,pid:process.pid,stateDir:M}));return}if(t.method==="GET"&&i.pathname==="/identities"){if(!T(t,e))return;e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({identities:[...I.values()].map(n=>({name:n.name,...n.temp?{temporary:!0,stale:!x(n.temp.owner.pid)}:{}}))}));return}if(t.method==="GET"&&i.pathname==="/unread"){if(!T(t,e))return;e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(ne()));return}{let n=/^\/identities\/([^/]+)\/notifications$/.exec(i.pathname);if(t.method==="GET"&&n){if(!T(t,e))return;let o=decodeURIComponent(n[1]);if(K(o)!==null){e.writeHead(400,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"invalid identity name"}));return}await te(t,e,o,i.searchParams.get("since"));return}}{let n=/^\/files\/([^/]+)$/.exec(i.pathname);if(t.method==="GET"&&n){if(!T(t,e))return;let o=decodeURIComponent(n[1]),d=t.headers["x-ours-lease-token"],w=typeof d=="string"&&d?Y(d):void 0,m=w?I.get(w.identity):void 0;if(!m){e.writeHead(401,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"no identity bound to this session"}));return}let y=W(m,o);if(!y){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 l=H.statSync(y);e.writeHead(200,{"Content-Type":"application/octet-stream","Content-Length":String(l.size)});let E=H.createReadStream(y);E.on("error",()=>{try{e.destroy()}catch{}}),E.pipe(e)}catch(l){e.writeHead(500,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:`failed to read file: ${String(l)}`}))}return}}if(i.pathname.startsWith(pe)){await le(t,e,i.pathname,fe);return}if(i.pathname!=="/mcp"||!r){e.writeHead(404,{"Content-Type":"text/plain"}),e.end("Not found");return}if(T(t,e))try{if(t.method==="POST"){let n=await fe(t),o=t.headers["mcp-session-id"],d=t.headers["x-ours-lease-token"],w=t.headers["x-ours-client-pid"],m=w?parseInt(w,10):void 0,y={token:d,pid:Number.isInteger(m)?m:void 0};if(o&&a[o]){u.set(o,y),ge(o,n),j(o),D(e);try{await a[o].handleRequest(t,e,n)}finally{A(o)}}else if(!o&&R(n)){G();let l=r.createTransport({sessionIdGenerator:()=>we(),onsessioninitialized:c=>{a[c]=l,u.set(c,y),S.set(c,C),r.onSessionInitialized?.(c,C),p(`session ${c.slice(0,8)}\u2026 initialized`)}}),E={sessionId:()=>l.sessionId??"pending",leaseToken:()=>u.get(l.sessionId??"pending")?.token,clientPid:()=>u.get(l.sessionId??"pending")?.pid},C=r.createServer(E);C.server.onerror=c=>ye(l.sessionId??"pending",c),l.onclose=()=>{let c=l.sessionId;c&&(delete a[c],S.delete(c),u.delete(c),r.onSessionClosed?.(c),p(`session ${c.slice(0,8)}\u2026 closed (lease kept)`))},await C.connect(l),D(e),await l.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||!a[n]){e.writeHead(400,{"Content-Type":"text/plain"}),e.end("Invalid or missing session ID");return}j(n),D(e);try{await a[n].handleRequest(t,e)}finally{A(n)}}else if(t.method==="DELETE"){let n=t.headers["mcp-session-id"];if(!n||!a[n]){e.writeHead(400,{"Content-Type":"text/plain"}),e.end("Invalid or missing session ID");return}let o=u.get(n)?.token??t.headers["x-ours-lease-token"];if(o){for(let[d,w]of[...$]){if(w.token!==o)continue;$.delete(d);let m=I.get(d);m?.temp&&m.temp.owner.tokenHash===Q(o)&&!m.temp.closing&&ie(m,"owning session released its lease").catch(y=>p(`[${d}] close on lease release failed:`,String(y)))}X.delete(o),Z(),p(`lease released by token \u2026${o.slice(-6)}`)}await a[n].handleRequest(t,e)}else e.writeHead(405,{"Content-Type":"text/plain"}),e.end("Method not allowed")}catch(n){p("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})))}});g.requestTimeout=0,await new Promise((t,e)=>{let i=n=>e(n);g.once("error",i),g.listen(k,"127.0.0.1",()=>{g.off("error",i),P?.ready(),p(`MCP server v${s.version??N} ready (transport=http, port=${k}, visibility=${V}, identities=${I.size}, state=${M}, broker=${F})`),t()})});let z=!1,J=async()=>{if(!z){z=!0,clearInterval(U),ce();for(let t of Object.keys(a)){try{await a[t].close()}catch{}delete a[t]}S.clear();for(let t of I.values())try{oe(t)}catch(e){p(`[${t.name}] shutdown save failed:`,String(e))}g.closeAllConnections?.()}},O=async()=>{p("shutting down\u2026"),await J(),g.close(),process.exit(0)};process.on("SIGINT",O),process.on("SIGTERM",O);let b=g.address();return{port:typeof b=="object"&&b!==null?b.port:k,close:async()=>{process.off("SIGINT",O),process.off("SIGTERM",O),h&&ee(h),await J(),await new Promise(t=>g.close(()=>t()))}}}export{Le as a};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{c as i,i as a}from"./chunk-HSVIKO4D.js";import{join as n}from"node:path";import{createHash as u}from"node:crypto";import*as r from"node:fs";var m;function P(t){m=t}var v=new Map,g=null,y=null;function T(t){g=t}function I(t){y=t}var _=t=>n(i,t),d=t=>n(t,"identity.key"),h=t=>n(t,"state_data.bin"),F=t=>n(t,"notifications.log"),W=t=>n(t,"unread.json"),x=t=>n(t.dir,"files"),c=t=>n(t,"temp.json"),E=t=>u("sha256").update(t).digest("hex");function H(t,e){r.writeFileSync(c(t),JSON.stringify({v:1,owner:{token_sha256:e.owner.tokenHash,pid:e.owner.pid},created_at:e.createdAt}),{mode:384})}function M(t){try{let e=JSON.parse(r.readFileSync(c(t),"utf8"));return e.v!==1||typeof e.owner?.token_sha256!="string"||typeof e.owner?.pid!="number"?null:{owner:{tokenHash:e.owner.token_sha256,pid:e.owner.pid},createdAt:typeof e.created_at=="number"?e.created_at:0}}catch{return null}}function R(){for(let t of w()){let e=n(i,t);try{r.chmodSync(e,448)}catch(o){a(`[${t}] chmod 0700 failed:`,String(o))}for(let o of[h(e),d(e)])if(r.existsSync(o))try{r.chmodSync(o,384)}catch(s){a(`[${t}] chmod 0600 ${o} failed:`,String(s))}}}var k=t=>/^[A-Za-z0-9]+$/.test(t)&&t.length>0&&t.length<=128,$=t=>/^[A-Fa-f0-9]{64}$/.test(t),j=32;function B(t,e){if(!k(e))return null;let o=x(t),s;try{s=r.readdirSync(o)}catch{return null}let l=`${e}-`,p=s.find(f=>f.startsWith(l));return p?n(o,p):null}function w(){return r.existsSync(i)?r.readdirSync(i,{withFileTypes:!0}).filter(t=>t.isDirectory()&&r.existsSync(d(n(i,t.name)))).map(t=>t.name):[]}export{m as a,P as b,v as c,g as d,y as e,T as f,I as g,_ as h,d as i,h as j,F as k,W as l,x as m,c as n,E as o,H as p,M as q,R as r,k as s,$ as t,j as u,B as v,w};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{c as a}from"./chunk-Q3UVLSCX.js";import{c as d,i as u}from"./chunk-HSVIKO4D.js";import{join as h}from"node:path";import*as r from"node:fs";var i=new Map,g=new Set,c=new Map,k=new Set;function E(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(t){return t.code==="EPERM"}}function m(e){for(let t of i.values())if(t.token===e)return t}var f=()=>h(d,"bindings.json");function l(){try{r.mkdirSync(d,{recursive:!0});let e=`${f()}.tmp`;r.writeFileSync(e,JSON.stringify({pid:process.pid,bound:[...i.keys()],holders:[...i.values()].map(t=>({identity:t.identity,pid:t.pid}))})),r.renameSync(e,f())}catch(e){u("failed to persist bindings snapshot:",String(e))}}function _(e){let t=c.get(e)?.token;if(!t)return{code:"NOT_BOUND",error:"No identity bound to this session. Call choose_identity (or create_identity) first."};if(g.has(t))return{code:"BINDING_REASSIGNED",error:"Your identity binding was reassigned to another session. Call choose_identity again to continue."};let n=m(t);if(!n)return{code:"NOT_BOUND",error:"No identity bound to this session. Call choose_identity (or create_identity) first."};let o=a.get(n.identity);if(!o)return i.delete(n.identity),l(),{code:"BOUND_IDENTITY_GONE",error:`The bound identity "${n.identity}" no longer exists. Choose another with choose_identity.`};if(o.temp?.closing)return{code:"TEMP_CLOSING",error:`The temporary identity "${o.name}" is closing and no longer accepts work. Its contacts are being notified and its local state deleted.`};n.sid=e;let s=c.get(e)?.pid;return s&&(n.pid=s),{id:o}}function x(e,t){let n=c.get(e),o=n?.token;if(!o)return;for(let[p,y]of[...i])y.token===o&&p!==t&&i.delete(p);let s=i.get(t)?.epoch??0;i.set(t,{identity:t,token:o,pid:n?.pid??0,sid:e,epoch:s+1,boundAt:Date.now()}),g.delete(o),l()}export{i as a,g as b,c,k as d,E as e,m as f,l as g,_ as h,x as i};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{e as d}from"./chunk-HCIVLHKC.js";import{E as a,G as c}from"./chunk-NQQ4GSVI.js";import{c as s}from"./chunk-Q3UVLSCX.js";function y(e){try{return a(n=>{let i=c(e,"::a2a_capabilities::get_manifest",n).Reduce("capabilities");return i.IsNil()?[]:[...i.GetKeys()].map(t=>typeof t=="string"?t:t.Visualize())})}catch{return[]}}function R(e){let n="",i="",t="",u="",l=[];try{a(g=>{let p=c(e,"::a2a_capabilities::get_manifest",g),r=o=>{let f=p.Reduce(o);return f.IsNil()?"":f.Visualize()};n=r("app_id"),i=r("name"),t=r("description"),u=r("version");let m=p.Reduce("capabilities");m.IsNil()||(l=[...m.GetKeys()].map(o=>typeof o=="string"?o:o.Visualize()))})}catch{}return{app_id:n,name:i,description:t,version:u,capabilities:l,monitoring_status:"unbound"}}function h(e){let n=[];for(let i of s.values()){if(i.name===e.name)continue;let t=d(i);t.rootCid===e.cid&&n.push({name:i.name,cid:i.cid,role_id:t.roleId,bio:t.bio,monitoring:t.monitoringEnabled,capabilities:y(i)})}return n}function v(e,n){let i=s.get(n)??[...s.values()].find(t=>t.cid===n);return!i||i.name===e.name?null:d(i).rootCid===e.cid?i:null}export{y as a,R as b,h as c,v as d};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{a as n}from"./chunk-UM73BGFH.js";var a=class{base;leaseToken;clientPid;apiToken;fetchImpl;constructor(e){this.base=e.url.replace(/\/+$/,""),this.leaseToken=e.leaseToken,this.clientPid=e.clientPid??process.pid,this.apiToken=e.apiToken,this.fetchImpl=e.fetch??globalThis.fetch}headers(e={}){return{"x-ours-lease-token":this.leaseToken,"x-ours-client-pid":String(this.clientPid),...this.apiToken?{"x-ours-api-token":this.apiToken}:{},...e}}async post(e,s){let i=await this.fetchImpl(`${this.base}/api/v1/${e}`,{method:"POST",headers:this.headers({"content-type":"application/json"}),body:JSON.stringify(s??{})}),t;try{t=await i.json()}catch{throw new Error(`${e}: the daemon returned a non-JSON response (HTTP ${i.status})`)}if(t&&typeof t=="object"&&!Array.isArray(t)&&"error"in t){let r=t.error,o=r!==null&&typeof r=="object"&&"code"in r&&"message"in r;if(i.status===400&&o){let{code:c,message:d}=r;throw new n(c,d)}let p=o?r.message:String(r);throw new Error(`${e}: ${p} (HTTP ${i.status})`)}if(!i.ok)throw new Error(`${e}: the daemon returned HTTP ${i.status} with no error field`);return t}async get(e,s){let i=await this.fetchImpl(`${this.base}${e}`,{headers:s?this.headers():{}}),t;try{t=await i.json()}catch{throw new Error(`GET ${e}: the daemon returned a non-JSON response (HTTP ${i.status})`)}if(t&&typeof t=="object"&&"error"in t)throw new Error(`GET ${e}: ${String(t.error)} (HTTP ${i.status})`);if(!i.ok)throw new Error(`GET ${e}: the daemon returned HTTP ${i.status} with no error field`);return t}createIdentity(e){return this.post("createIdentity",e)}createTemporaryIdentity(e){return this.post("createTemporaryIdentity",e)}closeTemporaryIdentityOp(e={}){return this.post("closeTemporaryIdentityOp",e)}createRootIdentity(e){return this.post("createRootIdentity",e)}defineLocalIdentityFile(e){return this.post("defineLocalIdentityFile",e)}chooseIdentity(e){return this.post("chooseIdentity",e)}listIdentities(){return this.post("listIdentities",{})}currentIdentity(){return this.post("currentIdentity",{})}removeIdentity(e){return this.post("removeIdentity",e)}releaseLease(){return this.post("releaseLease",{})}generateInvite(e={}){return this.post("generateInvite",e)}listInvites(){return this.post("listInvites",{})}revokeInvite(e){return this.post("revokeInvite",e)}addContact(e){return this.post("addContact",e)}listContacts(){return this.post("listContacts",{})}listLocalContactBook(){return this.post("listLocalContactBook",{})}setLocalBookPolicy(e){return this.post("setLocalBookPolicy",e)}removeContact(e){return this.post("removeContact",e)}renameContact(e){return this.post("renameContact",e)}respondToIntroduction(e){return this.post("respondToIntroduction",e)}setBio(e){return this.post("setBio",e)}advertiseMigrate(){return this.post("advertiseMigrate",{})}setPersona(e){return this.post("setPersona",e)}sendMessage(e){return this.post("sendMessage",e)}sendFile(e){return this.post("sendFile",e)}listIncomingMessages(){return this.post("listIncomingMessages",{})}getMessages(){return this.post("getMessages",{})}deferMessages(e){return this.post("deferMessages",e)}listIncomingFiles(){return this.post("listIncomingFiles",{})}getFiles(e={}){return this.post("getFiles",e)}saveFileFallbackNotice(e){return this.post("saveFileFallbackNotice",e)}version(){return this.get("/version",!1)}stateDir(){return this.get("/state-dir",!1)}async identities(){return(await this.get("/identities",!0)).identities}unread(){return this.get("/unread",!0)}async*watchNotifications(e,s={}){let i=s.since??"tip",t=`/identities/${encodeURIComponent(e)}/notifications`;for(;!s.signal?.aborted;){let r;try{let o=await this.fetchImpl(`${this.base}${t}?since=${i}`,{headers:this.headers(),signal:s.signal});try{r=await o.json()}catch{throw new Error(`watchNotifications(${e}): the daemon returned a non-JSON response (HTTP ${o.status})`)}}catch(o){if(s.signal?.aborted)return;throw o}if("error"in r)throw new Error(`watchNotifications(${e}): ${r.error}`);i=r.cursor;for(let o of r.events)yield o}}async fetchFile(e){let s=await this.fetchImpl(`${this.base}/files/${encodeURIComponent(e)}`,{headers:this.headers()});if(!s.ok){let i=`HTTP ${s.status}`;try{let t=await s.json();t&&t.error!==void 0&&(i=String(t.error))}catch{}throw new Error(`fetchFile(${e}): ${i}`)}return new Uint8Array(await s.arrayBuffer())}};export{a};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{a as O,b,c as w,d as F,e as T,f as N,g as L,h as H,i as B,j}from"./chunk-KZMPGVQM.js";import{a as E,b as J,c as _}from"./chunk-AJQIWYXG.js";import{a as $,b as V,c as X,d as q,e as z}from"./chunk-NSPYN5TT.js";import{a as D,b as G,c as K}from"./chunk-3DQSMLVZ.js";import{b as u,c as v,d as S,e as k,f as x,g as h,h as R,i as C,j as P,k as M}from"./chunk-7UUFYO6G.js";import{a as I}from"./chunk-UM73BGFH.js";import{c as d}from"./chunk-RAGUBE4Y.js";import{o as f}from"./chunk-Q3UVLSCX.js";import{i as m,m as y}from"./chunk-HSVIKO4D.js";var W="/api/v1/",t=i=>(e,n)=>i(e,n),s=i=>e=>i(e),Y=i=>(e,n)=>i(n),Q={createIdentity:t(u),createTemporaryIdentity:t(v),closeTemporaryIdentityOp:t(S),createRootIdentity:t(k),defineLocalIdentityFile:Y(x),chooseIdentity:t(h),listIdentities:s(R),currentIdentity:s(C),removeIdentity:t(P),releaseLease:s(M),generateInvite:t(O),listInvites:s(b),revokeInvite:t(w),addContact:t(F),listContacts:s(T),listLocalContactBook:s(N),setLocalBookPolicy:t(L),removeContact:t(H),renameContact:t(B),respondToIntroduction:t(j),setBio:t(D),advertiseMigrate:s(G),setPersona:t(K),sendMessage:t($),sendFile:t(V),listIncomingMessages:s(X),getMessages:s(q),deferMessages:t(z),listIncomingFiles:s(E),getFiles:t(J),saveFileFallbackNotice:t(_)},l=new Map,U=(i,e)=>{let n=i.headers[e];return typeof n=="string"&&n!==""?n:void 0};function Z(i){let e=U(i,"x-ours-lease-token"),n=U(i,"x-ours-client-pid"),A=n?parseInt(n,10):NaN,a=Number.isInteger(A)?A:void 0,o=e?`api:${f(e)}`:"api:anonymous";return d.set(o,{token:e,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 c=(i,e,n)=>{i.writableEnded||(i.writeHead(e,{"Content-Type":"application/json"}),i.end(JSON.stringify(n??null)))};async function pe(i,e,n,A){let a=n.slice(W.length);if(!y(i,e))return;if(i.method!=="POST"){c(e,405,{error:"method not allowed: the typed API is POST-only"});return}let o=Object.prototype.hasOwnProperty.call(Q,a)?Q[a]:void 0;if(!o){c(e,404,{error:`unknown operation "${a}"`});return}let r;try{r=await A(i)}catch{c(e,400,{error:"the request body must be JSON"});return}if(r===null||typeof r!="object"||Array.isArray(r)){c(e,400,{error:"the request body must be a JSON object"});return}let g=Z(i);try{c(e,200,await o(g.ctx,r))}catch(p){if(p instanceof I){c(e,400,{error:{code:p.code,message:p.message}});return}m("api handler error:",a,String(p)),c(e,500,{error:`internal error in ${a}: ${String(p)}`})}finally{g.release()}}export{W as a,Q as b,Z as c,pe as d};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
var r=new Set(["message_received","file_received","contact_name_collision","sibling_contact_added","local_contact_request","pending_message","e2e_restore_rejected","contact_restored","migration_active","e2e_app_send","dedup_degraded","e2e_delivery_expired","e2e_app_recv","e2e_rekey","migration_deferred_flush","migration_stalled","downgrade_refused","contact_removed","monitoring_disabled","inbound_error"]),i={event:()=>{},notification:()=>{}},t={...i};function o(e,n){return t[e]=n,()=>{t[e]===n&&(t[e]=i[e])}}function d(){Object.assign(t,i)}function s(e){return t[e]===i[e]}function a(e,n){t.event({identity:e.name,event:typeof n.event=="string"?n.event:"",record:n})}function c(e,n){t.notification(e,n)}export{r as a,o as b,d as c,s as d,a as e,c as f};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
var t=class extends Error{constructor(n,r){super(r);this.code=n;this.name="OursError"}},i=()=>new t("NOT_BOUND","No identity bound to this session. Call choose_identity (or create_identity) first."),s=()=>new t("BINDING_REASSIGNED","Your identity binding was reassigned to another session. Call choose_identity again to continue."),a=e=>new t("BOUND_IDENTITY_GONE",`The bound identity "${e}" no longer exists. Choose another with choose_identity.`),d=e=>new t("TEMP_CLOSING",`The temporary identity "${e}" is closing and no longer accepts work. Its contacts are being notified and its local state deleted.`),_=(e,o)=>new t("NAME_TAKEN",`${e} failed: an identity named "${o}" already exists.`),c=()=>new t("NO_LEASE_HEADERS","create_temporary_identity failed: this client is not connected through the ours connector (no lease token / client pid headers), so there is no session lease to own the identity. Launch ours via the connector (`ours-mcp proxy`)."),l=()=>new t("RANDOM_NAME_EXHAUSTED","create_temporary_identity failed: could not pick a free random name after 5 attempts \u2014 retry."),E=e=>new t("ROOT_EXISTS",`create_root_identity failed: a root identity already exists ("${e}") \u2014 one root per host. Nothing to do.`),y=()=>new t("NOT_BOUND_NO_NAME","close_temporary_identity failed: no identity is bound to this session and no name was given."),N=e=>new t("NOT_TEMPORARY",`close_temporary_identity failed: "${e}" is a permanent identity. Use remove_identity if you really mean to delete it.`),p=(e,o)=>new t("TEMP_OWNED_ELSEWHERE",`close_temporary_identity failed: "${e}" is owned by another LIVE session (owner pid ${o}) \u2014 one session cannot delete another's temporary identity.`),O=(e,o,n)=>new t("DELETE_PARTIAL",`Temporary identity "${e}" closed with an error: ${o}. ${n}`),h=e=>new t("PATH_NOT_ABSOLUTE",`define_local_identity_file failed: path must be absolute (got "${e}").`),T=e=>new t("NO_SUCH_IDENTITY",`choose_identity failed: no identity named "${e}". Create it with create_identity.`),w=()=>new t("NO_LEASE_TOKEN","choose_identity failed: this client is not connected through the ours connector (no lease token header). Launch ours via the connector (`ours-mcp proxy`)."),u=e=>new t("TEMP_CLOSING",`choose_identity failed: temporary identity "${e}" is closing \u2014 its state is being deleted.`),m=(e,o)=>new t("TEMP_OWNED_ELSEWHERE",`choose_identity failed: "${e}" is a TEMPORARY identity owned by another live session (owner pid ${o}). Ownership is exclusive and cannot be overridden \u2014 not even with force. Create your own with create_temporary_identity.`),A=(e,o)=>new t("TEMP_STALE",`choose_identity failed: temporary identity "${e}" is STALE \u2014 its owning session (pid ${o}) is gone and it is pending automatic cleanup. It cannot be adopted by another session; use close_temporary_identity to reclaim (clean it up) now.`),I=e=>new t("BOUND_ELSEWHERE",`choose_identity declined: "${e}" is currently bound to another live session. Do not retry with force=true on your own \u2014 tell the user it is in use elsewhere and ask whether to forcibly rebind it here; only retry with force=true after they explicitly confirm.`),L=(e,o)=>new t("TEMP_OWNED_ELSEWHERE",`remove_identity failed: "${e}" is a TEMPORARY identity owned by another LIVE session (owner pid ${o}) \u2014 one session cannot delete another's temporary identity.`),g=(e,o,n)=>new t("DELETE_PARTIAL",`Temporary identity "${e}" closed with an error: ${o}.${n}`),D=(e,o)=>new t("ROOT_HAS_ROLES",`remove_identity failed: "${e}" is the root identity and still has ${o.length} role(s): ${o.join(", ")}. Remove the roles first.`),f=(e,o)=>new t("DELETE_PARTIAL",`Identity "${e}" removed from memory, but ${o}`),R=()=>new t("PUBLIC_INVITE_NAMED","generate_invite failed: a public invite cannot pre-assign a contact name \u2014 every redeemer would be registered under it. Omit `name` for a public invite."),S=()=>new t("NO_POLICY_ARGS","set_local_book_policy: pass expose and/or auto_accept."),x=()=>new t("SEND_ARGS","send_file: provide exactly one of `path` or `data_base64`."),b=()=>new t("SEND_ARGS","send_file: `filename` is required with `data_base64`."),$=e=>new t("FILE_UNREADABLE",`send_file: cannot read file: ${e}`),C=(e,o)=>new t("CONNECTOR_TOO_OLD","save_file could not be completed by your ours connector: it reached the daemon directly, which means the connector is too old to stream the bytes and write them as your OS user. Update the ours connector to use save_file, or fall back to get_files and copy the returned path yourself (`cp`)."+(o?"":` (Also note: no file with wire_id ${e} is currently on disk for this identity \u2014 run get_files first.)`)),M=()=>new t("NO_ROOT","No root identity exists on this host \u2014 create one with create_root_identity first."),P=e=>new t("INVALID_SELECTION",`get_files failed: wire_ids must contain 1-${e} items.`),v=()=>new t("MALFORMED_ID","get_files failed: every selected wire_id must be exactly 64 hexadecimal characters."),U=()=>new t("DUPLICATE_ID","get_files failed: wire_ids must not contain duplicates."),B=()=>new t("UNKNOWN_OR_STALE_ID","get_files failed: one or more selected wire_ids is unknown, stale, or no longer unread; no files were retrieved."),F=(e,o,n="TX_FAILED")=>new t(n,`${e} failed: ${o}`);export{t as a,i as b,s as c,a as d,d as e,_ as f,c as g,l as h,E as i,y as j,N as k,p as l,O as m,h as n,T as o,w as p,u as q,m as r,A as s,I as t,L as u,g as v,D as w,f as x,R as y,S as z,x as A,b as B,$ as C,C as D,M as E,P as F,v as G,U as H,B as I,F as J};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
var d=25e3,u=`: ka
|
|
3
|
+
|
|
4
|
+
`;function a(e=process.env){let t=(e.OURS_SSE_KEEPALIVE_MS??"").trim();if(t==="")return 25e3;let n=Number(t);return Number.isFinite(n)&&n>=0?n:25e3}function p(e,t=a()){if(!(t>0))return;let n=!1,E=e.writeHead.bind(e);e.writeHead=(...r)=>{let o=typeof r[1]=="object"&&r[1]!==null?r[1]:r[2];if(o&&!Array.isArray(o))for(let[c,S]of Object.entries(o))c.toLowerCase()==="content-type"&&String(S).includes("text/event-stream")&&(n=!0);return E(...r)};let i=setInterval(()=>{if(!(!n||e.writableEnded||e.destroyed))try{e.write(u)}catch{}},t);i.unref?.();let s=()=>clearInterval(i);e.once("close",s),e.once("finish",s)}export{d as a,u as b,a as c,p as d};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{a as l}from"./chunk-T25JIPX5.js";import{e as o}from"./chunk-HCIVLHKC.js";import{F as p,G as f,J as m}from"./chunk-NQQ4GSVI.js";import{c as r}from"./chunk-Q3UVLSCX.js";import{i as u}from"./chunk-HSVIKO4D.js";var A=()=>d,d=!0,C=d?2:1;function g(e,n){let a=[];for(let t of r.values()){if(t.name===e.name)continue;let i=o(t);if(i.rootCid!==e.cid)continue;let c=f(t,"::actor::export_address_document_native",n);a.push({cid:c.Reduce("identity").Reduce("container_id"),role_id:i.roleId,name:t.name,bio:i.bio,persona:i.persona,caps:l(t),child_ad:c})}return a}var s=new Set;async function y(e){if(!s.has(e.name)){s.add(e.name);try{await p(async n=>{await m(e,"::a2a_cluster::reconcile",{pending_handle:"",children:g(e,n)},n)})}catch(n){u(`[${e.name}] cluster sweep failed:`,String(n))}finally{s.delete(e.name)}}}var w=6e4;function T(){setInterval(()=>{if(d)for(let e of r.values())o(e).roleId===""&&y(e)},w).unref()}export{A as a,C as b,y as c,T as d};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{b as s,e as p}from"./chunk-HCIVLHKC.js";import{F as f,J as c,N as g,P as l,t as u}from"./chunk-NQQ4GSVI.js";import{c as d,d as a}from"./chunk-Q3UVLSCX.js";function S(e,t){if(!s||!d.has(s))return null;let r=d.get(t)??[...d.values()].find(n=>n.cid===t);if(!r||r.name===e.name)return null;let i=n=>n.name===s||p(n).roleId!=="";return i(e)&&i(r)?r:null}async function V(e,t,r){let i=l(t);return await f(async n=>{await c(e,"::actor::connect_sibling",{name:t.name,target_ad:e.pw.packet.NewBinaryFromBuffer(i).Attach(n),text:r},n)}),u(e),`"${t.name}" was not a contact yet \u2014 connected as an intra-root sibling (delegation-cert auto-accept) and delivered the message.`}async function N(e,t,r){if(!a)throw new Error(`"${t}" is not a contact, and the local contact book is unavailable.`);let i=g(),n=i[t]??Object.values(i).find(o=>o.container_id===t);if(!n)throw new Error(`"${t}" is not a contact and has no local contact-book entry. Use generate_invite/add_contact for remote peers, or list_local_contact_book to see local ones.`);if(n.container_id===e.cid)throw new Error("that contact-book entry is this identity itself.");let m=Buffer.from(n.address_document,"base64url"),w=Buffer.from(n.registrar_sig,"base64url"),y=l(e);return await f(async o=>{let k=await c(a,"::actor::mint_introduction",{joiner_ad:a.pw.packet.NewBinaryFromBuffer(y).Attach(o),target_ad:a.pw.packet.NewBinaryFromBuffer(m).Attach(o)},o),b=Buffer.from(k.Reduce("intro").GetBinary());await c(e,"::actor::connect_local",{name:n.name,target_ad:e.pw.packet.NewBinaryFromBuffer(m).Attach(o),intro:e.pw.packet.NewBinaryFromBuffer(b).Attach(o),entry_sig:e.pw.packet.NewBinaryFromBuffer(w).Attach(o),text:r},o)}),u(e),`"${n.name}" was not a contact yet \u2014 connected via the local contact book and sent the message with the introduction. If "${n.name}" requires approval for local introductions, delivery completes once they approve.`}var R=e=>{let t=n=>!e.Reduce(n).IsNil(),r=e.Reduce("wire_id").Visualize(),i=t("sent_to")?e.Reduce("sent_to").Visualize():"";if(t("downgrade_refused"))return{kind:"refused",wireId:r,cid:i};if(t("migrating"))return{kind:"migrating",wireId:r,cid:i,queued:t("queued")?Number(e.Reduce("queued").Visualize()):0};if(t("route")){let n=t("retained")&&!e.Reduce("retained").GetBoolean();return{kind:"e2e",wireId:r,cid:i,notRetained:n}}return t("deferred")?{kind:"deferred",wireId:r,queued:t("queued")?Number(e.Reduce("queued").Visualize()):0}:{kind:"sent",wireId:r}};export{S as a,V as b,N as c,R as d};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{c as p,h as w,j as I,k as b,l as x}from"./chunk-DIRW7I4S.js";import{b as z}from"./chunk-P55RJGZU.js";import{m as h}from"./chunk-Q3UVLSCX.js";import{b as _}from"./chunk-HSVIKO4D.js";import{basename as M,join as $}from"node:path";import{createHash as S,randomUUID as G}from"node:crypto";import{mkdir as C,open as O,rename as v,unlink as N,lstat as D}from"node:fs/promises";import{brotliCompressSync as K,brotliDecompressSync as P}from"node:zlib";function Z(e){let n=[];if(e.IsNil())return n;for(let i of e.GetKeys()){let t=e.Reduce(i);t.IsNil()||n.push({name:t.Reduce("name").Visualize(),container_id:t.Reduce("container_id").Visualize()})}return n}function ee(e){let n={};if(e.IsNil())return n;for(let i of e.GetKeys()){let t=e.Reduce(i);t.IsNil()||(n[typeof i=="string"?i:i.Visualize()]=t.Visualize())}return n}function te(e){let n=[];if(e.IsNil())return n;for(let i=0;;i++){let t=e.Reduce(i);if(t.IsNil())break;let s=t.Reduce("reply_to"),o=null;if(!s.IsNil()){o={wire_id:s.Reduce("wire_id").Visualize()};let r=s.Reduce("sentence");r.IsNil()||(o.sentence=parseInt(r.Visualize(),10))}n.push({msg_id:parseInt(t.Reduce("msg_id").Visualize(),10),sender_id:t.Reduce("sender_id").Visualize(),sender_name:t.Reduce("sender_name").Visualize(),text:t.Reduce("text").Visualize(),date:t.Reduce("date").Visualize(),status:t.Reduce("status").Visualize(),wire_id:t.Reduce("wire_id").Visualize(),reply_to:o})}return n}function ie(e){let n=[];if(e.IsNil())return n;for(let i=0;;i++){let t=e.Reduce(i);if(t.IsNil())break;let s=t.Reduce("filename").Visualize(),o=t.Reduce("mime").Visualize()||"application/octet-stream",r=t.Reduce("reply_to"),a=null;if(!r.IsNil()){a={wire_id:r.Reduce("wire_id").Visualize()};let u=parseInt(r.Reduce("sentence").Visualize(),10);Number.isSafeInteger(u)&&u>0&&(a.sentence=u)}n.push({file_id:parseInt(t.Reduce("file_id").Visualize(),10),wire_id:t.Reduce("wire_id").Visualize(),from:{id:t.Reduce("sender_id").Visualize(),name:t.Reduce("sender_name").Visualize()},filename:s,mime:o,size:parseInt(t.Reduce("size").Visualize(),10),size_source:"received_payload",status:t.Reduce("status").Visualize(),date:t.Reduce("date").Visualize(),sha256:null,reply_to:a,kind:p(o,s)?"voice_message":"file"})}return n}function ne(e){if(e.length===0)return"No files received.";let n=[];for(let i of e){let t=i.kind==="voice_message"?"\u{1F3A4} voice message \xB7 ":"";n.push(` \u2022 ${t}${i.filename} (${i.mime}, ${i.size} B) from ${i.from.name} [${i.status}] {${i.wire_id}} sender_id=${i.from.id}`)}return`${n.length} file(s):
|
|
3
|
+
${n.join(`
|
|
4
|
+
`)}`}async function j(e,n,i){await C(e,{recursive:!0,mode:448});let t=await D(e);if(!t.isDirectory()||t.isSymbolicLink())throw new Error("received-files directory is not a safe directory");let s=$(e,`.${M(n)}.${G()}.tmp`),o=await O(s,"wx",384);try{await o.writeFile(i),await o.sync()}catch(r){throw await o.close().catch(()=>{}),await N(s).catch(()=>{}),r}await o.close();try{await v(s,n)}catch(r){throw await N(s).catch(()=>{}),r}}async function re(e,n){let i=[];if(n.IsNil())return{text:"No new files.",files:i};let t=h(e),s=[];for(let o=0;;o++){let r=n.Reduce(o);if(r.IsNil())break;let a=r.Reduce("filename").Visualize(),u=r.Reduce("mime").Visualize()||"application/octet-stream",f=r.Reduce("sender_name").Visualize(),A=r.Reduce("sender_id").Visualize(),F=parseInt(r.Reduce("file_id").Visualize(),10),B=r.Reduce("date").Visualize(),d=r.Reduce("wire_id").Visualize(),c=Buffer.from(r.Reduce("data").GetBinary()),V=S("sha256").update(c).digest("hex"),l=$(t,`${d}-${z(a)}`);await j(t,l,c);let g={file_id:F,wire_id:d,from:{id:A,name:f},filename:a,path:l,mime:u,size:c.length,sha256:V,status:"processed",date:B,kind:p(u,a)?"voice_message":"file",sender:f};if(p(u,a)){let y=w(_.stt),m;if(!y.ready)m={kind:"unconfigured",reason:y.reason};else{let R=await I(c,a,u,_.stt);m=R.ok?{kind:"transcript",text:R.text}:{kind:"failed",error:R.error}}g.transcription=b(y,m,{audioPath:l,wireId:d}),s.push(x({sender:f,wire:d,savedPath:l,sizeBytes:c.length},m)),i.push(g);continue}i.push(g),s.push(` \u2022 ${a} (${u}, ${c.length} B, sha256 ${V}) from ${f} \u2192 ${l} {${d}}`)}return s.length===0?{text:"No new files.",files:i}:{text:`${s.length} new file(s) written to your identity's files dir \u2014 paths + metadata below (bytes stay on disk, never in this result). If your OS user can read the path, use it directly; otherwise use save_file({ wire_id, dest_path }) to stream a copy to a path you can write:
|
|
5
|
+
${s.join(`
|
|
6
|
+
`)}`,files:i}}function se(e){let n=[];if(e.IsNil())return n;for(let i of e.GetKeys()){let t=e.Reduce(i);t.IsNil()||n.push({container_id:typeof i=="string"?i:i.Visualize(),name:t.Reduce("name").Visualize(),queued:parseInt(t.Reduce("queued").Visualize(),10)||0})}return n}function oe(e){let n={};if(e.IsNil())return n;for(let i of e.GetKeys()){let t=e.Reduce(i);t.IsNil()||(n[typeof i=="string"?i:i.Visualize()]={root_cid:t.Reduce("root_cid").Visualize(),root_name:t.Reduce("root_name").Visualize(),role_id:t.Reduce("role_id").Visualize()})}return n}function ae(e){if(!e)return"";let n=e.root_name||e.root_cid;return e.role_id?` [role "${e.role_id}" of ${n}]`:` [root identity of ${n}]`}function q(e){return K(e).toString("base64url")}function ue(e){return P(Buffer.from(e.replace(/\s+/g,""),"base64url"))}var E=new Set(["members","caps"]);function L(e){try{let n=e.GetNumber();return Number.isInteger(n)?n:NaN}catch{return NaN}}function k(e,n){if(e.IsNil())return null;let i;try{i=e.GetKeys()}catch{try{return q(Buffer.from(e.GetBinary()))}catch{}try{return e.GetBoolean()}catch{}try{let t=e.GetNumber();if(!Number.isNaN(t))return t}catch{}return e.Visualize()}if(i.length>0){if(i.map(L).every((r,a)=>r===a))return i.map((r,a)=>k(e.Reduce(a)));let o={};for(let r of i)o[r.Visualize()]=k(e.Reduce(r),r.Visualize());return o}return n!==void 0&&E.has(n)?[]:{}}export{Z as a,ee as b,te as c,ie as d,ne as e,re as f,se as g,oe as h,ae as i,q as j,ue as k,k as l};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{resolve as l,join as i,dirname as p}from"node:path";import{fileURLToPath as m}from"node:url";import*as t from"node:fs";function g(){let o=p(m(import.meta.url)),s=process.env.OURS_UNIT_DIR,c=process.env.OURS_ADVERTISE_MIGRATE==="0",a=n=>c?[`${n}-nocap`]:[n],f=s?a(l(s)):[i(o,"mufl_code"),i(o,"..","mufl_code")].flatMap(a);for(let n of f){if(!t.existsSync(n))continue;let r=t.readdirSync(n).find(e=>e.endsWith(".muflo"));if(r){let e=r.slice(0,-6),d=new Uint8Array(t.readFileSync(i(n,r)));return{dir:n,hash:e,contents:d}}}throw new Error(`no compiled .muflo packet found (looked in: ${f.join(", ")})`+(c?' \u2014 OURS_ADVERTISE_MIGRATE=0 requires a "<dir>-nocap" packet variant (compiled with $advertise = [core.e2e] only); build it or unset the env.':""))}var h;function R(o){h=o}export{g as a,h as b,R as c};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{F as m,J as s,r as c,s as l,u as f}from"./chunk-NQQ4GSVI.js";import{c as o}from"./chunk-Q3UVLSCX.js";import{f as i,i as a}from"./chunk-HSVIKO4D.js";var e=null,n=!1;function v(){e||(e=setInterval(()=>{n||(n=!0,(async()=>{try{for(let t of o.values()){try{await m(async r=>{await s(t,"::actor::gc",{},r)})}catch(r){a(`gc(${t.name}) failed:`,String(r))}await c(t),await l(t),await f(t)}}finally{n=!1}})())},i),e.unref?.(),a(`message GC timer armed (every ${i}ms)`))}function w(){e&&(clearInterval(e),e=null)}export{v as a,w as b};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import*as a from"node:fs";import{join as v}from"node:path";var A="startup-progress.json",b=1,y={initializing:"Initializing daemon",wrapper:"Starting protocol runtime",registrar:"Starting local contact book",identities:"Restoring identities",reconciliation:"Reconciling restored identities",server:"Opening local API",ready:"Daemon ready",failed:"Daemon startup failed"};function h(e){return v(e,A)}function R(e){return typeof e=="string"&&Object.hasOwn(y,e)}function x(e){try{let t=JSON.parse(a.readFileSync(h(e),"utf8"));return t.version!==b||!Number.isInteger(t.pid)||(t.pid??0)<=0||typeof t.bootId!="string"||!t.bootId||!R(t.phase)||!Number.isFinite(t.startedAt)||!Number.isFinite(t.updatedAt)||(t.completed!==void 0||t.total!==void 0)&&(!Number.isInteger(t.completed)||!Number.isInteger(t.total)||(t.completed??-1)<0||(t.total??-1)<0||(t.completed??0)>(t.total??0))?null:t}catch{return null}}function I(e,t={}){let s=t.pid??process.pid,n=t.now??Date.now,o=n(),p=h(e),d=`${p}.${s}.tmp`,u=Math.max(100,t.heartbeatMs??2e3),r=!1,i=!1,l={version:b,pid:s,bootId:`${s}-${o}`,phase:"initializing",startedAt:o,updatedAt:o},c=()=>{if(!i)try{a.mkdirSync(e,{recursive:!0,mode:448}),a.writeFileSync(d,`${JSON.stringify(l)}
|
|
3
|
+
`,{mode:384}),a.renameSync(d,p);try{a.chmodSync(p,384)}catch{}}catch{i=!0;try{a.rmSync(d,{force:!0})}catch{}}},m=(f,S)=>{l={version:b,pid:s,bootId:l.bootId,phase:f,...S?{completed:S.completed,total:S.total}:{},startedAt:o,updatedAt:n()},c()};c();let g=setInterval(()=>{r||(l={...l,updatedAt:n()},c())},u);g.unref?.();let P=f=>{r||(m(f),r=!0,clearInterval(g))};return{update:m,ready:()=>P("ready"),failed:()=>P("failed")}}function w(e){let t=y[e.phase];return e.phase==="identities"&&e.completed!==void 0&&e.total!==void 0?`${t} ${e.completed}/${e.total}`:t}function $(e,t){let s=`startup: ${w(e)}`;return t?`\r${s}\x1B[K`:`${s}
|
|
4
|
+
`}async function O(e){let t=e.now??Date.now,s=e.sleep??(r=>new Promise(i=>setTimeout(i,r))),n=t(),o=n,p=-1,d="",u=null;for(;;){if(await e.isReady())return{ok:!0,elapsedMs:t()-n,lastProgress:u};let r=e.readProgress();if(r?.pid===e.pid){u=r,r.updatedAt>p&&(p=r.updatedAt,o=t());let m=`${r.phase}:${r.completed??""}:${r.total??""}`;if(m!==d&&(d=m,e.onProgress?.(r)),r.phase==="failed")return{ok:!1,reason:"daemon-reported-failure",elapsedMs:t()-n,lastProgress:u}}if(!e.isProcessAlive())return{ok:!1,reason:"process-exited",elapsedMs:t()-n,lastProgress:u};let i=t()-n;if(i>=e.absoluteMs)return{ok:!1,reason:"absolute-timeout",elapsedMs:i,lastProgress:u};if(t()-o>=e.inactivityMs)return{ok:!1,reason:"inactivity-timeout",elapsedMs:i,lastProgress:u};let l=e.absoluteMs-i,c=e.inactivityMs-(t()-o);await s(Math.max(1,Math.min(e.pollMs,l,c)))}}export{A as a,b,h as c,x as d,I as e,w as f,$ as g,O as h};
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import type * as contactsApi from '../api/contacts.js';
|
|
2
|
+
import type * as filesApi from '../api/files.js';
|
|
3
|
+
import type * as identityApi from '../api/identity.js';
|
|
4
|
+
import type * as messagingApi from '../api/messaging.js';
|
|
5
|
+
import type * as profileApi from '../api/profile.js';
|
|
6
|
+
import type { SessionContext } from '../api/types.js';
|
|
7
|
+
/** The argument object of an `OursApi` operation, with `ctx` dropped. */
|
|
8
|
+
type Arg<F> = F extends (ctx: SessionContext, a: infer A) => unknown ? A : never;
|
|
9
|
+
/** The argument object of the one operation that takes no `ctx`. */
|
|
10
|
+
type Arg0<F> = F extends (a: infer A) => unknown ? A : never;
|
|
11
|
+
/** Its settled result. */
|
|
12
|
+
type Res<F> = F extends (...args: never[]) => infer R ? Awaited<R> : never;
|
|
13
|
+
/** `GET /info` and `GET /version` — the frozen introspection body. */
|
|
14
|
+
export interface DaemonInfo {
|
|
15
|
+
name: string;
|
|
16
|
+
version: string;
|
|
17
|
+
compat: number;
|
|
18
|
+
protocol: number;
|
|
19
|
+
pid: number;
|
|
20
|
+
stateDir: string;
|
|
21
|
+
}
|
|
22
|
+
/** `GET /state-dir` — the unauthenticated subset. */
|
|
23
|
+
export interface DaemonStateDir {
|
|
24
|
+
stateDir: string;
|
|
25
|
+
version: string;
|
|
26
|
+
compat: number;
|
|
27
|
+
}
|
|
28
|
+
/** One row of `GET /identities` (the daemon's own liveness view, not the tree). */
|
|
29
|
+
export interface DaemonIdentityRow {
|
|
30
|
+
name: string;
|
|
31
|
+
temporary?: boolean;
|
|
32
|
+
stale?: boolean;
|
|
33
|
+
}
|
|
34
|
+
/** One page of `GET /identities/<name>/notifications`. */
|
|
35
|
+
export interface NotificationPage {
|
|
36
|
+
cursor: number;
|
|
37
|
+
events: Array<Record<string, unknown>>;
|
|
38
|
+
}
|
|
39
|
+
export interface OursClientOptions {
|
|
40
|
+
/** The daemon's base URL, e.g. `http://127.0.0.1:3050`. */
|
|
41
|
+
url: string;
|
|
42
|
+
/**
|
|
43
|
+
* This client's connector lease token (`x-ours-lease-token`). It IS the
|
|
44
|
+
* session: two clients sharing a token share a binding, and two clients with
|
|
45
|
+
* different tokens are different sessions to every session-scoped operation.
|
|
46
|
+
*/
|
|
47
|
+
leaseToken: string;
|
|
48
|
+
/**
|
|
49
|
+
* The client process's pid (`x-ours-client-pid`). Liveness is OS-authoritative
|
|
50
|
+
* on the daemon side, so this must be a pid that dies when this client does.
|
|
51
|
+
* Defaults to `process.pid`.
|
|
52
|
+
*/
|
|
53
|
+
clientPid?: number;
|
|
54
|
+
/** The daemon's API token, when `apiVisibility` is not `open`. */
|
|
55
|
+
apiToken?: string;
|
|
56
|
+
/**
|
|
57
|
+
* Injected `fetch`, for hosts that need a proxy agent or a test double. The
|
|
58
|
+
* same seam Tasks 13 and 14 used for the MCP transport and the connector's
|
|
59
|
+
* stdio — the SDK never reaches for an ambient global it cannot be given.
|
|
60
|
+
*/
|
|
61
|
+
fetch?: typeof globalThis.fetch;
|
|
62
|
+
}
|
|
63
|
+
export declare class OursClient {
|
|
64
|
+
private readonly base;
|
|
65
|
+
private readonly leaseToken;
|
|
66
|
+
private readonly clientPid;
|
|
67
|
+
private readonly apiToken;
|
|
68
|
+
private readonly fetchImpl;
|
|
69
|
+
constructor(opts: OursClientOptions);
|
|
70
|
+
private headers;
|
|
71
|
+
/**
|
|
72
|
+
* The one place an operation crosses the wire. Reconstructs an `OursError`
|
|
73
|
+
* from `{error: {code, message}}` so `.message` is byte-identical to what the
|
|
74
|
+
* daemon-side operation raised; anything else with an `error` key is a
|
|
75
|
+
* transport failure and becomes a plain Error.
|
|
76
|
+
*
|
|
77
|
+
* THE STATUS IS CHECKED TWICE, and both checks are load-bearing:
|
|
78
|
+
*
|
|
79
|
+
* 1. The `{code, message}` OBJECT shape is reconstructed ONLY at 400, because
|
|
80
|
+
* that is the only status the route ever sends it with
|
|
81
|
+
* (`api-routes.ts:314`; the two 400s at :297 and :301 send a plain string
|
|
82
|
+
* and fall through). Without the status test, anything between here and
|
|
83
|
+
* the daemon — a proxy, a gateway, a captive portal — could answer 502
|
|
84
|
+
* with a body of that shape and have it laundered into a fabricated
|
|
85
|
+
* `OursError`, i.e. into text a user reads as if the engine had said it.
|
|
86
|
+
* 2. A non-2xx WITHOUT an `error` key must not resolve as a result. It used
|
|
87
|
+
* to: a gateway answering `403 {"detail":"Forbidden"}` was returned
|
|
88
|
+
* verbatim as the operation's value, so the failure surfaced as a
|
|
89
|
+
* `TypeError` in the caller's own code, arbitrarily far from the cause.
|
|
90
|
+
*/
|
|
91
|
+
private post;
|
|
92
|
+
/** GET a JSON route that is not part of the typed operation surface. */
|
|
93
|
+
private get;
|
|
94
|
+
createIdentity(a: Arg<typeof identityApi.createIdentity>): Promise<Res<typeof identityApi.createIdentity>>;
|
|
95
|
+
createTemporaryIdentity(a: Arg<typeof identityApi.createTemporaryIdentity>): Promise<Res<typeof identityApi.createTemporaryIdentity>>;
|
|
96
|
+
closeTemporaryIdentityOp(a?: Arg<typeof identityApi.closeTemporaryIdentityOp>): Promise<Res<typeof identityApi.closeTemporaryIdentityOp>>;
|
|
97
|
+
createRootIdentity(a: Arg<typeof identityApi.createRootIdentity>): Promise<Res<typeof identityApi.createRootIdentity>>;
|
|
98
|
+
defineLocalIdentityFile(a: Arg0<typeof identityApi.defineLocalIdentityFile>): Promise<Res<typeof identityApi.defineLocalIdentityFile>>;
|
|
99
|
+
chooseIdentity(a: Arg<typeof identityApi.chooseIdentity>): Promise<Res<typeof identityApi.chooseIdentity>>;
|
|
100
|
+
listIdentities(): Promise<Res<typeof identityApi.listIdentities>>;
|
|
101
|
+
currentIdentity(): Promise<Res<typeof identityApi.currentIdentity>>;
|
|
102
|
+
removeIdentity(a: Arg<typeof identityApi.removeIdentity>): Promise<Res<typeof identityApi.removeIdentity>>;
|
|
103
|
+
/**
|
|
104
|
+
* Hand back every lease this client's token holds. The typed counterpart of the
|
|
105
|
+
* `/mcp` DELETE branch, which was the only release path before — see
|
|
106
|
+
* `src/api/identity.ts`. Idempotent: a token holding nothing gets `[]`.
|
|
107
|
+
*/
|
|
108
|
+
releaseLease(): Promise<Res<typeof identityApi.releaseLease>>;
|
|
109
|
+
generateInvite(a?: Arg<typeof contactsApi.generateInvite>): Promise<Res<typeof contactsApi.generateInvite>>;
|
|
110
|
+
listInvites(): Promise<Res<typeof contactsApi.listInvites>>;
|
|
111
|
+
revokeInvite(a: Arg<typeof contactsApi.revokeInvite>): Promise<Res<typeof contactsApi.revokeInvite>>;
|
|
112
|
+
addContact(a: Arg<typeof contactsApi.addContact>): Promise<Res<typeof contactsApi.addContact>>;
|
|
113
|
+
listContacts(): Promise<Res<typeof contactsApi.listContacts>>;
|
|
114
|
+
listLocalContactBook(): Promise<Res<typeof contactsApi.listLocalContactBook>>;
|
|
115
|
+
setLocalBookPolicy(a: Arg<typeof contactsApi.setLocalBookPolicy>): Promise<Res<typeof contactsApi.setLocalBookPolicy>>;
|
|
116
|
+
removeContact(a: Arg<typeof contactsApi.removeContact>): Promise<Res<typeof contactsApi.removeContact>>;
|
|
117
|
+
renameContact(a: Arg<typeof contactsApi.renameContact>): Promise<Res<typeof contactsApi.renameContact>>;
|
|
118
|
+
respondToIntroduction(a: Arg<typeof contactsApi.respondToIntroduction>): Promise<Res<typeof contactsApi.respondToIntroduction>>;
|
|
119
|
+
setBio(a: Arg<typeof profileApi.setBio>): Promise<Res<typeof profileApi.setBio>>;
|
|
120
|
+
advertiseMigrate(): Promise<Res<typeof profileApi.advertiseMigrate>>;
|
|
121
|
+
setPersona(a: Arg<typeof profileApi.setPersona>): Promise<Res<typeof profileApi.setPersona>>;
|
|
122
|
+
sendMessage(a: Arg<typeof messagingApi.sendMessage>): Promise<Res<typeof messagingApi.sendMessage>>;
|
|
123
|
+
sendFile(a: Arg<typeof messagingApi.sendFile>): Promise<Res<typeof messagingApi.sendFile>>;
|
|
124
|
+
listIncomingMessages(): Promise<Res<typeof messagingApi.listIncomingMessages>>;
|
|
125
|
+
getMessages(): Promise<Res<typeof messagingApi.getMessages>>;
|
|
126
|
+
deferMessages(a: Arg<typeof messagingApi.deferMessages>): Promise<Res<typeof messagingApi.deferMessages>>;
|
|
127
|
+
listIncomingFiles(): Promise<Res<typeof filesApi.listIncomingFiles>>;
|
|
128
|
+
getFiles(a?: Arg<typeof filesApi.getFiles>): Promise<Res<typeof filesApi.getFiles>>;
|
|
129
|
+
/**
|
|
130
|
+
* The save_file fallback probe. It does NOT save anything — a current ours
|
|
131
|
+
* connector intercepts save_file and never forwards it, so reaching the daemon
|
|
132
|
+
* proves the connector is too old (src/api/files.ts). Use `fetchFile` to pull
|
|
133
|
+
* the bytes and write them yourself as your own OS user.
|
|
134
|
+
*/
|
|
135
|
+
saveFileFallbackNotice(a: Arg<typeof filesApi.saveFileFallbackNotice>): Promise<Res<typeof filesApi.saveFileFallbackNotice>>;
|
|
136
|
+
/** `GET /version` (unauthenticated). Same body as `/info`. */
|
|
137
|
+
version(): Promise<DaemonInfo>;
|
|
138
|
+
/** `GET /state-dir` (unauthenticated) — the daemon's REAL state dir. */
|
|
139
|
+
stateDir(): Promise<DaemonStateDir>;
|
|
140
|
+
/**
|
|
141
|
+
* `GET /identities` — the daemon's liveness view (which identities exist, and
|
|
142
|
+
* whether a temporary one is stale). Not `listIdentities`, which is the
|
|
143
|
+
* session-scoped tree.
|
|
144
|
+
*/
|
|
145
|
+
identities(): Promise<DaemonIdentityRow[]>;
|
|
146
|
+
/** `GET /unread` — the content-free unread summary per identity. */
|
|
147
|
+
unread(): Promise<{
|
|
148
|
+
identities: Array<Record<string, unknown>>;
|
|
149
|
+
}>;
|
|
150
|
+
/**
|
|
151
|
+
* Long-poll `GET /identities/<name>/notifications`, yielding each content-free
|
|
152
|
+
* event as it lands. Primes at EOF (the backlog is skipped, matching the
|
|
153
|
+
* route's own `since` contract) unless a cursor is supplied.
|
|
154
|
+
*
|
|
155
|
+
* The daemon holds each request open until an event arrives or its own bounded
|
|
156
|
+
* timeout expires, so this loops rather than polls. Pass an `AbortSignal` to
|
|
157
|
+
* stop it; without one it runs forever, which is what a watcher wants.
|
|
158
|
+
*
|
|
159
|
+
* ABORTING IS A CLEAN STOP, NOT AN ERROR. Because the route long-polls, the
|
|
160
|
+
* signal almost always lands while a request is IN FLIGHT rather than between
|
|
161
|
+
* two of them — `fetch` then rejects with `AbortError`, and an uncaught one
|
|
162
|
+
* escapes the `for await` as an unhandled `DOMException`, in a consumer that
|
|
163
|
+
* did exactly what this docstring told it to. So the loop condition is not
|
|
164
|
+
* enough on its own: an abort caught mid-request returns instead of throwing.
|
|
165
|
+
*/
|
|
166
|
+
watchNotifications(identity: string, opts?: {
|
|
167
|
+
since?: number | 'tip';
|
|
168
|
+
signal?: AbortSignal;
|
|
169
|
+
}): AsyncGenerator<Record<string, unknown>, void, undefined>;
|
|
170
|
+
/**
|
|
171
|
+
* `GET /files/<wireId>` — the raw bytes of a received file, resolved STRICTLY
|
|
172
|
+
* within THIS session's bound identity's own folder (the identity comes from
|
|
173
|
+
* the lease token, never from the URL). Run `getFiles` first: the route serves
|
|
174
|
+
* what is already on disk.
|
|
175
|
+
*/
|
|
176
|
+
fetchFile(wireId: string): Promise<Uint8Array>;
|
|
177
|
+
}
|
|
178
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type Identity } from '../identity/model.js';
|
|
2
|
+
export declare const envelopeDispatch: () => boolean;
|
|
3
|
+
export declare const PROTOCOL_VERSION: number;
|
|
4
|
+
export declare function clusterSweep(root: Identity): Promise<void>;
|
|
5
|
+
export declare function startClusterSweep(): 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-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 PROTOCOL_VERSION,c as clusterSweep,a as envelopeDispatch,d as startClusterSweep};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type Identity } from '../identity/model.js';
|
|
2
|
+
export interface MonitoringStatus {
|
|
3
|
+
enabled: boolean;
|
|
4
|
+
proxyCid: string;
|
|
5
|
+
proxyPending: boolean;
|
|
6
|
+
copiesQueued: number;
|
|
7
|
+
controlQueued: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function manifestCapabilities(id: Identity): string[];
|
|
10
|
+
export declare function buildManifest(root: Identity): Record<string, unknown>;
|
|
11
|
+
export declare function listAgentsFor(root: Identity): Array<Record<string, unknown>>;
|
|
12
|
+
export declare function findAgentOf(root: Identity, ref: string): Identity | null;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
|
+
import{a,b,c,d}from"../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 buildManifest,d as findAgentOf,c as listAgentsFor,a as manifestCapabilities};
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { SttUserConfig } from './transcribe';
|
|
2
|
+
export type ApiVisibility = 'owner' | 'shared' | 'open';
|
|
3
|
+
export declare const API_VISIBILITIES: ApiVisibility[];
|
|
4
|
+
export interface OursConfig {
|
|
5
|
+
brokerUrl: string;
|
|
6
|
+
port: number;
|
|
7
|
+
stateDir: string;
|
|
8
|
+
gcIntervalMs: number;
|
|
9
|
+
autoStart: boolean;
|
|
10
|
+
apiVisibility: ApiVisibility;
|
|
11
|
+
apiToken?: string;
|
|
12
|
+
stt?: SttUserConfig;
|
|
13
|
+
}
|
|
14
|
+
export declare const DEFAULT_CONFIG: OursConfig;
|
|
15
|
+
export declare function configPath(): string;
|
|
16
|
+
export declare function loadConfig(): OursConfig;
|
|
17
|
+
export declare const API_TOKEN_FILENAME = "daemon-token";
|
|
18
|
+
export declare function apiTokenPath(cfg: Pick<OursConfig, 'stateDir'>): string;
|
|
19
|
+
export declare function explicitApiToken(cfg: Pick<OursConfig, 'apiToken'>): string | undefined;
|
|
20
|
+
export interface ResolvedApiToken {
|
|
21
|
+
token: string;
|
|
22
|
+
source: 'env' | 'config' | 'file' | 'generated';
|
|
23
|
+
}
|
|
24
|
+
export declare function resolveApiToken(cfg: Pick<OursConfig, 'stateDir' | 'apiToken'>, opts?: {
|
|
25
|
+
generate?: boolean;
|
|
26
|
+
}): ResolvedApiToken | null;
|
|
27
|
+
export declare function writeConfig(cfg: OursConfig): string;
|
|
28
|
+
export declare const IDENTITY_FILENAME = ".ours-identity";
|
|
29
|
+
export interface IdentityFileOptions {
|
|
30
|
+
name: string;
|
|
31
|
+
force?: boolean;
|
|
32
|
+
exposeLocal?: boolean;
|
|
33
|
+
localAutoAccept?: boolean;
|
|
34
|
+
}
|
|
35
|
+
export declare function buildIdentityFile(opts: IdentityFileOptions): Record<string, unknown>;
|
|
36
|
+
export declare function resolveIdentityFilePath(target: string): string;
|
|
37
|
+
export declare function writeIdentityFile(target: string, opts: IdentityFileOptions, overwrite?: boolean): string;
|
package/dist/config.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,k,l,m}from"./chunk-IB2U7K6Y.js";export{e as API_TOKEN_FILENAME,a as API_VISIBILITIES,b as DEFAULT_CONFIG,j as IDENTITY_FILENAME,f as apiTokenPath,k as buildIdentityFile,c as configPath,g as explicitApiToken,d as loadConfig,h as resolveApiToken,l as resolveIdentityFilePath,i as writeConfig,m as writeIdentityFile};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One JSON-RPC frame, or a batch of them. Deliberately as loose as the wire:
|
|
3
|
+
* this file routes on `id` / `method` / `params.name` and forwards the rest
|
|
4
|
+
* verbatim, so modelling the payload would buy nothing and would drag an MCP
|
|
5
|
+
* type dependency in behind it (see THE MCP SEAM above).
|
|
6
|
+
*/
|
|
7
|
+
export type JsonRpcMessage = Record<string, unknown> | Record<string, unknown>[];
|
|
8
|
+
/**
|
|
9
|
+
* The subset of an MCP transport this connector touches, described
|
|
10
|
+
* structurally. Both of the concrete transports it is given at runtime —
|
|
11
|
+
* `StdioServerTransport` downstream, `StreamableHTTPClientTransport` upstream —
|
|
12
|
+
* satisfy it; neither type is imported.
|
|
13
|
+
*/
|
|
14
|
+
export interface JsonRpcTransportLike {
|
|
15
|
+
onmessage?: (message: JsonRpcMessage) => void;
|
|
16
|
+
onerror?: (error: unknown) => void;
|
|
17
|
+
onclose?: () => void;
|
|
18
|
+
start(): Promise<void>;
|
|
19
|
+
send(message: JsonRpcMessage): Promise<void>;
|
|
20
|
+
close(): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
/** Upstream adds the protocol-version mirror (absent on older SDKs — hence optional). */
|
|
23
|
+
export interface HttpClientTransportLike extends JsonRpcTransportLike {
|
|
24
|
+
setProtocolVersion?(version: string): void;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Construction arguments for the upstream transport. They stay HERE — only the
|
|
28
|
+
* `new` is the host's — because they are behaviour this file depends on: the
|
|
29
|
+
* retry budget below is what the notification-stream escalation is tuned
|
|
30
|
+
* against, and the two headers are the daemon's lease identity.
|
|
31
|
+
*/
|
|
32
|
+
export interface HttpClientTransportInit {
|
|
33
|
+
reconnectionOptions: {
|
|
34
|
+
initialReconnectionDelay: number;
|
|
35
|
+
maxReconnectionDelay: number;
|
|
36
|
+
reconnectionDelayGrowFactor: number;
|
|
37
|
+
maxRetries: number;
|
|
38
|
+
};
|
|
39
|
+
requestInit: {
|
|
40
|
+
headers: Record<string, string>;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export interface TransportFactories {
|
|
44
|
+
/** The downstream (client-facing) stdio server transport. Called once. */
|
|
45
|
+
createStdioServer(): JsonRpcTransportLike;
|
|
46
|
+
/** The upstream (daemon-facing) streamable-HTTP client transport. Called once per connect. */
|
|
47
|
+
createHttpClient(url: URL, init: HttpClientTransportInit): HttpClientTransportLike;
|
|
48
|
+
}
|
|
49
|
+
export interface ProxyOptions {
|
|
50
|
+
/** Daemon MCP endpoint, e.g. http://127.0.0.1:3050/mcp */
|
|
51
|
+
url: string;
|
|
52
|
+
/** The two MCP transports, injected — see THE MCP SEAM above. */
|
|
53
|
+
transports: TransportFactories;
|
|
54
|
+
/** Best-effort: make sure the daemon is listening (called before each connect attempt). */
|
|
55
|
+
ensureDaemon?: () => Promise<void>;
|
|
56
|
+
/** Daemon state dir (per-host); the session-restore store lives under it. Defaults to OURS_STATE_DIR or ~/.ours. */
|
|
57
|
+
stateDir?: string;
|
|
58
|
+
/** Bearer token for the daemon HTTP surface (Part B). Undefined in `open` mode. */
|
|
59
|
+
apiToken?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Called with each get_files RESPONSE frame on its way back to the client, so
|
|
62
|
+
* the host can rewrite the result in place; returns true if it did. ours-mcp
|
|
63
|
+
* injects its MCP-result annotator here (was proxy.ts:139). Absent ⇒ pure
|
|
64
|
+
* passthrough, which is also what an annotator that declines returns.
|
|
65
|
+
*/
|
|
66
|
+
annotateResult?: (message: unknown) => boolean;
|
|
67
|
+
}
|
|
68
|
+
export declare function runProxy(opts: ProxyOptions): Promise<void>;
|