thinkpool-pair 0.7.398 → 0.7.399

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.
@@ -1 +1 @@
1
- const e=(e,t,n,i,r=["claude","codex","hermes"])=>Object.freeze({name:e,description:t,route:n,...i?{inputHint:i}:{},runtimes:Object.freeze(r)});export const CODE_ROOM_COMMANDS=Object.freeze([e("/handoff","save a concise checkpoint or handoff","handoff","optional end goal"),e("/side","ask or investigate without interrupting this terminal","side","task"),e("/help","list commands available in this lane","control"),e("/status","runtime, model, permissions, and busy state","control"),e("/usage","session usage and provider limits","control"),e("/context","current context-window usage","control"),e("/diff","Git changes and branch status","control"),e("/find","find relevant files in this repository","control","query"),e("/compact","compact context","runtime"),e("/clear","clear context · confirms","clear"),e("/model","pick model — opens selector","model"),e("/mode","set permission mode","mode","normal | auto-accept | plan | bypass"),e("/effort","set reasoning effort","effort","none | minimal | low | medium | high | xhigh | max | ultra"),e("/queue","run a prompt after the active turn","queue","prompt"),e("/steer","guide the active turn","steer","prompt",["codex","hermes"]),e("/credits","provider credit balance","credits",null,["codex","hermes"]),e("/review","review uncommitted changes","runtime",null,["codex"])]);const t=Object.freeze({claude:Object.freeze({accept:!0,hidden:Object.freeze(new Set(["/flow"]))}),codex:Object.freeze({accept:!1,hidden:Object.freeze(new Set(["/flow"]))}),hermes:Object.freeze({accept:!0,hidden:Object.freeze(new Set(["/flow","/reasoning"]))})}),n=e=>{const t=(e=>{const t=`/${String(("string"==typeof e?e:e?.name)||"").trim().replace(/^\/+/,"")}`;return/^\/[A-Za-z0-9][A-Za-z0-9:_-]*$/.test(t)?t:""})(e);if(!t)return null;if("string"==typeof e)return{name:t,description:"runtime command",route:"runtime"};const n=String(e?.description||"").trim()||"runtime command",i=String(e?.inputHint||e?.input_hint||e?.input?.hint||"").trim();return{name:t,description:n,route:String(e?.route||"").trim()||"runtime",...i?{inputHint:i}:{}}};export function commandCatalogForRuntime(e,i=[]){const r=(e=>"thinkpool"===e?"hermes":e)(e),o=t[r]||t.codex,c=new Map;for(const e of CODE_ROOM_COMMANDS)e.runtimes.includes(r)&&c.set(e.name,{name:e.name,description:e.description,route:e.route,...e.inputHint?{inputHint:e.inputHint}:{}});for(const e of Array.isArray(i)?i:[]){const t=n(e);if(!t||!o.accept||o.hidden.has(t.name))continue;const i=c.get(t.name),s="hermes"===r&&["/help","/status","/context","/credits"].includes(t.name);c.set(t.name,i?{...t,...i,description:"runtime command"===t.description?i.description:t.description,...t.inputHint?{inputHint:t.inputHint}:{},...s?{route:"runtime"}:{}}:t)}return[...c.values()]}export const commandNeedsInput=e=>!!String(e?.inputHint||"").trim();export const commandRoute=e=>String(e?.route||"runtime");export function commandHelpLine(e){return(Array.isArray(e)?e:[]).map(e=>`${e.name}${e.inputHint?` <${e.inputHint}>`:""}`).join(" ")}export function normalizePermissionMode(e){const t=String(e||"").trim().toLowerCase().replace(/[\s_-]+/g,"");return["normal","default","manual"].includes(t)?"default":["auto","autoaccept","autoacceptedits","acceptedits"].includes(t)?"acceptEdits":"plan"===t?"plan":["bypass","bypasspermissions","fullauto"].includes(t)?"bypassPermissions":null}export function reconcileCommandCatalog({current:e,incoming:t,onChanged:n,onLifecycle:i}={}){const r=Array.isArray(t)&&t.length>0,o=r&&JSON.stringify(e||[])===JSON.stringify(t);return r&&!o&&n?.(t),i?.({duplicate:o,hasIncoming:r}),o}
1
+ const e=(e,t,n,i,r=["claude","codex","hermes","opencode"])=>Object.freeze({name:e,description:t,route:n,...i?{inputHint:i}:{},runtimes:Object.freeze(r)});export const CODE_ROOM_COMMANDS=Object.freeze([e("/handoff","save a concise checkpoint or handoff","handoff","optional end goal"),e("/side","ask or investigate without interrupting this terminal","side","task"),e("/help","list commands available in this lane","control"),e("/status","runtime, model, permissions, and busy state","control"),e("/usage","session usage and provider limits","control"),e("/context","current context-window usage","control"),e("/diff","Git changes and branch status","control"),e("/find","find relevant files in this repository","control","query"),e("/compact","compact context","runtime"),e("/clear","clear context · confirms","clear"),e("/model","pick model — opens selector","model"),e("/mode","set permission mode","mode","normal | auto-accept | plan | bypass"),e("/effort","set reasoning effort","effort","none | minimal | low | medium | high | xhigh | max | ultra"),e("/queue","run a prompt after the active turn","queue","prompt"),e("/steer","guide the active turn","steer","prompt",["codex","hermes"]),e("/credits","provider credit balance","credits",null,["codex","hermes"]),e("/review","review uncommitted changes","runtime",null,["codex"])]);const t=Object.freeze({claude:Object.freeze({accept:!0,hidden:Object.freeze(new Set(["/flow"]))}),codex:Object.freeze({accept:!1,hidden:Object.freeze(new Set(["/flow"]))}),hermes:Object.freeze({accept:!0,hidden:Object.freeze(new Set(["/flow","/reasoning"]))})}),n=e=>{const t=(e=>{const t=`/${String(("string"==typeof e?e:e?.name)||"").trim().replace(/^\/+/,"")}`;return/^\/[A-Za-z0-9][A-Za-z0-9:_-]*$/.test(t)?t:""})(e);if(!t)return null;if("string"==typeof e)return{name:t,description:"runtime command",route:"runtime"};const n=String(e?.description||"").trim()||"runtime command",i=String(e?.inputHint||e?.input_hint||e?.input?.hint||"").trim();return{name:t,description:n,route:String(e?.route||"").trim()||"runtime",...i?{inputHint:i}:{}}};export function commandCatalogForRuntime(e,i=[]){const r=(e=>"thinkpool"===e?"hermes":e)(e),o=t[r]||t.codex,c=new Map;for(const e of CODE_ROOM_COMMANDS)e.runtimes.includes(r)&&c.set(e.name,{name:e.name,description:e.description,route:e.route,...e.inputHint?{inputHint:e.inputHint}:{}});for(const e of Array.isArray(i)?i:[]){const t=n(e);if(!t||!o.accept||o.hidden.has(t.name))continue;const i=c.get(t.name),s="hermes"===r&&["/help","/status","/context","/credits"].includes(t.name);c.set(t.name,i?{...t,...i,description:"runtime command"===t.description?i.description:t.description,...t.inputHint?{inputHint:t.inputHint}:{},...s?{route:"runtime"}:{}}:t)}return[...c.values()]}export const commandNeedsInput=e=>!!String(e?.inputHint||"").trim();export const commandRoute=e=>String(e?.route||"runtime");export function commandHelpLine(e){return(Array.isArray(e)?e:[]).map(e=>`${e.name}${e.inputHint?` <${e.inputHint}>`:""}`).join(" ")}export function normalizePermissionMode(e){const t=String(e||"").trim().toLowerCase().replace(/[\s_-]+/g,"");return["normal","default","manual"].includes(t)?"default":["auto","autoaccept","autoacceptedits","acceptedits"].includes(t)?"acceptEdits":"plan"===t?"plan":["bypass","bypasspermissions","fullauto"].includes(t)?"bypassPermissions":null}export function reconcileCommandCatalog({current:e,incoming:t,onChanged:n,onLifecycle:i}={}){const r=Array.isArray(t)&&t.length>0,o=r&&JSON.stringify(e||[])===JSON.stringify(t);return r&&!o&&n?.(t),i?.({duplicate:o,hasIncoming:r}),o}
package/lane-worktree.mjs CHANGED
@@ -1 +1 @@
1
- import{execFileSync as r}from"node:child_process";import e from"node:path";import t from"node:fs";const o=[".env.local",".env.development.local"];export function linkLocalEnvIntoWorktree({root:r,dir:n,fsImpl:i=t}={}){const a=[];for(const t of o){const o=e.join(r,t),c=e.join(n,t);try{if(!i.existsSync?.(o)||i.existsSync?.(c))continue;i.symlinkSync?.(o,c),a.push(t)}catch{}}return a}export function createManagedLaneWorktree({terminalId:r,cwd:o=process.cwd(),git:i=n,fsImpl:a=t}={}){const c=String(r||""),s=c.replace(/[^a-zA-Z0-9]/g,"").slice(0,8);if(!s)throw new Error("terminal id required for managed worktree");const m=String(i(["rev-parse","--show-toplevel"],o)||"").trim();if(!m)throw new Error("not a git repository");const l=e.join(m,".thinkpool","worktrees",`terminal-${s}`),d=`thinkpool/terminal/${s}`,p=function({root:r,git:e}){for(const t of["origin/HEAD","origin/main","origin/master","main","master","HEAD"])try{if(String(e(["rev-parse","--verify","--quiet",t],r)||"").trim())return t}catch{}return"HEAD"}({root:m,git:i});return a.mkdirSync(e.dirname(l),{recursive:!0}),i(["worktree","add","-b",d,l,p],m),linkLocalEnvIntoWorktree({root:m,dir:l,fsImpl:a}),{terminalId:c,root:m,dir:l,branch:d}}export function removeManagedLaneWorktree({terminalId:r,managedWorktree:t,git:o=n}={}){const i=String(r||""),a=t&&"object"==typeof t?t:null;if(!i||!a||a.terminalId!==i)return{removed:!1,reason:"not managed by this terminal"};const c=e.resolve(String(a.root||"")),s=e.resolve(String(a.dir||"")),m=String(a.branch||""),l=e.join(c,".thinkpool","worktrees"),d=i.replace(/[^a-zA-Z0-9]/g,"").slice(0,8);if(!c||s===l||!s.startsWith(l+e.sep))return{removed:!1,reason:"path outside managed worktrees"};if(!d||!e.basename(s).includes(d)||!m.startsWith(`thinkpool/terminal/${d}`))return{removed:!1,reason:"ownership marker mismatch"};try{o(["worktree","remove",s,"--force"],c)}catch{}try{o(["branch","-D",m],c)}catch{}return{removed:!0,dir:s,branch:m}}function n(e,t){return r("git",e,{cwd:t,stdio:["ignore","pipe","pipe"],encoding:"utf8"})}
1
+ import{execFileSync as r}from"node:child_process";import e from"node:path";import t from"node:fs";const o=[".env.local",".env.development.local"];export function linkLocalEnvIntoWorktree({root:r,dir:n,fsImpl:i=t}={}){const a=[];for(const t of o){const o=e.join(r,t),s=e.join(n,t);try{if(!i.existsSync?.(o)||i.existsSync?.(s))continue;i.symlinkSync?.(o,s),a.push(t)}catch{}}return a}export function createManagedLaneWorktree({terminalId:r,cwd:o=process.cwd(),baseSha:i=null,git:a=n,fsImpl:s=t}={}){const c=String(r||""),l=c.replace(/[^a-zA-Z0-9]/g,"").slice(0,8);if(!l)throw new Error("terminal id required for managed worktree");const m=String(a(["rev-parse","--show-toplevel"],o)||"").trim();if(!m)throw new Error("not a git repository");const d=e.join(m,".thinkpool","worktrees",`terminal-${l}`),p=`thinkpool/terminal/${l}`,h=null==i?function({root:r,git:e}){for(const t of["origin/HEAD","origin/main","origin/master","main","master","HEAD"])try{if(String(e(["rev-parse","--verify","--quiet",t],r)||"").trim())return t}catch{}return"HEAD"}({root:m,git:a}):function({root:r,baseSha:e,git:t}){const o=String(e||"").trim().toLowerCase();if(!/^[a-f0-9]{40}$/.test(o))throw new Error("exact base SHA required for checkpoint branch");let n="";try{n=String(t(["rev-parse","--verify",`${o}^{commit}`],r)||"").trim().toLowerCase()}catch{}if(n!==o)throw new Error("checkpoint base SHA is unavailable in this repository");return o}({root:m,baseSha:i,git:a});return s.mkdirSync(e.dirname(d),{recursive:!0}),a(["worktree","add","-b",p,d,h],m),linkLocalEnvIntoWorktree({root:m,dir:d,fsImpl:s}),{terminalId:c,root:m,dir:d,branch:p,...null==i?{}:{baseSha:h}}}export function removeManagedLaneWorktree({terminalId:r,managedWorktree:t,git:o=n}={}){const i=String(r||""),a=t&&"object"==typeof t?t:null;if(!i||!a||a.terminalId!==i)return{removed:!1,reason:"not managed by this terminal"};const s=e.resolve(String(a.root||"")),c=e.resolve(String(a.dir||"")),l=String(a.branch||""),m=e.join(s,".thinkpool","worktrees"),d=i.replace(/[^a-zA-Z0-9]/g,"").slice(0,8);if(!s||c===m||!c.startsWith(m+e.sep))return{removed:!1,reason:"path outside managed worktrees"};if(!d||!e.basename(c).includes(d)||!l.startsWith(`thinkpool/terminal/${d}`))return{removed:!1,reason:"ownership marker mismatch"};try{o(["worktree","remove",c,"--force"],s)}catch{}try{o(["branch","-D",l],s)}catch{}return{removed:!0,dir:c,branch:l}}function n(e,t){return r("git",e,{cwd:t,stdio:["ignore","pipe","pipe"],encoding:"utf8"})}
package/launcher.mjs CHANGED
@@ -1 +1 @@
1
- import e from"node:os";import n from"node:fs";import t from"node:path";import{execSync as r}from"node:child_process";import{detectProvider as i,fetchModels as o,ANTHROPIC_COMPATIBLE as a,gatewayHint as s}from"./byok-detect.mjs";import{probeHermesRuntime as l}from"./hermes-probe.mjs";import{darwinServiceRunning as c,serviceRuntimeVersion as p}from"./service.mjs";import{loadKeepAwakePreference as d}from"./keep-awake.mjs";const u=e.homedir(),m=t.join(u,".thinkpool-pair"),h=(()=>{try{return JSON.parse(n.readFileSync(new URL("./package.json",import.meta.url),"utf8")).version}catch{return null}})();export const KNOWN_AGENTS=[{label:"Claude Code",cmd:"claude",resume:["--continue"]},{label:"Codex",cmd:"codex"},{label:"Hermes",cmd:"thinkpool"}];function k(e){const r="win32"===process.platform?(process.env.PATHEXT||".EXE;.CMD;.BAT;.COM").split(";"):[""];for(const i of(process.env.PATH||"").split(t.delimiter))if(i)for(const o of r)try{if(n.existsSync(t.join(i,e+o)))return!0}catch{}return!1}function f(e){try{return JSON.parse(n.readFileSync(e,"utf8"))}catch{return null}}export function detectState(){const e=f(t.join(m,"auth.json")),i=f(t.join(m,"provider.json")),o=!!i?.provider&&"anthropic"!==i.provider,a=k("hermes"),s=k("thinkpool")&&l().available,v=function(e){const i=e?`io.thinkpool.pair.${e.toLowerCase()}`:"io.thinkpool.pair.account";try{if("darwin"===process.platform){const e=r(`launchctl print gui/$(id -u)/${i}`,{encoding:"utf8",stdio:["ignore","pipe","ignore"]});return c(e)}return"linux"===process.platform?(r(`systemctl --user is-active --quiet ${i}.service`),!0):n.existsSync(function(e){const n=e?`io.thinkpool.pair.${e.toLowerCase()}`:"io.thinkpool.pair.account";if("darwin"===process.platform)return t.join(u,"Library","LaunchAgents",`${n}.plist`);if("linux"===process.platform)return t.join(u,".config","systemd","user",`${n}.service`);const r=t.join(process.env.APPDATA||t.join(u,"AppData","Roaming"),"Microsoft","Windows","Start Menu","Programs","Startup");return t.join(r,`thinkpool-pair-${e||"account"}.cmd`)}(e))}catch{return!1}}(null),g=!!e?.reconnect_required;return{loggedIn:!!e?.refresh_token&&!g,reconnectRequired:g,email:e?.email||e?.user?.email||null,provider:o?`Custom (${i.baseUrl||"endpoint"})`:"Anthropic (default)",providerModel:o&&i.model||null,agents:KNOWN_AGENTS.filter(e=>k(e.cmd)&&("thinkpool"!==e.cmd||s)),hermesInstalled:a,hermesReady:s,accountSvc:v,keepAwake:d(),serviceVersion:v?p(null):null,platform:process.platform,cwd:process.cwd(),version:h}}const v=e=>`${e}`,g=e=>`${e}`,y=e=>`${e}`,w=e=>`${e}`,b=e=>`${e}`;export async function runLauncher({actions:e,io:n,state:t=detectState(),refresh:r=null}){const l=e=>({...e,agents:Array.isArray(e?.agents)?e.agents:[],loggedIn:!!e?.loggedIn,reconnectRequired:!!e?.reconnectRequired,accountSvc:!!e?.accountSvc,keepAwake:!0===e?.keepAwake,serviceVersion:"string"==typeof e?.serviceVersion&&e.serviceVersion?e.serviceVersion:null,platform:e?.platform||process.platform,provider:e?.provider||"Anthropic (default)",cwd:e?.cwd||process.cwd(),version:e?.version||h});t=l(t);const c=()=>{r&&(t=l(r()))},p=async(e,t,r=1)=>{t.forEach((e,t)=>n.print(` ${y(String(t+1))}) ${e.label}${e.hint?" "+v(e.hint):""}`));const i=await n.ask(`\n ${e} ${v(`[${r}]`)} ${y("▸")} `),o=parseInt(i,10);return Number.isInteger(o)&&o>=1&&o<=t.length?o-1:r-1},d=async(e,t=!0)=>{const r=(await n.ask(` ${e} ${v(t?"[Y/n]":"[y/N]")} ${y("▸")} `)).toLowerCase();return r?"y"===r[0]:t},u=()=>{n.print(""),n.print(" "+v("┌ ")+g("thinkpool-pair")+v(" "+"─".repeat(40))),n.print(` ${v("│ launcher ")} ${t.version?`v${t.version}`:"version unavailable"}`),n.print(` ${v("│ account ")} ${t.reconnectRequired?b("reconnect required"):t.loggedIn?w((t.email||"linked")+" ✓"):b("not linked")}`),n.print(` ${v("│ agents ")} ${t.agents.length?t.agents.map(e=>e.label).join(", "):b("none ready: install Claude Code, Codex, or Hermes")}`),n.print(` ${v("│ directory")} ${v(t.cwd)}`);const e=t.accountSvc?"win32"===t.platform?w("startup entry installed"):w("running"+(t.serviceVersion?` v${t.serviceVersion}`:" (version unavailable)")):"not installed";n.print(` ${v("│ bridge ")} ${e}`),n.print(` ${v("│ keep awake")} ${t.keepAwake?w("on")+v(", display may still dim"):"off"}`),n.print(" "+v("└"+"─".repeat(54))+"\n")},m=async()=>!!t.loggedIn||(n.print("\n "+b(t.reconnectRequired?"This bridge lost its thinkpool account link.":"You are not linked to a thinkpool account yet.")),await d(" Link this device now?",!0)&&(await e.login(),c()),!!t.loggedIn||(n.print(" "+b("login needed to serve your sessions — back to menu")),!1)),k=async()=>!!t.agents.length||(n.print("\n "+b("No coding agent is ready on this computer")),n.print(" thinkpool connects an agent already installed on this machine. It does not"),n.print(" include one. Install and configure at least one of:"),n.print(`\n ${y("Claude Code")} command: claude`),n.print(` ${y("Codex")} command: codex`),n.print(` ${y("Hermes")} command: hermes, then set up its thinkpool profile here`),n.print("\n "+g("BYOK does not replace the agent. It only gives an installed agent")),n.print(" credentials for a model provider."),n.print("\n Install one, then reopen this launcher."),!1),f=async()=>{const r=t.provider+(t.providerModel?`, model ${t.providerModel}`:"");n.print("\n "+v("Provider settings supply model credentials. Claude Code, Codex, or Hermes must still be installed locally."));const l=await p("\n provider",[{label:"Anthropic (default)",hint:"regular Claude login"},{label:"Paste a key, pick a model",hint:"auto-detects the provider · OpenRouter = any model"},{label:"Custom endpoint",hint:"enter a base url + token by hand"},{label:"← Back",hint:`current: ${r}`}],4);if(3===l)return;if(0===l)return await e.setProvider({kind:"anthropic"}),c(),void n.print("\n "+w("✓ back on regular Claude."));if(1===l){const t=(await n.ask(`\n Paste your API key ${v("(blank to cancel)")} ${y("▸")} `)).trim();if(!t)return void n.print(" "+b("cancelled — provider unchanged"));const r=i(t);if(!r.compatible)return void n.print("\n "+b(s(r.name)));const l=a[r.id];n.print(`\n ${w("✓ detected "+l.name)} ${v("— fetching models…")}`);const d=await o({modelsUrl:l.models,key:t,auth:l.auth});let u;if(0===d.length)u=(await n.ask(` Couldn't list models. Model id ${v("(blank = endpoint default)")} ${y("▸")} `)).trim()||void 0;else if(d.length<=40){const e=await p("\n model",d.map(e=>({label:e})),1);u=d[e]}else for(n.print(` ${v(d.length+" models available, e.g. "+d.slice(0,3).join(", ")+"…")}`);;){const e=(await n.ask(` Type a model id or part of it ${v("(blank to cancel)")} ${y("▸")} `)).trim();if(!e)return void n.print(" "+b("cancelled — provider unchanged"));const t=d.filter(n=>n.toLowerCase().includes(e.toLowerCase()));if(0!==t.length){if(1===t.length){u=t[0];break}if(t.length<=40){const e=await p("\n pick",t.map(e=>({label:e})),1);u=t[e];break}n.print(` ${b(t.length+" matches — narrow it down")}`)}else n.print(" "+b("no match — try again"))}return await e.setProvider({kind:"custom",base:l.base,token:t,model:u}),c(),void n.print(`\n ${w("✓ provider set.")}\n ${l.name}\n model: ${u||"(endpoint default)"}`)}const d=(await n.ask(`\n Base url ${v("(blank to cancel · SDK appends /v1/messages)")} ${y("▸")} `)).trim();if(!d)return void n.print(" "+b("cancelled — provider unchanged"));const u=(await n.ask(` API token ${v("(blank to cancel)")} ${y("▸")} `)).trim();if(!u)return void n.print(" "+b("cancelled — provider unchanged"));const m=(await n.ask(` Model ${v("(blank = endpoint default · e.g. glm-4.6)")} ${y("▸")} `)).trim();await e.setProvider({kind:"custom",base:d,token:u,model:m||void 0}),c(),n.print(`\n ${w("✓ provider set to custom.")}\n base url: ${t.provider}\n model: ${t.providerModel||"(endpoint default)"}`)},$=async()=>{for(;;){const r=[{key:"provider",label:"Provider",hint:`current: ${t.provider}`},{key:"account",label:"Account",hint:t.reconnectRequired?"reconnect required":t.loggedIn?`linked: ${t.email||"yes"}`:"not linked"},{key:"awake",label:"Keep computer awake",hint:(t.keepAwake?"ON":"off")+" · the screen can still dim, lock, and turn off"}];t.hermesInstalled&&r.push({key:"hermes",label:t.hermesReady?"Hermes profile":"Set up Hermes",hint:t.hermesReady?"isolated profile ready":"set up isolated profile + delegation guard"}),r.push({key:"back",label:"Back to main menu",hint:""});const i=r[await p("\n change",r,r.length)];if("back"===i.key)return;if("provider"===i.key)await f();else{if("account"===i.key)return await e.login(),void c();if("awake"===i.key)if(t.keepAwake){if(!1===await e.setKeepAwake({enabled:!1}))continue;t={...t,keepAwake:!1},c(),n.print("\n "+w("✓ keep-awake is off. The computer may sleep normally."))}else if(n.print("\n "+b("Important: keep-awake changes this computer’s power behavior")),n.print(" While the bridge runs, thinkpool will prevent the computer itself from"),n.print(" automatically sleeping. This can use substantially more battery and may"),n.print(" also block suspend requests on some Linux systems."),n.print("\n "+w("It does NOT keep the screen on. Display dimming, screen locking, and")),n.print(" display sleep continue to work normally. Closing a laptop lid may still"),n.print(" sleep it, depending on the operating system and power settings."),await d("\n Enable keep-awake while the thinkpool bridge runs?",!1)){if(!1===await e.setKeepAwake({enabled:!0}))continue;t={...t,keepAwake:!0},c(),n.print("\n "+w("✓ keep-awake is on. Your screen is still free to dim and turn off."))}else n.print("\n "+b("unchanged: keep-awake remains off."));else if("hermes"===i.key){const n=await p("\n Hermes profile",[{label:"Clone active profile",hint:"copies provider/config explicitly; fresh thinkpool session history"},{label:"Create clean profile",hint:"no copied credentials or bundled skills; configure provider afterward"},{label:"Back",hint:""}],3);2!==n&&(await e.setupHermes({mode:0===n?"clone":"clean"}),c())}}}};for(;;){u(),n.print(" "+g("What do you want to do?")+"\n");const r=t.accountSvc?["win32"===t.platform?{key:"restart",label:"Update startup entry",hint:"installs the latest version; relaunch the bridge window to apply"}:{key:"restart",label:"Restart & update bridge",hint:"install the latest published version; sessions resume"},{key:"uninstall",label:"Remove background service",hint:"stop serving your sessions on this device"}]:[{key:"serve",label:"Serve all my sessions",hint:"runs here, Ctrl-C stops it"},{key:"service",label:"Always-on background service",hint:"recommended — survives reboot, restarts on crash"}];r.push({key:"settings",label:"Settings",hint:`provider · account · keep-awake ${t.keepAwake?"ON":"off"}${t.hermesInstalled?" · Hermes profile":""}`}),r.push({key:"quit",label:"Quit",hint:""});const i=r[await p("choose",r)];if("quit"===i.key)return;if("serve"===i.key)await k()&&await m()&&await e.serveAccountForeground();else if("service"===i.key){if(await k()&&await m()){if(!0===await e.installService({room:null})&&(!e.relaunchLauncher||await e.relaunchLauncher()))return;c()}}else if("restart"===i.key){if(!0===await e.restartUpdateService({room:null})&&(!e.relaunchLauncher||await e.relaunchLauncher()))return;c()}else"uninstall"===i.key?(await e.uninstallService({room:null}),c()):"settings"===i.key&&await $();await n.ask("\n "+v("press Enter to return to the menu…"))}}
1
+ import e from"node:os";import n from"node:fs";import t from"node:path";import{execSync as r}from"node:child_process";import{detectProvider as o,fetchModels as i,ANTHROPIC_COMPATIBLE as a,gatewayHint as s}from"./byok-detect.mjs";import{probeHermesRuntime as l}from"./hermes-probe.mjs";import{probeOpenCodeRuntime as c}from"./opencode-probe.mjs";import{darwinServiceRunning as p,serviceRuntimeVersion as d}from"./service.mjs";import{loadKeepAwakePreference as u}from"./keep-awake.mjs";const m=e.homedir(),h=t.join(m,".thinkpool-pair"),k=(()=>{try{return JSON.parse(n.readFileSync(new URL("./package.json",import.meta.url),"utf8")).version}catch{return null}})();export const KNOWN_AGENTS=[{label:"Claude Code",cmd:"claude",resume:["--continue"]},{label:"Codex",cmd:"codex"},{label:"Hermes",cmd:"thinkpool"},{label:"OpenCode",cmd:"opencode"}];function f(e){const r="win32"===process.platform?(process.env.PATHEXT||".EXE;.CMD;.BAT;.COM").split(";"):[""];for(const o of(process.env.PATH||"").split(t.delimiter))if(o)for(const i of r)try{if(n.existsSync(t.join(o,e+i)))return!0}catch{}return!1}function v(e){try{return JSON.parse(n.readFileSync(e,"utf8"))}catch{return null}}export function detectState(){const e=v(t.join(h,"auth.json")),o=v(t.join(h,"provider.json")),i=!!o?.provider&&"anthropic"!==o.provider,a=f("hermes"),s=f("thinkpool")&&l().available,g=f("opencode")&&c().available,y=function(e){const o=e?`io.thinkpool.pair.${e.toLowerCase()}`:"io.thinkpool.pair.account";try{if("darwin"===process.platform){const e=r(`launchctl print gui/$(id -u)/${o}`,{encoding:"utf8",stdio:["ignore","pipe","ignore"]});return p(e)}return"linux"===process.platform?(r(`systemctl --user is-active --quiet ${o}.service`),!0):n.existsSync(function(e){const n=e?`io.thinkpool.pair.${e.toLowerCase()}`:"io.thinkpool.pair.account";if("darwin"===process.platform)return t.join(m,"Library","LaunchAgents",`${n}.plist`);if("linux"===process.platform)return t.join(m,".config","systemd","user",`${n}.service`);const r=t.join(process.env.APPDATA||t.join(m,"AppData","Roaming"),"Microsoft","Windows","Start Menu","Programs","Startup");return t.join(r,`thinkpool-pair-${e||"account"}.cmd`)}(e))}catch{return!1}}(null),w=!!e?.reconnect_required;return{loggedIn:!!e?.refresh_token&&!w,reconnectRequired:w,email:e?.email||e?.user?.email||null,provider:i?`Custom (${o.baseUrl||"endpoint"})`:"Anthropic (default)",providerModel:i&&o.model||null,agents:KNOWN_AGENTS.filter(e=>f(e.cmd)&&("thinkpool"!==e.cmd||s)&&("opencode"!==e.cmd||g)),hermesInstalled:a,hermesReady:s,opencodeReady:g,accountSvc:y,keepAwake:u(),serviceVersion:y?d(null):null,platform:process.platform,cwd:process.cwd(),version:k}}const g=e=>`${e}`,y=e=>`${e}`,w=e=>`${e}`,b=e=>`${e}`,$=e=>`${e}`;export async function runLauncher({actions:e,io:n,state:t=detectState(),refresh:r=null}){const l=e=>({...e,agents:Array.isArray(e?.agents)?e.agents:[],loggedIn:!!e?.loggedIn,reconnectRequired:!!e?.reconnectRequired,accountSvc:!!e?.accountSvc,keepAwake:!0===e?.keepAwake,serviceVersion:"string"==typeof e?.serviceVersion&&e.serviceVersion?e.serviceVersion:null,platform:e?.platform||process.platform,provider:e?.provider||"Anthropic (default)",cwd:e?.cwd||process.cwd(),version:e?.version||k});t=l(t);const c=()=>{r&&(t=l(r()))},p=async(e,t,r=1)=>{t.forEach((e,t)=>n.print(` ${w(String(t+1))}) ${e.label}${e.hint?" "+g(e.hint):""}`));const o=await n.ask(`\n ${e} ${g(`[${r}]`)} ${w("▸")} `),i=parseInt(o,10);return Number.isInteger(i)&&i>=1&&i<=t.length?i-1:r-1},d=async(e,t=!0)=>{const r=(await n.ask(` ${e} ${g(t?"[Y/n]":"[y/N]")} ${w("▸")} `)).toLowerCase();return r?"y"===r[0]:t},u=()=>{n.print(""),n.print(" "+g("┌ ")+y("thinkpool-pair")+g(" "+"─".repeat(40))),n.print(` ${g("│ launcher ")} ${t.version?`v${t.version}`:"version unavailable"}`),n.print(` ${g("│ account ")} ${t.reconnectRequired?$("reconnect required"):t.loggedIn?b((t.email||"linked")+" ✓"):$("not linked")}`),n.print(` ${g("│ agents ")} ${t.agents.length?t.agents.map(e=>e.label).join(", "):$("none ready: install Claude Code, Codex, or Hermes")}`),n.print(` ${g("│ directory")} ${g(t.cwd)}`);const e=t.accountSvc?"win32"===t.platform?b("startup entry installed"):b("running"+(t.serviceVersion?` v${t.serviceVersion}`:" (version unavailable)")):"not installed";n.print(` ${g("│ bridge ")} ${e}`),n.print(` ${g("│ keep awake")} ${t.keepAwake?b("on")+g(", display may still dim"):"off"}`),n.print(" "+g("└"+"─".repeat(54))+"\n")},m=async()=>!!t.loggedIn||(n.print("\n "+$(t.reconnectRequired?"This bridge lost its thinkpool account link.":"You are not linked to a thinkpool account yet.")),await d(" Link this device now?",!0)&&(await e.login(),c()),!!t.loggedIn||(n.print(" "+$("login needed to serve your sessions — back to menu")),!1)),h=async()=>!!t.agents.length||(n.print("\n "+$("No coding agent is ready on this computer")),n.print(" thinkpool connects an agent already installed on this machine. It does not"),n.print(" include one. Install and configure at least one of:"),n.print(`\n ${w("Claude Code")} command: claude`),n.print(` ${w("Codex")} command: codex`),n.print(` ${w("Hermes")} command: hermes, then set up its thinkpool profile here`),n.print("\n "+y("BYOK does not replace the agent. It only gives an installed agent")),n.print(" credentials for a model provider."),n.print("\n Install one, then reopen this launcher."),!1),f=async()=>{const r=t.provider+(t.providerModel?`, model ${t.providerModel}`:"");n.print("\n "+g("Provider settings supply model credentials. Claude Code, Codex, or Hermes must still be installed locally."));const l=await p("\n provider",[{label:"Anthropic (default)",hint:"regular Claude login"},{label:"Paste a key, pick a model",hint:"auto-detects the provider · OpenRouter = any model"},{label:"Custom endpoint",hint:"enter a base url + token by hand"},{label:"← Back",hint:`current: ${r}`}],4);if(3===l)return;if(0===l)return await e.setProvider({kind:"anthropic"}),c(),void n.print("\n "+b("✓ back on regular Claude."));if(1===l){const t=(await n.ask(`\n Paste your API key ${g("(blank to cancel)")} ${w("▸")} `)).trim();if(!t)return void n.print(" "+$("cancelled — provider unchanged"));const r=o(t);if(!r.compatible)return void n.print("\n "+$(s(r.name)));const l=a[r.id];n.print(`\n ${b("✓ detected "+l.name)} ${g("— fetching models…")}`);const d=await i({modelsUrl:l.models,key:t,auth:l.auth});let u;if(0===d.length)u=(await n.ask(` Couldn't list models. Model id ${g("(blank = endpoint default)")} ${w("▸")} `)).trim()||void 0;else if(d.length<=40){const e=await p("\n model",d.map(e=>({label:e})),1);u=d[e]}else for(n.print(` ${g(d.length+" models available, e.g. "+d.slice(0,3).join(", ")+"…")}`);;){const e=(await n.ask(` Type a model id or part of it ${g("(blank to cancel)")} ${w("▸")} `)).trim();if(!e)return void n.print(" "+$("cancelled — provider unchanged"));const t=d.filter(n=>n.toLowerCase().includes(e.toLowerCase()));if(0!==t.length){if(1===t.length){u=t[0];break}if(t.length<=40){const e=await p("\n pick",t.map(e=>({label:e})),1);u=t[e];break}n.print(` ${$(t.length+" matches — narrow it down")}`)}else n.print(" "+$("no match — try again"))}return await e.setProvider({kind:"custom",base:l.base,token:t,model:u}),c(),void n.print(`\n ${b("✓ provider set.")}\n ${l.name}\n model: ${u||"(endpoint default)"}`)}const d=(await n.ask(`\n Base url ${g("(blank to cancel · SDK appends /v1/messages)")} ${w("▸")} `)).trim();if(!d)return void n.print(" "+$("cancelled — provider unchanged"));const u=(await n.ask(` API token ${g("(blank to cancel)")} ${w("▸")} `)).trim();if(!u)return void n.print(" "+$("cancelled — provider unchanged"));const m=(await n.ask(` Model ${g("(blank = endpoint default · e.g. glm-4.6)")} ${w("▸")} `)).trim();await e.setProvider({kind:"custom",base:d,token:u,model:m||void 0}),c(),n.print(`\n ${b("✓ provider set to custom.")}\n base url: ${t.provider}\n model: ${t.providerModel||"(endpoint default)"}`)},v=async()=>{for(;;){const r=[{key:"provider",label:"Provider",hint:`current: ${t.provider}`},{key:"account",label:"Account",hint:t.reconnectRequired?"reconnect required":t.loggedIn?`linked: ${t.email||"yes"}`:"not linked"},{key:"awake",label:"Keep computer awake",hint:(t.keepAwake?"ON":"off")+" · the screen can still dim, lock, and turn off"}];t.hermesInstalled&&r.push({key:"hermes",label:t.hermesReady?"Hermes profile":"Set up Hermes",hint:t.hermesReady?"isolated profile ready":"set up isolated profile + delegation guard"}),r.push({key:"back",label:"Back to main menu",hint:""});const o=r[await p("\n change",r,r.length)];if("back"===o.key)return;if("provider"===o.key)await f();else{if("account"===o.key)return await e.login(),void c();if("awake"===o.key)if(t.keepAwake){if(!1===await e.setKeepAwake({enabled:!1}))continue;t={...t,keepAwake:!1},c(),n.print("\n "+b("✓ keep-awake is off. The computer may sleep normally."))}else if(n.print("\n "+$("Important: keep-awake changes this computer’s power behavior")),n.print(" While the bridge runs, thinkpool will prevent the computer itself from"),n.print(" automatically sleeping. This can use substantially more battery and may"),n.print(" also block suspend requests on some Linux systems."),n.print("\n "+b("It does NOT keep the screen on. Display dimming, screen locking, and")),n.print(" display sleep continue to work normally. Closing a laptop lid may still"),n.print(" sleep it, depending on the operating system and power settings."),await d("\n Enable keep-awake while the thinkpool bridge runs?",!1)){if(!1===await e.setKeepAwake({enabled:!0}))continue;t={...t,keepAwake:!0},c(),n.print("\n "+b("✓ keep-awake is on. Your screen is still free to dim and turn off."))}else n.print("\n "+$("unchanged: keep-awake remains off."));else if("hermes"===o.key){const n=await p("\n Hermes profile",[{label:"Clone active profile",hint:"copies provider/config explicitly; fresh thinkpool session history"},{label:"Create clean profile",hint:"no copied credentials or bundled skills; configure provider afterward"},{label:"Back",hint:""}],3);2!==n&&(await e.setupHermes({mode:0===n?"clone":"clean"}),c())}}}};for(;;){u(),n.print(" "+y("What do you want to do?")+"\n");const r=t.accountSvc?["win32"===t.platform?{key:"restart",label:"Update startup entry",hint:"installs the latest version; relaunch the bridge window to apply"}:{key:"restart",label:"Restart & update bridge",hint:"install the latest published version; sessions resume"},{key:"uninstall",label:"Remove background service",hint:"stop serving your sessions on this device"}]:[{key:"serve",label:"Serve all my sessions",hint:"runs here, Ctrl-C stops it"},{key:"service",label:"Always-on background service",hint:"recommended — survives reboot, restarts on crash"}];r.push({key:"settings",label:"Settings",hint:`provider · account · keep-awake ${t.keepAwake?"ON":"off"}${t.hermesInstalled?" · Hermes profile":""}`}),r.push({key:"quit",label:"Quit",hint:""});const o=r[await p("choose",r)];if("quit"===o.key)return;if("serve"===o.key)await h()&&await m()&&await e.serveAccountForeground();else if("service"===o.key){if(await h()&&await m()){if(!0===await e.installService({room:null})&&(!e.relaunchLauncher||await e.relaunchLauncher()))return;c()}}else if("restart"===o.key){if(!0===await e.restartUpdateService({room:null})&&(!e.relaunchLauncher||await e.relaunchLauncher()))return;c()}else"uninstall"===o.key?(await e.uninstallService({room:null}),c()):"settings"===o.key&&await v();await n.ask("\n "+g("press Enter to return to the menu…"))}}
@@ -0,0 +1 @@
1
+ const e=/(?:TOKEN|SECRET|PASSWORD|PRIVATE_KEY|API_KEY|ACCESS_KEY|CREDENTIAL|AUTHORIZATION)/i;export const OPENCODE_SUPPORTED_SLICE_TYPES=Object.freeze(["scaffold","feature","fix"]);export const opencodeChildEnv=(o={})=>Object.fromEntries(Object.entries(o).filter(([o])=>!e.test(o)));export function opencodeRoleAdmission({flowRole:e=null,sliceType:o=null}={}){return e?Object.freeze({ok:!1,code:"flow_roles_unsupported"}):"review"===o||"plan"===o?Object.freeze({ok:!1,code:"structural_role_unsupported"}):o&&!OPENCODE_SUPPORTED_SLICE_TYPES.includes(o)?Object.freeze({ok:!1,code:"slice_type_unsupported"}):Object.freeze({ok:!0,role:o||"ordinary"})}export function opencodePermissionOutcome(e,o=[]){if("allow"!==e)return{outcome:"cancelled"};const t=o.find(e=>"allow_once"===e?.kind&&"allow_once"===e?.optionId);return t?{outcome:"selected",optionId:t.optionId}:{outcome:"cancelled"}}
@@ -0,0 +1 @@
1
+ import{execFileSync as e}from"node:child_process";const n=e=>String(e||"").replace(/[\r\n]+/g," ").trim();export function probeOpenCodeRuntime({command:o="opencode",execFile:a=e,env:r=process.env}={}){try{const e=a(o,["--version"],{encoding:"utf8",env:r,timeout:1e4,stdio:["ignore","pipe","pipe"]}),i=n(e).match(/\b(\d+\.\d+\.\d+(?:[-+][\w.-]+)?)\b/)?.[1]||null;return i?{available:!0,version:i,command:o,package:"opencode-ai",acpProtocol:1}:{available:!1,version:null,reason:"OpenCode did not report an exact semantic version"}}catch(e){return{available:!1,version:null,command:o,package:"opencode-ai",reason:n(e?.stderr||e?.message||e)||"opencode is not installed"}}}
@@ -0,0 +1 @@
1
+ import e from"node:path";import o from"node:fs";import{randomUUID as n}from"node:crypto";import{createAcpRuntimeAdapter as t,startAcpAdapterClient as s}from"./acp-runtime-adapter.mjs";import{AcpEventMapper as r}from"./acp-event-mapper.mjs";import{opencodeChildEnv as i,opencodePermissionOutcome as a,opencodeRoleAdmission as l}from"./opencode-policy.mjs";import{probeOpenCodeRuntime as c}from"./opencode-probe.mjs";import{createCompatibilityProfile as p,projectCompatibilityProfile as d}from"./runtime-compatibility-profile.mjs";export const OPENCODE_COMMAND="opencode";export const OPENCODE_ACP_PROTOCOL_VERSION=1;const m=t({runtime:"opencode",command:"opencode",capabilities:{streaming:!0,permission_request:!0,cancellation:!0,resume:!0,new_session:!0,model_catalog:!1,mode_catalog:!1,images:!0}}),u=n=>{const t=e.extname(n).toLowerCase();return{type:"image",mimeType:".png"===t?"image/png":".webp"===t?"image/webp":".gif"===t?"image/gif":"image/jpeg",data:o.readFileSync(n).toString("base64")}};export function startOpenCodeSession({cwd:o,model:f,resume:g,env:w=process.env,onEvent:C,requestPermission:h,command:y="opencode",args:v=["acp"],clientFactory:b=null,flowRole:O=null,sliceType:I=null,lazy:E=!1,platform:S=process.platform}={}){const k=l({flowRole:O,sliceType:I});if(!k.ok)throw new Error(`OpenCode runtime selection rejected: ${k.code}`);let A=g||null,q=null,P=null,$=!1,_=!1,x=!1,R=!1,T=f||null,j="",N=null,V=null;const M=e=>{try{C?.(e)}catch{}},D=async()=>{if(_)throw new Error("OpenCode session is closed");if(x)throw new Error("OpenCode ACP process crashed; retry starts a fresh process");if(!q?.alive||!P)return N||(N=(async()=>{if("opencode"===y&&!b){const e=c({command:y,env:i(w)});if(!e.available)throw new Error(`OpenCode runtime unavailable: ${e.reason}`)}const n="opencode"===y?m:t({...m,runtime:"opencode",command:y,args:v});q=b?b({command:y,args:v,cwd:o,env:i(w),onNotification:z,onRequest:F,onStderr:L,onClose:U}):s(n,{cwd:o,env:i(w),onNotification:z,onRequest:F,onStderr:L,onClose:U}),q.start();const a=await q.request("initialize",{protocolVersion:1,clientCapabilities:{fs:{readTextFile:!1,writeTextFile:!1},terminal:!1},clientInfo:{name:"thinkpool-pair",title:"thinkpool Code",version:"1"}},15e3);if(1!==a?.protocolVersion)throw new Error(`Unsupported OpenCode ACP protocol ${a?.protocolVersion??"unknown"}`);const l={cwd:e.resolve(o||process.cwd()),mcpServers:[]},u=A?await q.request("session/resume",{...l,sessionId:A},3e4):await q.request("session/new",l,3e4);if(A||=u?.sessionId||null,!A)throw new Error("OpenCode ACP did not return a session id");T||=u?.models?.currentModelId||null,P=new r({onEvent:M,sessionId:A,model:T,runtime:"opencode"}),P.startSession({sessionId:A,models:u?.models,modes:u?.modes,commands:[]}),V=p({runtime:"opencode",runtimeVersion:a?.agentInfo?.version||null,modelId:T,role:k.role,platform:S,observedAt:(new Date).toISOString().slice(0,10),checks:["acp_initialize","session_lifecycle"],capabilities:{streaming:!0,cancellation:!0,resume:null!=a?.agentCapabilities?.sessionCapabilities?.resume,images:!0===a?.agentCapabilities?.promptCapabilities?.image},available:!0}),M({kind:"capabilities",runtime:"opencode",protocol:"acp",protocolVersion:a.protocolVersion,capabilities:a.agentCapabilities||{},models:[],provider:"OpenCode local configuration (unverified)",profile:d(V),flow:!1}),$=!0})().catch(e=>{throw x=!0,q?.end(),M({kind:"error",message:`OpenCode ACP startup failed: ${e?.message||e}${j?`: ${j.slice(-240)}`:""}`,recoverable:!0}),e}).finally(()=>{N=null}),N)};async function F(e,o,n){if("session/request_permission"!==e)throw Object.assign(new Error(`Unsupported ACP client method: ${e}`),{code:-32601});let t="deny";try{t=await(h?.({id:`opencode-perm:${n}`,toolName:String(o?.toolCall?.title||"OpenCode tool"),input:o?.toolCall?.rawInput||{},risk:"high"}))}catch{}return{outcome:a(t,o?.options||[])}}function z(e,o){"session/update"===e&&P?.push(o)}function L(e){j=(j+String(e)).slice(-2e3)}function U(e){_||x||(x=!0,R=!1,M({kind:"error",message:`OpenCode ACP closed unexpectedly: ${e?.message||e}`,recoverable:!0}))}return E||queueMicrotask(()=>{D().catch(()=>{})}),{get sessionId(){return A},get turnActive(){return R},get started(){return $},get canSteer(){return!1},get profile(){return V},sendTurn(e,o={}){if(_||R)return!1;R=!0;const t=[{type:"text",text:String(e)}];for(const e of Array.isArray(o.images)?o.images:[])try{t.push(u(e))}catch{}return D().then(()=>q.request("session/prompt",{sessionId:A,prompt:t,messageId:n()},0)).then(e=>P.finishTurn({stopReason:e?.stopReason,usage:e?.usage})).catch(e=>M({kind:"error",message:`OpenCode turn failed: ${e?.message||e}`,recoverable:!0})).finally(()=>{R=!1}),!0},async abort(){R&&q?.alive&&A&&(R=!1,await q.notify("session/cancel",{sessionId:A}).catch(e=>{x=!0,q?.end(),M({kind:"error",message:`OpenCode cancellation delivery failed: ${e?.message||e}`,recoverable:!0})}),P?.finishTurn({stopReason:"cancelled"}))},setModel:()=>!1,setMode:()=>!1,clearContext:()=>!1,warm(){D().catch(()=>{})},end(){_=!0,R=!1,A&&q?.alive?q.request("session/close",{sessionId:A},1500).catch(()=>{}).finally(()=>q?.end()):q?.end()}}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thinkpool-pair",
3
- "version": "0.7.398",
3
+ "version": "0.7.399",
4
4
  "description": "Connect Claude Code, Codex, or Hermes on your computer to a thinkpool Code room.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",
@@ -37,12 +37,22 @@
37
37
  "codex-mcp-http.mjs",
38
38
  "lane-worktree.mjs",
39
39
  "lane-work-snapshot.mjs",
40
+ "branch-checkpoint.mjs",
41
+ "permission-rules.mjs",
42
+ "public-proof.mjs",
40
43
  "codex-event-mapper.mjs",
41
44
  "edit-diff.mjs",
42
45
  "cumulative-event-relay.mjs",
43
46
  "codex-commands.mjs",
44
47
  "acp-client.mjs",
48
+ "acp-event-mapper.mjs",
49
+ "acp-runtime-adapter.mjs",
45
50
  "hermes-session.mjs",
51
+ "opencode-session.mjs",
52
+ "opencode-policy.mjs",
53
+ "opencode-probe.mjs",
54
+ "runtime-adapter.mjs",
55
+ "runtime-compatibility-profile.mjs",
46
56
  "hermes-model-cache.mjs",
47
57
  "hermes-policy.mjs",
48
58
  "hermes-acp-bootstrap.py",
@@ -0,0 +1 @@
1
+ const e=/^(?!.*\.\.)[A-Za-z0-9][A-Za-z0-9_.:/-]{0,119}$/,r=/^[A-Z0-9-]{3,12}$/,o=new Set(["medium","network"]);export function codePermissionRuleSignature(r,t){const s="string"==typeof r?r.trim():"";return e.test(s)&&o.has(t)?`${s}:${t}`:null}export function activePermissionRuleAllows(e,{toolName:r,risk:o}={}){const t=codePermissionRuleSignature(r,o);return!(!t||!Array.isArray(e))&&e.some(e=>!e?.revoked_at&&codePermissionRuleSignature(e?.tool_name,e?.risk)===t)}export async function fetchCodePermissionRules({supabaseUrl:e,anonKey:o,token:t,roomCode:s,fetcher:i=globalThis.fetch,timeoutMs:n=1200}={}){const a="string"==typeof s?s.toUpperCase().trim():"";if(!("function"==typeof i&&"string"==typeof e&&e&&"string"==typeof o&&o&&"string"==typeof t&&t&&r.test(a)))return Object.freeze({ok:!1,code:"permission_rules_unavailable",rules:Object.freeze([])});const l=new AbortController,u=setTimeout(()=>l.abort(),n);u.unref?.();try{const r=await i(`${e.replace(/\/$/,"")}/rest/v1/rpc/list_code_permission_rules`,{method:"POST",headers:{apikey:o,Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify({p_session_code:a,p_include_revoked:!1}),signal:l.signal});if(!r?.ok)return Object.freeze({ok:!1,code:"permission_rules_unavailable",rules:Object.freeze([])});const s=await r.json();if(!Array.isArray(s))return Object.freeze({ok:!1,code:"permission_rules_invalid",rules:Object.freeze([])});const n=s.filter(e=>!e?.revoked_at&&codePermissionRuleSignature(e?.tool_name,e?.risk));return Object.freeze({ok:!0,code:"permission_rules_loaded",rules:Object.freeze(n)})}catch{return Object.freeze({ok:!1,code:"permission_rules_unavailable",rules:Object.freeze([])})}finally{clearTimeout(u)}}export async function allowsCodePermissionRule(e={}){if(!codePermissionRuleSignature(e.toolName,e.risk))return!1;const r=await fetchCodePermissionRules(e);return r.ok&&activePermissionRuleAllows(r.rules,e)}
@@ -0,0 +1 @@
1
+ import{createFlowReviewReceipt as e}from"./flow-receipt.mjs";const r=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;export async function registerPublicProof({webBase:t,token:o,room:i,sourceCid:a,sourceTerminalId:n,receipt:s,fetcher:c=fetch,timeoutMs:l=1800}={}){if(!(t&&o&&i&&r.test(a||"")&&r.test(n||"")))return{ok:!1,reason:"unavailable"};let u;try{u=e(s)}catch{return{ok:!1,reason:"invalid-receipt"}}if("pass"!==u.outcome||!u.verified||!u.scope?.held)return{ok:!1,reason:"ineligible"};const f=new AbortController,p=setTimeout(()=>f.abort(),l);try{const e=await c(`${t.replace(/\/$/,"")}/api/proof-receipt`,{method:"POST",headers:{Authorization:`Bearer ${o}`,"Content-Type":"application/json"},body:JSON.stringify({action:"register",code:i,sourceCid:a,sourceTerminalId:n,receipt:u}),signal:f.signal});return e.ok?{ok:!0}:{ok:!1,reason:`http-${e.status}`}}catch(e){return{ok:!1,reason:"AbortError"===e?.name?"timeout":"network"}}finally{clearTimeout(p)}}
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "format": 1,
3
3
  "package": "thinkpool-pair",
4
- "version": "0.7.398",
4
+ "version": "0.7.399",
5
5
  "kind": "minified",
6
- "minifiedModules": 123,
7
- "sourceModuleBytes": 1774795,
8
- "artifactModuleBytes": 803839,
6
+ "minifiedModules": 133,
7
+ "sourceModuleBytes": 1810866,
8
+ "artifactModuleBytes": 827302,
9
9
  "files": {
10
- "package.json": "d1fe9fa766e292f3e4b8f621c79fcdd0934a4c2e9fa7cc2bb5308119f510694a",
10
+ "package.json": "12f7d087ed6cfda10490a8af4badae6e7f213cca825ee9af330a19bfa595ad58",
11
11
  "LICENSE": "8a030197ca1cad9669909ca14c9ad15cf48d9fe551da526ccaf1fca993eddb23",
12
- "bridge.mjs": "c1fa4233f324b712da9abc81a5a2d14061b45da2a996769b2c6c7378566b0a85",
12
+ "bridge.mjs": "daa93eee4ee30bea185e6045da6232f8bed9bfab1402ffbbf134a6c631727b5a",
13
13
  "bridge-service.sh": "b64f27c473ca8f3a49190fd08c23947ab14ca9958d70b6fa53c7bddc2be91403",
14
14
  "command-guidance.mjs": "b9b967b59ff4e77c9613abb0f28858bf3ac5b106a509e471039777b53bec3e29",
15
15
  "abort-turn-barrier.mjs": "3734a5b7e2e940ec6d7fa8b5b04935e1429a23d1bd9e92b2ac2a2ecd9f77c75e",
@@ -18,9 +18,9 @@
18
18
  "keep-awake.mjs": "6c0a51409321f2564082b414b00696d22a740ca98180b1f628828c5fe19995c7",
19
19
  "sdk-smoke.mjs": "dfe509863ede8a12780914939740f7f9fee36d3980f8fcb57803a33593ac4056",
20
20
  "sdk-admission.mjs": "eb33725cc33347b900c75289eae7917f6ce3526203711515aecd48d43b3c895d",
21
- "launcher.mjs": "d10ea30ec940094b8ae7881c296d18f348f16d013a89c1ea725cacc273e2d376",
21
+ "launcher.mjs": "a63c63492be0e97b41aae9c0ae24045903207a768c2cb86f8d7a9297d2741f1b",
22
22
  "privacy-report.mjs": "b444610be6de8b3bcf0086d585594286ef000dad1e075df87013003a315bf211",
23
- "agent-visibility.mjs": "624448728a596fea3a2f01fc686db78716cff20429b8ddbfaa4fb7eb05027870",
23
+ "agent-visibility.mjs": "6afed5ce9120c4aaa7582d3cfb30c0658186a936ad1f87b1b01dfd20e988f839",
24
24
  "byok-detect.mjs": "f31f2ca426737581a97c391b3cecfc75f0207cfa31f51c6bf4a9148309c9625d",
25
25
  "context-contract.mjs": "ffebb435dc5d75c289329bf16ab909df9d634a2b508154c250c6b25906a02a91",
26
26
  "context-windows.mjs": "80af664f84d7e95ef2b0a2a3131090ac4ccd522709448ac9a0d96c378bbec0f7",
@@ -35,14 +35,24 @@
35
35
  "codex-app-server.mjs": "d50e30ba6cb2a383c90d89186bc7a13f4caf900c977dd501572468986009470e",
36
36
  "codex-images.mjs": "31605d6d8b3dd6b73395da63d1b0c513445c95ffa2f4306ee466f201d633ffc0",
37
37
  "codex-mcp-http.mjs": "7472543648a9bb575ce20dc3e3270c2da84174c6ea6e9faf87dfaafb95b6212a",
38
- "lane-worktree.mjs": "37583757ab82843412ba565dfba3d7cab517e94782eb33115decd5438d092d8f",
38
+ "lane-worktree.mjs": "20a4327b501d3771c8e41e0908926d50c477db9d76c41d5243204d72d20417e8",
39
39
  "lane-work-snapshot.mjs": "ba40233059ea86ba2e08d0b61763427baa9602eb6edf6c445a6b22fd15af212c",
40
+ "branch-checkpoint.mjs": "6301c39df24b0343aacb05c13aad4a37dcce1c1acee3ffdf7465fc51db6acaa2",
41
+ "permission-rules.mjs": "552a9e33dc85ea2dbbe168d6335fcee4f11ef7c0a5b47fd8d9c5b74d24c149ef",
42
+ "public-proof.mjs": "00e010d629e0bb2ab859167037e65b6c90986a23cb7df0fb5f2c898972c34581",
40
43
  "codex-event-mapper.mjs": "a7c423806b5e80957733c21d756078740773ae7230305ed00dba72cecb3a558a",
41
44
  "edit-diff.mjs": "258c64416b4e60b1f8243546f1cc25e1b27457f0edeaa0e6c837a3e888f49ba2",
42
45
  "cumulative-event-relay.mjs": "cf6e6533e33b3c5bb0b462d15ccc86106f2b56f8b1e66fc1f4867dd8f44d7ae6",
43
46
  "codex-commands.mjs": "cae3f617ac42e1316d8980ef97e4255227fe5df5e8e9b556630a3bfb83bb7c2b",
44
47
  "acp-client.mjs": "9e7919ff79825883820019ff7a0ca578f120853ed61c7caab21a8ffc3a67ffc9",
48
+ "acp-event-mapper.mjs": "bcef2d7b5b940a4ee1dc5053e2283ac962dd0567c7fd87f8fb6e16b083be5847",
49
+ "acp-runtime-adapter.mjs": "b0e65df88a2e5f64ad3bcb123843daca5ae30e32ac33aceee31ca4f4c167f38b",
45
50
  "hermes-session.mjs": "b3d521ea59297edb58ecfcc0daad3c0df88d96131cadc455fa36fc1cca954210",
51
+ "opencode-session.mjs": "0828568fe8ad2110fb75363b501b69730627889aa8191fc460513f80c72ba337",
52
+ "opencode-policy.mjs": "3c76d26162a26a6ea15d4f123155be5ca0ee10efe2cc1bc74659750ccc62d277",
53
+ "opencode-probe.mjs": "08aa692d27873ece9aec2907641ae8e6d0f776f6f0e9e0dafb865fd890ce3bfd",
54
+ "runtime-adapter.mjs": "0500660893b12b202848b1a0da9b00ab86f6be425aa4820eb680d10537a95cba",
55
+ "runtime-compatibility-profile.mjs": "137730baf95d315723872e8df80e66305bccb909e3c6cb81ae753ea9adadac84",
46
56
  "hermes-model-cache.mjs": "aee23efdebe1aa5e10053f291a9153981fe9b45065c293c9519ca73477251e72",
47
57
  "hermes-policy.mjs": "df6dd384ab130b3626045816b6ac4c1d2aecde37fb7b7a4be0c1bffc375fd8ff",
48
58
  "hermes-acp-bootstrap.py": "9453b48d1ec0057a1d1754fc828acb949ad3f69c687fd055dc3856823d26c19b",
@@ -53,15 +63,15 @@
53
63
  "hermes-delegation-guard.mjs": "f737d05fb93591848fa3839fd5df2c019779bda828d42ab785cd57213665f922",
54
64
  "catastrophic-command-guard.mjs": "65158e59266e4be1e2a72479fb9b2c7e7a4ec7902a8b764d3b26017cd0cdbfd5",
55
65
  "codex-catastrophic-command-hook.mjs": "5bf1eb5dd837b77044846af0cb8936a81edbc435e454217ddb15981f3626f7dc",
56
- "runtime-registry.mjs": "d0a3d93edb60443df56273025ed3f10ed4b1d06a16b84759267782691cacdda8",
66
+ "runtime-registry.mjs": "278ff20fe803dba5990f275ef4f2f26730a2e17d0886700d76cb5b37c6e3163e",
57
67
  "runtime-skill-parity.mjs": "933535bc7b70d7843cf7bf8eb83f306693045ccf7154ad781b6d42be75442f1c",
58
68
  "reasoning-effort.mjs": "3a514997656bbcd41ff1aefe9d5e59c5920a90e6bfcc928016d95987db2ceaa3",
59
- "runtime-contract.mjs": "eb24b177002ba33353ec0335f4f830fb57fe313552b1a8d7aef8163cc743f6c1",
60
- "command-catalog.mjs": "ecad63189f8803eba99e1b797afa57b355ca1b55d09e1cf212cc74dd952baa65",
69
+ "runtime-contract.mjs": "410e55770d4b1ee72af5adc5c7706fb021c28126f728f270a1aad711d4ad3460",
70
+ "command-catalog.mjs": "42a61109ce791bcdb4ca793ad343402fe3c7bbad44cbe8f1f135bc67207aa00e",
61
71
  "repo-search.mjs": "10cbce1d86655a7add0d7350ea8862a57165ccb02c2afa406348f4669050c304",
62
72
  "project-intelligence.mjs": "b16108075648b331c84976cb63e267cf5835da7776ec7456b7642721225610a6",
63
73
  "git-diff-report.mjs": "a428b3129c90e207a125a86c4485ec16c8ee7e81d432060a070e37172d85ce7a",
64
- "runtime-session.mjs": "1a149012375047f0c031e210cba973e64ce2e6de427a951dfc937fa7c3c402ee",
74
+ "runtime-session.mjs": "ff97a7a65aba31d176d1afc8d0dc9d11a217415c8b0b7660a5b33c17756576c4",
65
75
  "turn-stall.mjs": "88c712d45974e492bfcfdbd93baa371bb8be1ddb754dacb18fae20da4dd672db",
66
76
  "update-gate.mjs": "4627870d1edae64cd4c569277dff702e4be7dd691a0a29bca6d2449d30e64d4b",
67
77
  "agent-notify.mjs": "5950ba8928edb6e8d6091a0fdc8fb62cb21fcb79d864504e3b56e012a6f8339a",
@@ -0,0 +1 @@
1
+ export const RUNTIME_ADAPTER_VERSION=1;const e=new Set(["start","new_session","resume","prompt","cancel","close","crash"]),r=new Set(["streaming","permission_request","cancellation","resume","new_session","model_catalog","mode_catalog","images"]),t=e=>e&&"object"==typeof e&&!Array.isArray(e);export function adapterFailureReceipt({runtime:e,check:r,code:t,detail:i=""}={}){return Object.freeze({version:1,runtime:String(e||""),check:String(r||""),ok:!1,code:String(t||"failed"),detail:String(i||"").slice(0,500)})}export function validateRuntimeAdapter(i){return t(i)&&1===i.version?/^[a-z][a-z0-9-]{1,63}$/.test(String(i.runtime||""))?t(i.subprocess)&&"string"==typeof i.subprocess.command&&Array.isArray(i.subprocess.args)?!Array.isArray(i.lifecycle)||i.lifecycle.some(r=>!e.has(r))?adapterFailureReceipt({runtime:i.runtime,check:"lifecycle",code:"invalid_lifecycle"}):!t(i.capabilities)||Object.entries(i.capabilities).some(([e,t])=>!r.has(e)||"boolean"!=typeof t)?adapterFailureReceipt({runtime:i.runtime,check:"capabilities",code:"invalid_capability_schema"}):Object.freeze({version:1,runtime:i.runtime,ok:!0,checks:["adapter_schema","subprocess_boundary","lifecycle","capabilities"]}):adapterFailureReceipt({runtime:i.runtime,check:"subprocess_boundary",code:"invalid_subprocess_boundary"}):adapterFailureReceipt({runtime:i?.runtime,check:"adapter_schema",code:"invalid_runtime_id"}):adapterFailureReceipt({runtime:i?.runtime,check:"adapter_schema",code:"unsupported_adapter_version"})}export function runRuntimeAdapterConformance(e,r={}){const t=validateRuntimeAdapter(e);if(!t.ok)return t;const i=Array.isArray(r.checks)?r.checks.filter(e=>/^[a-z][a-z0-9_-]{1,80}$/.test(e)):[],a=Array.isArray(r.failures)?r.failures.filter(Boolean).map(String).slice(0,16):[];return i.length?a.length?adapterFailureReceipt({runtime:e.runtime,check:"conformance",code:"observed_check_failed",detail:a.join("; ")}):Object.freeze({version:1,runtime:e.runtime,ok:!0,checks:[...new Set([...t.checks,...i])],observedAt:"string"==typeof r.observedAt?r.observedAt:null}):adapterFailureReceipt({runtime:e.runtime,check:"conformance",code:"no_observed_checks"})}
@@ -0,0 +1 @@
1
+ const e=(e,i=160)=>"string"==typeof e&&e.length>0&&e.length<=i;export function createCompatibilityProfile({runtime:i,runtimeVersion:l,modelId:t=null,role:r,platform:n,observedAt:o,checks:a=[],capabilities:c={},available:s=!0}={}){const u=(b=a,Array.isArray(b)?[...new Set(b.filter(e=>/^[a-z][a-z0-9_-]{1,80}$/.test(e)))]:[]);var b;const d=e(i)&&e(l)&&e(r)&&e(n)&&e(o,32),f=!0===s&&d&&u.includes("acp_initialize")&&u.includes("session_lifecycle");return Object.freeze({version:1,runtime:i||null,runtimeVersion:l||null,modelId:t||null,role:r||null,platform:n||null,observedAt:o||null,checks:Object.freeze(u),capabilities:Object.freeze({...c}),available:!0===s,verified:f})}export function projectCompatibilityProfile(e){const i=e&&"object"==typeof e&&1===e.version;return Object.freeze({runtime:i?e.runtime:null,modelId:i?e.modelId:null,verified:i&&!0===e.verified,available:i&&!0===e.available,capabilities:i?e.capabilities:{},observedAt:i?e.observedAt:null})}
@@ -1 +1 @@
1
- const e=Object.freeze(["claude","codex","hermes"]),t=Object.freeze({claude:"native",codex:"native",hermes:"native"}),r=/(?:\/home\/|\/users\/|\/private\/|\/tmp\/|[a-z]:\\|\\\\|(?:^|[\\/])\.\.(?:[\\/]|$))/i,i=/(secret|token|password|authorization|api.?key|private.?key)/i,a=/(?:sk-[a-z0-9_-]{8,}|gsk_[a-z0-9_-]{8,}|AIza[a-z0-9_-]{8,}|gh[pousr]_[a-z0-9]{20,}|github_pat_[a-z0-9_]{20,}|xox[baprs]-[a-z0-9-]{10,}|AKIA[0-9A-Z]{16}|sbp_[a-z0-9]{20,}|eyJ[a-z0-9_-]{16,}\.[a-z0-9_-]{16,}\.[a-z0-9_-]{8,}|bearer\s+[a-z0-9._-]{8,})/i,n=/(?:raw transcript|tool args?|chain[ -]of[ -]thought|hidden reasoning|system prompt|environment dump|provider key|BEGIN (?:RSA |OPENSSH )?PRIVATE KEY)/i,o=(e=[],t={})=>Object.freeze({type:"object",additionalProperties:!1,required:Object.freeze(e),properties:Object.freeze(t)}),c=(e=500)=>Object.freeze({type:"string",minLength:1,maxLength:e}),p=(e=500)=>Object.freeze({type:"string",maxLength:e}),s=Object.freeze({type:"boolean"}),u=Object.freeze({type:"string",minLength:1,maxLength:160,pattern:"^[A-Za-z0-9][A-Za-z0-9._:@-]*$"}),m=o(["label","description"],{label:c(80),description:c(240)}),d=o(["id","header","question","options"],{id:Object.freeze({type:"string",minLength:1,maxLength:80,pattern:"^[A-Za-z0-9][A-Za-z0-9_-]*$"}),header:c(12),question:c(500),options:Object.freeze({type:"array",minItems:2,maxItems:3,items:m}),multiSelect:s}),l=o(["type","id"],{type:u,id:u});export const RUNTIME_CAPABILITY_VERSION=1;export const RUNTIME_CAPABILITIES=Object.freeze([Object.freeze({id:"request_user_input",version:1,runtimeSupport:t,inputSchema:o(["questions"],{questions:Object.freeze({type:"array",minItems:1,maxItems:3,items:d}),autoResolutionMs:Object.freeze({type:"integer",minimum:6e4,maximum:24e4})}),output:"accepted | deferred | rejected | failed",authority:"pair-control",persistence:"durable-safe-ref",continuation:"resumable",secretFreeRoomPayload:!0}),Object.freeze({id:"request_permission",version:1,runtimeSupport:t,inputSchema:o(["action"],{action:c(160),reason:p(280)}),output:"accepted | deferred | rejected | failed",authority:"pair-control",persistence:"durable-safe-ref",continuation:"resumable",secretFreeRoomPayload:!0}),Object.freeze({id:"submit_flow_plan",version:1,runtimeSupport:t,inputSchema:o(["plan"],{plan:c(32768)}),output:"accepted | rejected | failed",authority:"pair-control",persistence:"durable-safe-ref",continuation:"resumable",secretFreeRoomPayload:!0}),Object.freeze({id:"mark_flow_done",version:1,runtimeSupport:t,inputSchema:o([],{evidenceRef:l}),output:"accepted | rejected | failed",authority:"bridge",persistence:"durable-safe-ref",continuation:"none",secretFreeRoomPayload:!0}),Object.freeze({id:"submit_flow_review",version:1,runtimeSupport:t,inputSchema:o(["verdict"],{verdict:c(16384)}),output:"accepted | rejected | failed",authority:"bridge",persistence:"durable-safe-ref",continuation:"none",secretFreeRoomPayload:!0}),Object.freeze({id:"terminal_interrupt",version:1,runtimeSupport:t,inputSchema:o([],{reason:p(280)}),output:"accepted | rejected | failed",authority:"bridge",persistence:"ephemeral",continuation:"none",secretFreeRoomPayload:!0}),Object.freeze({id:"lane_continuation",version:1,runtimeSupport:t,inputSchema:o(["state"],{state:Object.freeze({type:"string",enum:Object.freeze(["waiting_for_human","resumable","canceled","terminal"])}),resumeKind:Object.freeze({type:"string",enum:Object.freeze(["human_response","approval","redispatch","reconnect"])})}),output:"accepted | deferred | rejected | failed",authority:"bridge",persistence:"durable-safe-ref",continuation:"resumable",secretFreeRoomPayload:!0})]);const b=new Map(RUNTIME_CAPABILITIES.map(e=>[e.id,e]));export const runtimeCapability=e=>b.get(e)||null;export const runtimeSupportsCapability=(t,r)=>e.includes(t)&&"native"===runtimeCapability(r)?.runtimeSupport?.[t];export function isSecretFreeRoomPayload(e,t=8192){if(null==e||(e=>{try{return(new TextEncoder).encode(JSON.stringify(e)).length}catch{return 1/0}})(e)>t)return!1;const o=e=>"string"==typeof e?e.length<=2048&&!r.test(e)&&!a.test(e)&&!n.test(e):null==e||"number"==typeof e||"boolean"==typeof e||(Array.isArray(e)?e.length<=64&&e.every(o):"object"==typeof e&&Object.entries(e).every(([e,t])=>!i.test(e)&&o(t)));return o(e)}function y(e,t){return!t||("object"===t.type?!(!e||"object"!=typeof e||Array.isArray(e))&&(!1!==t.additionalProperties||!Object.keys(e).some(e=>!Object.hasOwn(t.properties||{},e)))&&!(t.required||[]).some(t=>!Object.hasOwn(e,t))&&Object.entries(t.properties||{}).every(([t,r])=>!Object.hasOwn(e,t)||y(e[t],r)):"array"===t.type?Array.isArray(e)&&e.length>=(t.minItems||0)&&e.length<=(t.maxItems??1/0)&&(!t.items||e.every(e=>y(e,t.items))):"string"===t.type?"string"==typeof e&&e.length>=(t.minLength||0)&&e.length<=(t.maxLength??1/0)&&(!t.enum||t.enum.includes(e))&&(!t.pattern||new RegExp(t.pattern).test(e)):"integer"===t.type?Number.isSafeInteger(e)&&e>=(t.minimum??-1/0)&&e<=(t.maximum??1/0):"boolean"===t.type&&"boolean"==typeof e)}export function validateRuntimeCapabilityInput(e,t){const r=runtimeCapability(e);return!!r&&y(t,r.inputSchema)}export function admitRuntimeCapability({runtime:t,capabilityId:r,input:i={},roomPayload:a=null}={}){const n=runtimeCapability(r);return n?e.includes(t)&&"native"===n.runtimeSupport[t]?validateRuntimeCapabilityInput(r,i)?n.secretFreeRoomPayload&&null!=a&&!isSecretFreeRoomPayload(a)?Object.freeze({ok:!1,code:"unsafe_room_payload"}):Object.freeze({ok:!0,code:"admitted",capability:n}):Object.freeze({ok:!1,code:"invalid_capability_input"}):Object.freeze({ok:!1,code:"runtime_capability_mismatch"}):Object.freeze({ok:!1,code:"unregistered_capability"})}export function assertRuntimeCapability(e){const t=admitRuntimeCapability(e);if(!t.ok)throw new TypeError(`Runtime capability rejected: ${t.code}`);return t.capability}
1
+ const e=Object.freeze(["claude","codex","hermes","opencode"]),t=Object.freeze({claude:"native",codex:"native",hermes:"native"}),r=Object.freeze({...t,opencode:"native"}),i=Object.freeze({...t,opencode:"native"}),n=Object.freeze({claude:"native",codex:"native",hermes:"native"}),a=/(?:\/home\/|\/users\/|\/private\/|\/tmp\/|[a-z]:\\|\\\\|(?:^|[\\/])\.\.(?:[\\/]|$))/i,o=/(secret|token|password|authorization|api.?key|private.?key)/i,c=/(?:sk-[a-z0-9_-]{8,}|gsk_[a-z0-9_-]{8,}|AIza[a-z0-9_-]{8,}|gh[pousr]_[a-z0-9]{20,}|github_pat_[a-z0-9_]{20,}|xox[baprs]-[a-z0-9-]{10,}|AKIA[0-9A-Z]{16}|sbp_[a-z0-9]{20,}|eyJ[a-z0-9_-]{16,}\.[a-z0-9_-]{16,}\.[a-z0-9_-]{8,}|bearer\s+[a-z0-9._-]{8,})/i,p=/(?:raw transcript|tool args?|chain[ -]of[ -]thought|hidden reasoning|system prompt|environment dump|provider key|BEGIN (?:RSA |OPENSSH )?PRIVATE KEY)/i,s=(e=[],t={})=>Object.freeze({type:"object",additionalProperties:!1,required:Object.freeze(e),properties:Object.freeze(t)}),u=(e=500)=>Object.freeze({type:"string",minLength:1,maxLength:e}),m=(e=500)=>Object.freeze({type:"string",maxLength:e}),d=Object.freeze({type:"boolean"}),l=Object.freeze({type:"string",minLength:1,maxLength:160,pattern:"^[A-Za-z0-9][A-Za-z0-9._:@-]*$"}),b=s(["label","description"],{label:u(80),description:u(240)}),y=s(["id","header","question","options"],{id:Object.freeze({type:"string",minLength:1,maxLength:80,pattern:"^[A-Za-z0-9][A-Za-z0-9_-]*$"}),header:u(12),question:u(500),options:Object.freeze({type:"array",minItems:2,maxItems:3,items:b}),multiSelect:d}),f=s(["type","id"],{type:l,id:l});export const RUNTIME_CAPABILITY_VERSION=1;export const RUNTIME_CAPABILITIES=Object.freeze([Object.freeze({id:"request_user_input",version:1,runtimeSupport:t,inputSchema:s(["questions"],{questions:Object.freeze({type:"array",minItems:1,maxItems:3,items:y}),autoResolutionMs:Object.freeze({type:"integer",minimum:6e4,maximum:24e4})}),output:"accepted | deferred | rejected | failed",authority:"pair-control",persistence:"durable-safe-ref",continuation:"resumable",secretFreeRoomPayload:!0}),Object.freeze({id:"request_permission",version:1,runtimeSupport:r,inputSchema:s(["action"],{action:u(160),reason:m(280)}),output:"accepted | deferred | rejected | failed",authority:"pair-control",persistence:"durable-safe-ref",continuation:"resumable",secretFreeRoomPayload:!0}),Object.freeze({id:"submit_flow_plan",version:1,runtimeSupport:n,inputSchema:s(["plan"],{plan:u(32768)}),output:"accepted | rejected | failed",authority:"pair-control",persistence:"durable-safe-ref",continuation:"resumable",secretFreeRoomPayload:!0}),Object.freeze({id:"mark_flow_done",version:1,runtimeSupport:n,inputSchema:s([],{evidenceRef:f}),output:"accepted | rejected | failed",authority:"bridge",persistence:"durable-safe-ref",continuation:"none",secretFreeRoomPayload:!0}),Object.freeze({id:"submit_flow_review",version:1,runtimeSupport:n,inputSchema:s(["verdict"],{verdict:u(16384)}),output:"accepted | rejected | failed",authority:"bridge",persistence:"durable-safe-ref",continuation:"none",secretFreeRoomPayload:!0}),Object.freeze({id:"terminal_interrupt",version:1,runtimeSupport:r,inputSchema:s([],{reason:m(280)}),output:"accepted | rejected | failed",authority:"bridge",persistence:"ephemeral",continuation:"none",secretFreeRoomPayload:!0}),Object.freeze({id:"lane_continuation",version:1,runtimeSupport:i,inputSchema:s(["state"],{state:Object.freeze({type:"string",enum:Object.freeze(["waiting_for_human","resumable","canceled","terminal"])}),resumeKind:Object.freeze({type:"string",enum:Object.freeze(["human_response","approval","redispatch","reconnect"])})}),output:"accepted | deferred | rejected | failed",authority:"bridge",persistence:"durable-safe-ref",continuation:"resumable",secretFreeRoomPayload:!0})]);const h=new Map(RUNTIME_CAPABILITIES.map(e=>[e.id,e]));export const runtimeCapability=e=>h.get(e)||null;export const runtimeSupportsCapability=(t,r)=>e.includes(t)&&"native"===runtimeCapability(r)?.runtimeSupport?.[t];export function isSecretFreeRoomPayload(e,t=8192){if(null==e||(e=>{try{return(new TextEncoder).encode(JSON.stringify(e)).length}catch{return 1/0}})(e)>t)return!1;const r=e=>"string"==typeof e?e.length<=2048&&!a.test(e)&&!c.test(e)&&!p.test(e):null==e||"number"==typeof e||"boolean"==typeof e||(Array.isArray(e)?e.length<=64&&e.every(r):"object"==typeof e&&Object.entries(e).every(([e,t])=>!o.test(e)&&r(t)));return r(e)}function j(e,t){return!t||("object"===t.type?!(!e||"object"!=typeof e||Array.isArray(e))&&(!1!==t.additionalProperties||!Object.keys(e).some(e=>!Object.hasOwn(t.properties||{},e)))&&!(t.required||[]).some(t=>!Object.hasOwn(e,t))&&Object.entries(t.properties||{}).every(([t,r])=>!Object.hasOwn(e,t)||j(e[t],r)):"array"===t.type?Array.isArray(e)&&e.length>=(t.minItems||0)&&e.length<=(t.maxItems??1/0)&&(!t.items||e.every(e=>j(e,t.items))):"string"===t.type?"string"==typeof e&&e.length>=(t.minLength||0)&&e.length<=(t.maxLength??1/0)&&(!t.enum||t.enum.includes(e))&&(!t.pattern||new RegExp(t.pattern).test(e)):"integer"===t.type?Number.isSafeInteger(e)&&e>=(t.minimum??-1/0)&&e<=(t.maximum??1/0):"boolean"===t.type&&"boolean"==typeof e)}export function validateRuntimeCapabilityInput(e,t){const r=runtimeCapability(e);return!!r&&j(t,r.inputSchema)}export function admitRuntimeCapability({runtime:t,capabilityId:r,input:i={},roomPayload:n=null}={}){const a=runtimeCapability(r);return a?e.includes(t)&&"native"===a.runtimeSupport[t]?validateRuntimeCapabilityInput(r,i)?a.secretFreeRoomPayload&&null!=n&&!isSecretFreeRoomPayload(n)?Object.freeze({ok:!1,code:"unsafe_room_payload"}):Object.freeze({ok:!0,code:"admitted",capability:a}):Object.freeze({ok:!1,code:"invalid_capability_input"}):Object.freeze({ok:!1,code:"runtime_capability_mismatch"}):Object.freeze({ok:!1,code:"unregistered_capability"})}export function assertRuntimeCapability(e){const t=admitRuntimeCapability(e);if(!t.ok)throw new TypeError(`Runtime capability rejected: ${t.code}`);return t.capability}
@@ -1 +1 @@
1
- import e from"node:path";import{runtimeCapability as t,runtimeSupportsCapability as o}from"./runtime-contract.mjs";export{normalizeStructuredEffort,reasoningEffortsForLane}from"./reasoning-effort.mjs";const r=Object.freeze({claude:Object.freeze({id:"claude",command:"claude",label:"Claude Code",protocol:"agent-sdk",structured:!0,flow:!0,canSteer:!1,images:!0,nativeModelCatalog:!1,effortControl:!0,defaultMode:"default",modes:Object.freeze(["default","acceptEdits","plan","bypassPermissions"])}),codex:Object.freeze({id:"codex",command:"codex",label:"Codex",protocol:"codex-app-server",structured:!0,flow:!0,canSteer:!0,images:!0,nativeModelCatalog:!0,effortControl:!0,defaultMode:"bypassPermissions",modes:Object.freeze(["default","acceptEdits","plan","bypassPermissions","review"])}),hermes:Object.freeze({id:"hermes",command:"thinkpool",label:"Hermes Agent",protocol:"acp",structured:!0,flow:!0,canSteer:!0,images:!0,nativeModelCatalog:!0,catalogRequiresSession:!0,effortControl:!0,defaultMode:"default",modes:Object.freeze(["default","acceptEdits","plan","bypassPermissions"]),beta:!0})});export const STRUCTURED_RUNTIME_IDS=Object.freeze(Object.keys(r));export const structuredRuntimeMetadata=e=>r[e]||null;export const structuredRuntimeForCommand=t=>{const o=e.basename(String(t||"")).toLowerCase();return Object.values(r).find(e=>e.command===o)?.id||null};export const defaultStructuredMode=e=>structuredRuntimeMetadata(e)?.defaultMode||"default";export const structuredRuntimeSupportsMode=(e,t)=>!0===structuredRuntimeMetadata(e)?.modes?.includes(t);export const structuredRuntimeSupportsFlow=e=>!0===structuredRuntimeMetadata(e)?.flow;export const structuredRuntimeCapability=(e,r)=>o(e,r)?t(r):null;export const structuredModeLocked=({flowRole:e,sliceType:t}={})=>"conductor"===e||"reviewer"===e||"review"===t;export const structuredModeForSlice=(e,t={})=>"reviewer"!==t.flowRole&&"review"!==t.sliceType?t.mode:structuredRuntimeSupportsMode(e,"review")?"review":structuredRuntimeSupportsMode(e,"plan")?"plan":t.mode;export const structuredModesForLane=(e,t={})=>{const o=structuredRuntimeMetadata(e)?.modes||[];return structuredModeLocked(t)&&o.includes(t.mode)?[t.mode]:o};export const shouldDeferStructuredRuntime=({runtime:e,defer:t,cwd:o,flowSessionId:r,flowTaskKey:s,models:d}={})=>{const a=structuredRuntimeMetadata(e);return!(!(!a?.catalogRequiresSession||Array.isArray(d)&&d.length)||!t&&(o||r||s))};
1
+ import e from"node:path";import{runtimeCapability as t,runtimeSupportsCapability as o}from"./runtime-contract.mjs";export{normalizeStructuredEffort,reasoningEffortsForLane}from"./reasoning-effort.mjs";const r=Object.freeze({claude:Object.freeze({id:"claude",command:"claude",label:"Claude Code",protocol:"agent-sdk",structured:!0,flow:!0,canSteer:!1,images:!0,nativeModelCatalog:!1,effortControl:!0,defaultMode:"default",modes:Object.freeze(["default","acceptEdits","plan","bypassPermissions"])}),codex:Object.freeze({id:"codex",command:"codex",label:"Codex",protocol:"codex-app-server",structured:!0,flow:!0,canSteer:!0,images:!0,nativeModelCatalog:!0,effortControl:!0,defaultMode:"bypassPermissions",modes:Object.freeze(["default","acceptEdits","plan","bypassPermissions","review"])}),hermes:Object.freeze({id:"hermes",command:"thinkpool",label:"Hermes Agent",protocol:"acp",structured:!0,flow:!0,canSteer:!0,images:!0,nativeModelCatalog:!0,catalogRequiresSession:!0,effortControl:!0,defaultMode:"default",modes:Object.freeze(["default","acceptEdits","plan","bypassPermissions"]),beta:!0}),opencode:Object.freeze({id:"opencode",command:"opencode",label:"OpenCode",protocol:"acp",structured:!0,flow:!1,canSteer:!1,images:!0,nativeModelCatalog:!1,catalogRequiresSession:!1,effortControl:!1,defaultMode:"default",modes:Object.freeze(["default"]),ordinaryOnly:!0})});export const STRUCTURED_RUNTIME_IDS=Object.freeze(Object.keys(r));export const structuredRuntimeMetadata=e=>r[e]||null;export const structuredRuntimeForCommand=t=>{const o=e.basename(String(t||"")).toLowerCase();return Object.values(r).find(e=>e.command===o)?.id||null};export const defaultStructuredMode=e=>structuredRuntimeMetadata(e)?.defaultMode||"default";export const structuredRuntimeSupportsMode=(e,t)=>!0===structuredRuntimeMetadata(e)?.modes?.includes(t);export const structuredRuntimeSupportsFlow=e=>!0===structuredRuntimeMetadata(e)?.flow;export const structuredRuntimeRoleSupported=(e,t={})=>{const o=structuredRuntimeMetadata(e);return!!o&&(!o.ordinaryOnly||!t.flowRole&&"review"!==t.sliceType&&"plan"!==t.sliceType)};export const structuredRuntimeCapability=(e,r)=>o(e,r)?t(r):null;export const structuredModeLocked=({flowRole:e,sliceType:t}={})=>"conductor"===e||"reviewer"===e||"review"===t;export const structuredModeForSlice=(e,t={})=>structuredRuntimeRoleSupported(e,t)?"reviewer"!==t.flowRole&&"review"!==t.sliceType?t.mode:structuredRuntimeSupportsMode(e,"review")?"review":structuredRuntimeSupportsMode(e,"plan")?"plan":t.mode:null;export const structuredModesForLane=(e,t={})=>{const o=structuredRuntimeMetadata(e)?.modes||[];return structuredModeLocked(t)&&o.includes(t.mode)?[t.mode]:o};export const shouldDeferStructuredRuntime=({runtime:e,defer:t,cwd:o,flowSessionId:r,flowTaskKey:d,models:s}={})=>{const a=structuredRuntimeMetadata(e);return!(!(!a?.catalogRequiresSession||Array.isArray(s)&&s.length)||!t&&(o||r||d))};
@@ -1 +1 @@
1
- import{startClaudeSession as r}from"./claude-session.mjs";import{startCodexSession as t}from"./codex-session.mjs";import{startHermesSession as e}from"./hermes-session.mjs";import{assertRuntimeCapability as o}from"./runtime-contract.mjs";const s=Object.freeze({claude:r,codex:t,hermes:e});export function startStructuredSession(r,t){const e=s[r];if(!e)throw new Error(`Unsupported structured runtime: ${r}`);return o({runtime:r,capabilityId:"terminal_interrupt",input:{}}),e(t)}
1
+ import{startClaudeSession as e}from"./claude-session.mjs";import{startCodexSession as r}from"./codex-session.mjs";import{startHermesSession as o}from"./hermes-session.mjs";import{startOpenCodeSession as t}from"./opencode-session.mjs";import{assertRuntimeCapability as s}from"./runtime-contract.mjs";const n=Object.freeze({claude:e,codex:r,hermes:o,opencode:t});export function startStructuredSession(e,r){const o=n[e];if(!o)throw new Error(`Unsupported structured runtime: ${e}`);if("opencode"===e&&(r?.flowRole||"review"===r?.sliceType||"plan"===r?.sliceType))throw new Error("OpenCode runtime selection rejected: structural_role_unsupported");return s({runtime:e,capabilityId:"terminal_interrupt",input:{}}),o(r)}