thinkpool-pair 0.7.416 → 0.7.418
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/account.mjs +1 -1
- package/bridge.mjs +1 -1
- package/claude-session.mjs +1 -1
- package/cloud-session-transcript.mjs +1 -1
- package/hermes-acp-bootstrap.py +19 -3
- package/hermes-policy.mjs +1 -1
- package/hermes-session.mjs +1 -1
- package/lane-work-snapshot.mjs +1 -1
- package/lane-worktree.mjs +1 -1
- package/package.json +3 -3
- package/publish-manifest.json +17 -17
- package/room-file-delivery.mjs +1 -0
- package/terminal-close-auth.mjs +1 -0
- package/terminal-row-reconcile.mjs +1 -1
- package/thinkpool-capabilities.json +28 -1
- package/handoff-in.mjs +0 -1
- package/handoff-out.mjs +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"bundleVersion":
|
|
3
|
+
"bundleVersion": 40,
|
|
4
4
|
"contracts": [
|
|
5
5
|
{
|
|
6
6
|
"id": "room-coordination",
|
|
@@ -76,6 +76,33 @@
|
|
|
76
76
|
{"path": "bridge/codex-app-server.mjs", "pattern": "mcpServer/startupStatus/updated"}
|
|
77
77
|
]
|
|
78
78
|
},
|
|
79
|
+
{
|
|
80
|
+
"id": "room-file-delivery",
|
|
81
|
+
"version": 1,
|
|
82
|
+
"routes": [
|
|
83
|
+
{
|
|
84
|
+
"id": "room-file-delivery",
|
|
85
|
+
"tools": ["attach_file"],
|
|
86
|
+
"trigger": "\\b(file|pdf|document|docx|spreadsheet|xlsx|presentation|pptx|archive|zip|report|artifact)\\b.{0,60}\\b(send|deliver|attach|download|open|link|share|give)\\b|\\b(send|deliver|attach|download|open|share|give)\\b.{0,60}\\b(file|pdf|document|docx|spreadsheet|xlsx|presentation|pptx|archive|zip|report|artifact)\\b|\\battach_file\\b",
|
|
87
|
+
"prompt": "When a person needs to open or download a generated file, use attach_file after the file exists. A host path, file:// URL, localhost URL, codex-file-citation directive, or statement that the file was written is not delivery. Call attach_file once and rely on its durable room receipt. If it fails, report the single concrete failure instead of retrying a different host-only surface."
|
|
88
|
+
}
|
|
89
|
+
],
|
|
90
|
+
"impact": [
|
|
91
|
+
{"path": "bridge/room-file-delivery.mjs"},
|
|
92
|
+
{"path": "bridge/bridge.mjs", "diffPattern": "attach_file|uploadRoomFile"},
|
|
93
|
+
{"path": "src/pages/code/structured.jsx", "diffPattern": "StructFiles|evt.files"},
|
|
94
|
+
{"path": "bridge/claude-session.mjs", "diffPattern": "attach_file"},
|
|
95
|
+
{"path": "bridge/hermes-policy.mjs", "diffPattern": "ROOM_FILE_DELIVERY_TOOL"},
|
|
96
|
+
{"path": "bridge/hermes-session.mjs", "diffPattern": "ROOM_FILE_DELIVERY_TOOL"}
|
|
97
|
+
],
|
|
98
|
+
"evidence": [
|
|
99
|
+
{"path": "bridge/room-file-delivery.mjs", "pattern": "uploadRoomFile"},
|
|
100
|
+
{"path": "bridge/bridge.mjs", "pattern": "'attach_file'"},
|
|
101
|
+
{"path": "src/pages/code/structured.jsx", "pattern": "<StructFiles code={code} files={evt.files}"},
|
|
102
|
+
{"path": "bridge/claude-session.mjs", "pattern": "mcp__thinkpool__attach_file"},
|
|
103
|
+
{"path": "bridge/hermes-policy.mjs", "pattern": "ROOM_FILE_DELIVERY_TOOL"}
|
|
104
|
+
]
|
|
105
|
+
},
|
|
79
106
|
{
|
|
80
107
|
"id": "work-routing",
|
|
81
108
|
"version": 13,
|
package/handoff-in.mjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import r from"node:crypto";import{promisify as e}from"node:util";import t from"node:zlib";const n=e(t.gunzip),a=new Set(["claude","codex","hermes","opencode"]),o=(r,e)=>{if(r?.error)throw new Error(`${e}: ${r.error.message||r.error}`);return Array.isArray(r?.data)?r.data:[]},s=r=>a.has(String(r||"").toLowerCase())?String(r).toLowerCase():"claude";async function i(e,t){const a=Buffer.isBuffer(e)?e:Buffer.from(e||[]);if(!a.length)throw new Error("handoff transcript object is empty");if(null!=t?.transcript_bytes&&Number(t.transcript_bytes)!==a.byteLength)throw new Error(`handoff transcript length mismatch (${a.byteLength} != ${t.transcript_bytes})`);if(t?.transcript_sha256&&(o=a,r.createHash("sha256").update(o).digest("hex")!==t.transcript_sha256))throw new Error("handoff transcript sha256 mismatch");var o;const s=await n(a,{maxOutputLength:25165824}),i=[];for(const r of s.toString("utf8").split("\n"))if(r&&!(i.length>=1e4))try{const e=JSON.parse(r);e&&"object"==typeof e&&!Array.isArray(e)&&i.push(e)}catch{}return i}function c(r,{bridgeId:e,sourceGeneration:t}){const n=new Map;for(const a of r||[]){if(!a?.terminal_id||a.from_bridge_id===e)continue;if(Number(a.lease_generation)!==t)continue;const r=n.get(a.terminal_id);(!r||String(a.created_at||"")>String(r.created_at||""))&&n.set(a.terminal_id,a)}return n}export async function receiveHandoffBundles({sb:r,room:e,bridgeId:t,hostId:n,fencing:a,localIds:d=[],waitMs:f=5e4,pollMs:l=1e3,sleep:h=r=>new Promise(e=>setTimeout(e,r)),ops:u,log:m=()=>{}}={}){if(!e)throw new Error("handoff-in requires room");if(!t)throw new Error("handoff-in requires bridgeId");if(!n)throw new Error("handoff-in requires hostId");const p=Number(a);if(!Number.isSafeInteger(p)||p<1)return{records:[],warnings:[],foreignTerminalCount:0};const w=u||function(r){if(!r?.from||!r?.storage?.from)throw new Error("handoff-in requires a Supabase client or injected ops");return{listTerminals:async e=>o(await r.from("code_terminals").select("id,name,agent,kind,host_id,host_label,last_active_at").eq("session_code",e),"terminal roster"),listHandoffs:async(e,t)=>o(await r.from("code_session_handoffs").select("terminal_id,from_bridge_id,lease_generation,sdk_session_id,branch,sha,transcript_path,transcript_bytes,transcript_sha256,cwd,warm,checkpoint_status,checkpoint_error,created_at").eq("session_code",e).eq("lease_generation",t).order("created_at",{ascending:!1}).limit(64),"handoff rows"),downloadTranscript:async e=>{const t=await r.storage.from("code-handoffs").download(e);if(t?.error)throw new Error(t.error.message||String(t.error));if(!t?.data?.arrayBuffer)throw new Error("handoff transcript object is empty");return Buffer.from(await t.data.arrayBuffer())},readCloudSnapshot:async(e,t)=>{const n=await r.from("code_messages").select("payload,created_at").eq("session_code",e).eq("id",`tx:${t}`).maybeSingle();return(r=>{if(r?.error)throw new Error(`cloud transcript snapshot: ${r.error.message||r.error}`);return r?.data||null})(n)?.payload||null}}}(r),g=new Set(d||[]),_=(await w.listTerminals(e)||[]).filter(r=>r?.id&&"structured"===r.kind&&r.host_id!==n&&!g.has(r.id));if(!_.length)return{records:[],warnings:[],foreignTerminalCount:0};const y=p-1,b=Math.max(1,Math.ceil(Math.max(0,f)/Math.max(1,l))+1);let S=new Map;for(let r=0;r<b&&(S=c(await w.listHandoffs(e,y),{bridgeId:t,sourceGeneration:y}),!_.every(r=>S.has(r.id)));r++)r+1<b&&await h(Math.max(1,l));const E=[],$=[];for(const r of _){const t=S.get(r.id)||null;let n=null,a=null;if(t?.transcript_path)try{n=await i(await w.downloadTranscript(t.transcript_path),t),a="handoff-object"}catch(e){const t=`${r.id}: ${e?.message||e}`;E.push(t),m(`[handoff-in] ${t}; using cloud snapshot`)}if(!n)try{const t=await w.readCloudSnapshot(e,r.id);n=Array.isArray(t?.events)?t.events.filter(r=>r&&"object"==typeof r&&!Array.isArray(r)).slice(-1e4):[],a="cloud-snapshot"}catch(e){const t=`${r.id}: cloud snapshot failed: ${e?.message||e}`;E.push(t),m(`[handoff-in] ${t}`),n=[],a="empty-cold-start"}$.push({id:r.id,name:r.name||null,runtime:s(r.agent),log:n,cwd:t?.cwd||null,sessionId:null,branch:t?.branch||null,sha:t?.sha||null,checkpointStatus:t?.checkpoint_status||null,checkpointError:t?.checkpoint_error||null,source:a})}return{records:$,warnings:E,foreignTerminalCount:_.length}}
|
package/handoff-out.mjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import t from"node:crypto";import{promisify as e}from"node:util";import n from"node:zlib";const r=e(n.gzip),o=20971520;export async function exportHandoffBundles({sb:e,room:n,terminals:s=[],env:a={},checkpointTerminal:i,log:l=()=>{}}){const{accountId:c,bridgeId:d,fencing:u}=a;if(!e)throw new Error("exportHandoffBundles requires sb (Supabase client)");if(!n)throw new Error("exportHandoffBundles requires room (session code)");if(!c)throw new Error("exportHandoffBundles requires env.accountId");if(!d)throw new Error("exportHandoffBundles requires env.bridgeId");let f=0,p=0,h=0;return await Promise.all(s.map(async s=>{const a=s?.id;if(a)try{if(function({session:t}){return!(!t||!0!==t.turnActive)}(s)&&!0!==s.handoffBoundary)return l(`[handoff-out] terminal ${a}: skipped (turn in flight)`),void p++;const m=s.session||{},y=s.transcript||[],w=function(t){if(!Array.isArray(t))return null;for(let e=t.length-1;e>=0;e--){const n=t[e]?.work;if(n&&"object"==typeof n){const t=n.identity?.sdkSessionId||null,e=n.git?.branch||null,r=n.git?.headSha||null,o=n.git?.worktreeState||null,s=n.capturedAt||null;return t||e||r?{sdkSessionId:t,branch:e,sha:r,worktree:o,capturedAt:s}:null}}return null}(y)||{},g=w.sdkSessionId;let b=w.branch,$=w.sha,_=null,k=null;if("function"==typeof i)try{const t=await i(s);t?.ok?(b=t.branch||b,$=t.sha||$,_="pushed"):(_="failed",k=String(t?.reason||"checkpoint unavailable").slice(0,500))}catch(t){_="failed",k=String(t?.message||t).slice(0,500)}const I=function(t){if(!Array.isArray(t))return"";const e=new Set(["you","assistant","tool_use","tool_result","result","error","attachment","propose","pool","__struct","__txsnap"]);return t.filter(t=>t&&"object"==typeof t&&e.has(t.kind)).slice(-1e4).map(t=>JSON.stringify(t)).join("\n")+"\n"}(y);I||l(`[handoff-out] terminal ${a}: empty transcript, writing minimal bundle`);const S=await async function(t){let e=t.split("\n").filter(Boolean);const n=async()=>{const t=e.slice(0,Math.floor(.7*e.length)).join("\n")+"\n",n=await r(t,{level:9});return{compressed:n,bytes:n.byteLength,truncated:!0}};try{const s=await r(t,{level:9});if(s.byteLength<=o)return{compressed:s,bytes:s.byteLength,truncated:!1};const a=await n();if(a.bytes<=o)return a;e=e.slice(0,Math.floor(.3*e.length));const i=await n();return i.bytes<=o?i:{bytes:i.bytes,compressed:null,truncated:!0}}catch(t){return{bytes:0,compressed:null,truncated:!1,error:t?.message||String(t)}}}(I),{compressed:x,bytes:v,truncated:B}=S;let A=null,H=null,j=null;if(x){H=v,j=function(e){return t.createHash("sha256").update(e).digest("hex")}(x);const r=function({accountId:t,room:e,terminalId:n}){return`handoff/${t}/${e}/${n}.jsonl.gz`}({accountId:c,room:n,terminalId:a});try{const{error:t}=await e.storage.from("code-handoffs").upload(r,x,{contentType:"application/gzip",upsert:!0});if(t)throw t;A=r,l(`[handoff-out] terminal ${a}: uploaded transcript (${v} bytes${B?", truncated":""})`)}catch(t){l(`[handoff-out] terminal ${a}: upload failed: ${t?.message||t}`),A=null}}else l(`[handoff-out] terminal ${a}: transcript too large (${v} bytes cap exceeded), writing minimal bundle`);const q=Number(u)||0,z={session_code:n,terminal_id:a,from_bridge_id:d,lease_generation:q,sdk_session_id:g,branch:b,sha:$,transcript_path:A,transcript_bytes:H,transcript_sha256:j,cwd:s.cwd||m.cwd||null,warm:"failed"!==_&&!!(g&&b&&$),checkpoint_status:_,checkpoint_error:k};try{const{error:t}=await e.from("code_session_handoffs").insert(z);if(t)throw t;f++,l(`[handoff-out] terminal ${a}: wrote handoff row (warm=${z.warm})`)}catch(t){l(`[handoff-out] terminal ${a}: DB insert failed: ${t?.message||t}`),h++}}catch(t){l(`[handoff-out] terminal ${s.id||"?"}: error: ${t?.message||t}`),h++}else l("[handoff-out] skipping terminal with missing id")})),l(`[handoff-out] complete: written=${f}, skipped=${p}, errors=${h}`),{written:f,skipped:p,errors:h}}
|