thinkpool-pair 0.7.427 → 0.7.428
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/package.json +1 -1
- package/publish-manifest.json +5 -5
- package/scheduled-runs.mjs +1 -1
package/package.json
CHANGED
package/publish-manifest.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"format": 1,
|
|
3
3
|
"package": "thinkpool-pair",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.428",
|
|
5
5
|
"kind": "minified",
|
|
6
6
|
"minifiedModules": 142,
|
|
7
|
-
"sourceModuleBytes":
|
|
8
|
-
"artifactModuleBytes":
|
|
7
|
+
"sourceModuleBytes": 1878442,
|
|
8
|
+
"artifactModuleBytes": 857962,
|
|
9
9
|
"files": {
|
|
10
|
-
"package.json": "
|
|
10
|
+
"package.json": "4ad6287c672a898c17331e6fa51352d49647dd63e8b2ea7c48a8b389aceb93f0",
|
|
11
11
|
"LICENSE": "8a030197ca1cad9669909ca14c9ad15cf48d9fe551da526ccaf1fca993eddb23",
|
|
12
12
|
"bridge.mjs": "b4ece124df615cd190e7b7472a64969121c4cd03ec1bfa628f77c32fa4a61bd2",
|
|
13
13
|
"bridge-service.sh": "b64f27c473ca8f3a49190fd08c23947ab14ca9958d70b6fa53c7bddc2be91403",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"error-recovery.mjs": "0ace80add28fa72b49a3f3a716f247e3ef9816671c09749b3863867700beae32",
|
|
89
89
|
"pair-control-authority.mjs": "7a95f101153dcc6dd0633b5a01595bf2979cd0c4bf50cfc6cd44bb7612ef40a5",
|
|
90
90
|
"pair-access.mjs": "953d32528a08cde1bfeef58caafa0ce97274df8f0251d8a3be2bd190e382b5cc",
|
|
91
|
-
"scheduled-runs.mjs": "
|
|
91
|
+
"scheduled-runs.mjs": "74c34a4bb63eb8973012a169f3c7de7ff6438b20ed9cedd0ef6d57ee360b92f4",
|
|
92
92
|
"scheduled-run-admission.mjs": "3a2098d904c3aff571bf314e0182d5636d25d242cef52207e70f9dc1618c94f5",
|
|
93
93
|
"event-id.mjs": "09c75e7fc8da282fc00651add58e5d2f82d3020e0c4dddb9921250cf9a6fa8c0",
|
|
94
94
|
"event-bounds.mjs": "aa8eb8517c4aa81b3378f71401ed39c550cdc80e28e3a57ab46d0a5ef5c7c9c1",
|
package/scheduled-runs.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{randomUUID as e}from"node:crypto";import{SPAWN as t,spawnDecision as n}from"./cross-terminal.mjs";const i=new Set(["once","daily","weekly"]),r=new Set(["claude","codex","hermes"]),o=new Set(["delivered","needs_decision","failed","canceled"]),d=new Set(["artifact","preview","commit","test","flow_task","control_item"]),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._-]{16,}|(?:token|secret|api[_-]?key|authorization)\s*=)/i,c=/(?:^|\s)(?:~\/|\/Users\/|\/home\/|\/private\/|\/tmp\/|[A-Za-z]:\\|\.\.[\\/])/i,u=/^[A-Za-z0-9][A-Za-z0-9._:@-]{0,159}$/,l=/^[A-Za-z0-9][A-Za-z0-9._:-]{0,119}$/,s=new Map,_=new Set([15,30,60]);export const scheduledRunsEnabled=(e=process.env.TP_SCHEDULED_RUNS_ENABLED)=>"1"===e;export const scheduledRunsCapability=(e=process.env.TP_SCHEDULED_RUNS_ENABLED)=>Object.freeze({enabled:scheduledRunsEnabled(e)});export async function admitScheduledRunExecution({terminalId:e,localAdmission:t,memoryAdmission:n,acquireHost:i,acquireScheduled:r,releaseHost:o}={}){if("string"!=typeof e||!u.test(e))return{ok:!1,code:"terminal_id_unavailable"};if("function"!=typeof t||"function"!=typeof n||"function"!=typeof i||"function"!=typeof r||"function"!=typeof o)return{ok:!1,code:"spawn_admission_unavailable"};let d=null;try{d=await t()}catch{d=null}if(!d?.ok)return d||{ok:!1,code:"spawn_not_admitted"};let a=null;try{a=await n()}catch{a=null}if(!a?.ok)return a||{ok:!1,code:"host_memory_unavailable"};let c=null;try{c=await i()}catch{c=null}if(!c?.ok)return c||{ok:!1,code:"capacity_authority_unavailable"};let l=null;try{l=await r()}catch{l=null}if(!l?.ok||!l.lease){try{await o(e)}catch{}return l||{ok:!1,code:"scheduled_admission_unavailable"}}return{ok:!0,code:"admitted",lease:{terminalId:e,scheduled:l.lease}}}export async function releaseScheduledRunExecution(e,{releaseScheduled:t,releaseHost:n}={}){if(!e?.scheduled||"string"!=typeof e.terminalId||"function"!=typeof t||"function"!=typeof n)return{ok:!1,code:"invalid_execution_lease"};let i=null;try{i=await t(e.scheduled)}catch{i=null}try{await n(e.terminalId)}catch{}return i||{ok:!1,code:"scheduled_release_failed"}}const p=(e,t)=>"string"==typeof e&&e.trim().length>0&&e.length<=t&&!a.test(e)&&!c.test(e),m=e=>e instanceof Date?e:new Date(e),f=e=>!Number.isNaN(m(e).getTime()),h=(e,t)=>{let n=s.get(e);n||(n=new Intl.DateTimeFormat("en-CA",{timeZone:e,weekday:"short",hour:"2-digit",minute:"2-digit",hourCycle:"h23"}),s.set(e,n));const i=Object.fromEntries(n.formatToParts(t).filter(e=>"literal"!==e.type).map(e=>[e.type,e.value]));return{weekday:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"].indexOf(i.weekday),time:`${i.hour}:${i.minute}`}};export function scheduleValidationError(e={}){if(!e||"object"!=typeof e||!i.has(e.kind))return"invalid_kind";if(!p(e.title,120)||!p(e.prompt,12e3))return"unsafe_or_invalid_text";if(!r.has(e.runtime))return"invalid_runtime";if(!(null==e.provider||p(e.provider,80)&&u.test(e.provider)))return"invalid_provider";if(!(null==e.model||p(e.model,160)&&u.test(e.model)))return"invalid_model";if(!Number.isInteger(e.maxRuntimeMinutes)||e.maxRuntimeMinutes<1||e.maxRuntimeMinutes>30)return"invalid_max_runtime";try{new Intl.DateTimeFormat("en",{timeZone:e.timezone})}catch{return"invalid_timezone"}return"once"!==e.kind||f(e.at)?null==e.intervalMinutes||_.has(e.intervalMinutes)?"once"!==e.kind&&!/^\d{2}:\d{2}$/.test(e.time)||"once"!==e.kind&&(Number(e.time.slice(0,2))>23||Number(e.time.slice(3))>59)?"invalid_local_time":"weekly"===e.kind&&(!Number.isInteger(e.weekday)||e.weekday<0||e.weekday>6)?"invalid_weekday":null:"invalid_interval":"invalid_once_time"}export function normalizeSchedule(e={},t=new Date){const n=scheduleValidationError(e);if(n)return Object.freeze({ok:!1,code:n});const i={kind:e.kind,title:e.title.trim(),prompt:e.prompt.trim(),runtime:e.runtime,provider:e.provider||null,model:e.model||null,timezone:e.timezone,maxRuntimeMinutes:e.maxRuntimeMinutes,..."once"===e.kind?{at:m(e.at).toISOString()}:{time:e.time,..."weekly"===e.kind?{weekday:e.weekday}:{},...e.intervalMinutes?{interval_minutes:e.intervalMinutes}:{}}},r=nextScheduledAt(i,t);return r?Object.freeze({ok:!0,value:Object.freeze(i),nextRunAt:r.toISOString()}):Object.freeze({ok:!1,code:"schedule_exhausted"})}export function nextScheduledAt(e,t=new Date){if("once"===e?.kind){const n=m(e.at);return f(n)&&n.getTime()>m(t).getTime()?n:null}const n=Number(e?.interval_minutes);if(_.has(n))return new Date(m(t).getTime()+6e4*n);const i=6e4*Math.floor(m(t).getTime()/6e4)+6e4;for(let t=i,n=i+3456e7;t<n;t+=6e4){const n=h(e.timezone,new Date(t));if(n.time===e.time&&("daily"===e.kind||n.weekday===e.weekday))return new Date(t)}return null}export function classifyRunOutcome({result:e=null,evidenceRefs:t=[],pendingControls:n=[],runId:i=null,canceled:r=!1}={}){if("runtime_limit"===e?.subtype)return Object.freeze({outcome:"failed",code:"runtime_limit"});if(r||["aborted","canceled","cancelled","interrupted"].includes(e?.subtype))return Object.freeze({outcome:"canceled",code:"canceled"});const o=(Array.isArray(t)?t:[]).filter(e=>e&&d.has(e.type)&&"string"==typeof e.id&&u.test(e.id)).slice(0,16);if(o.length)return Object.freeze({outcome:"delivered",code:"evidence_delivered",evidence:o});const a=(Array.isArray(n)?n:[]).find(e=>"pending"===e?.status&&e?.id&&e?.request_context?.run_id&&(!i||e.request_context.run_id===i)&&Number.isSafeInteger(Number(e.source_event_from_seq)));return a?Object.freeze({outcome:"needs_decision",code:"pending_pair_control",controlItemId:a.id}):"success"===e?.subtype?Object.freeze({outcome:"failed",code:"missing_deliverable"}):Object.freeze({outcome:"failed",code:e?.subtype||"runtime_failed"})}export function sanitizeScheduledOutcomeIntent({runId:e,result:t=null,evidenceRefs:n=[],canceled:i=!1}={}){if("string"!=typeof e||!u.test(e))return null;const r="string"==typeof t?.subtype&&l.test(t.subtype)?t.subtype:"runtime_failed";return Object.freeze({runId:e,result:Object.freeze({subtype:r}),evidenceRefs:Object.freeze((o=n,(Array.isArray(o)?o:[]).filter(e=>e&&d.has(e.type)&&"string"==typeof e.id&&u.test(e.id)).slice(0,16).map(e=>Object.freeze({type:e.type,id:e.id})))),canceled:!0===i});var o}export function scheduledRunDeadlineRequired({runId:e,deadlineAt:t,outcomeRecorded:n=!1,outcomePending:i=null}={}){return Boolean(e&&Number.isFinite(t)&&!n&&!i)}export function scheduledOutcomeReconciliationComplete(e=[]){return Array.isArray(e)&&0===e.length}export function scheduledRunSpawnAdmission({spawnTimes:e=[],now:i=Date.now(),totalLive:r=0,disabled:o=!1}={},d=t){const a={...t,...d||{}},c=(Array.isArray(e)?e:[]).filter(e=>Number.isFinite(e)&&e>i-a.windowMs).slice(-(a.perWindowCap||1)),u=n({hop:0,spawnTimes:c,now:i,spawnedLive:0,totalLive:r,plan:"free",disabled:o},a);return Object.freeze({...u,spawnTimes:Object.freeze(u.ok?[...c,i].slice(-a.perWindowCap):c)})}export function preflightScheduledRun({schedule:e,occurrence:t,ownerId:n,bridgeId:i,bridgeFencing:r,providerAvailable:o,capsOk:d=!0,now:a=new Date}={}){return e?.enabled?t?.id&&t.schedule_revision===e.revision?!n||!i||!Number.isSafeInteger(r)||r<1||t.owner_id!==n||t.bridge_id!==i||t.bridge_fencing!==r?Object.freeze({ok:!1,code:"owner_bridge_mismatch"}):d?"function"==typeof o&&o(e)?!t.lease_expires_at||m(t.lease_expires_at).getTime()<=m(a).getTime()?Object.freeze({ok:!1,code:"lease_expired"}):Object.freeze({ok:!0,code:"admitted"}):Object.freeze({ok:!1,code:"provider_unavailable"}):Object.freeze({ok:!1,code:"runtime_cap_exceeded"}):Object.freeze({ok:!1,code:"stale_schedule_revision"}):Object.freeze({ok:!1,code:"schedule_disabled"})}const b=async({fetchImpl:e,supabaseUrl:t,headers:n,name:i,body:r})=>{const o=await e(`${String(t).replace(/\/$/,"")}/rest/v1/rpc/${i}`,{method:"POST",headers:n,body:JSON.stringify(r)});if(!o?.ok)throw new Error(`${i}_failed`);return o.json()};export async function pollDueScheduledRuns({enabled:t=!1,fetchImpl:n=globalThis.fetch,supabaseUrl:i,anonKey:r,token:o,roomCode:d,bridgeId:a,bridgeFencing:c,ownerId:l,providerAvailable:s,openTerminal:_,admitRun:p,releaseRun:f,makeTerminalId:h=e,capsOk:y=()=>!0,now:g=new Date}={}){if(!t)return Object.freeze({ok:!1,code:"feature_disabled",runs:[]});if(!("function"==typeof n&&i&&r&&o&&d&&a&&Number.isSafeInteger(c))||c<1||!l||"function"!=typeof _||"function"!=typeof p||"function"!=typeof f||"function"!=typeof h)return Object.freeze({ok:!1,code:"runner_unavailable",runs:[]});const k={apikey:r,Authorization:`Bearer ${o}`,"Content-Type":"application/json"},w=String(d).trim().toUpperCase();try{const e=await b({fetchImpl:n,supabaseUrl:i,headers:k,name:"expire_code_scheduled_runs",body:{p_room_code:w,p_bridge_id:a,p_bridge_fencing:c,p_limit:24}});if(!e?.ok)throw new Error("expire_code_scheduled_runs_failed");const t=await b({fetchImpl:n,supabaseUrl:i,headers:k,name:"list_due_code_schedules",body:{p_room_code:w,p_limit:12}}),r=[];for(const e of Array.isArray(t)?t:[]){if(String(e?.session_code||"").trim().toUpperCase()!==w){r.push({scheduleId:e?.id,code:"room_scope_mismatch"});continue}if(!y(e)){r.push({scheduleId:e.id,code:"runtime_cap_exceeded"});continue}if("function"!=typeof s||!s(e)){r.push({scheduleId:e.id,code:"provider_unavailable"});continue}const t=h();if("string"!=typeof t||!u.test(t)){r.push({scheduleId:e.id,code:"terminal_id_unavailable"});continue}const o={...e.schedule_spec||{},kind:e.schedule_kind||e.kind,timezone:e.timezone},d="once"===o.kind?new Date("9999-12-31T23:59:00.000Z"):nextScheduledAt(o,new Date(e.next_run_at));if(!d){r.push({scheduleId:e.id,code:"next_run_invalid"});continue}const v=`${e.id}:${m(e.next_run_at).toISOString()}`,I=Math.min(1860,Math.max(60,60*e.max_runtime_minutes+60)),z=m(g).getTime()+1e3*I;let x=null;try{x=await p({schedule:e,runId:v,terminalId:t,deadlineAt:z})}catch{x=null}if(!x?.ok){r.push({scheduleId:e.id,code:x?.code||"spawn_not_admitted"});continue}let O=!1;try{const o=await b({fetchImpl:n,supabaseUrl:i,headers:k,name:"claim_due_code_schedule",body:{p_schedule_id:e.id,p_expected_revision:e.revision,p_bridge_id:a,p_bridge_fencing:c,p_occurrence_key:v,p_lease_seconds:I}});if(!o?.ok||!o?.run){r.push({scheduleId:e.id,code:o?.code||"claim_failed"});continue}const u=preflightScheduledRun({schedule:e,occurrence:o.run,ownerId:l,bridgeId:a,bridgeFencing:c,providerAvailable:s,capsOk:!0,now:g});if(!u.ok){r.push({scheduleId:e.id,runId:o.run.id,code:u.code});continue}const p=await b({fetchImpl:n,supabaseUrl:i,headers:k,name:"open_code_scheduled_run",body:{p_run_id:o.run.id,p_bridge_id:a,p_bridge_fencing:c,p_terminal_id:t,p_next_run_at:d.toISOString()}});if(!p?.ok){r.push({scheduleId:e.id,runId:o.run.id,code:p?.code||"open_not_persisted"});continue}const m=p.run||o.run;let f=null;try{f=await _({schedule:e,run:m,terminalId:t,admission:x.lease})}catch{f=null}if("string"==typeof f?f:!0===f?t:!0===f?.ok&&"string"==typeof f.terminalId&&f.terminalId){O=!0,r.push({scheduleId:e.id,runId:o.run.id,code:"opened"});continue}const h=!1===f?.ok&&"string"==typeof f.code&&/^terminal_[a-z0-9_]{1,100}$/.test(f.code)?f.code:"terminal_open_failed",y=await b({fetchImpl:n,supabaseUrl:i,headers:k,name:"finish_code_scheduled_run",body:{p_run_id:o.run.id,p_bridge_id:a,p_bridge_fencing:c,p_outcome:"failed",p_outcome_code:h,p_evidence_refs:[],p_decision_item_id:null}});r.push({scheduleId:e.id,runId:o.run.id,code:y?.ok?h:y?.code||"open_failed_unrecorded"})}finally{if(!O)try{await f(x.lease)}catch{}}}return Object.freeze({ok:!0,code:"polled",runs:Object.freeze(r)})}catch{return Object.freeze({ok:!1,code:"runner_read_failed",runs:[]})}}export async function finishScheduledRun({fetchImpl:e=globalThis.fetch,supabaseUrl:t,anonKey:n,token:i,roomCode:r,runId:o,bridgeId:d,bridgeFencing:a,result:c,evidenceRefs:u,canceled:l=!1}={}){if(!(t&&n&&i&&r&&o&&d&&Number.isSafeInteger(a))||a<1)return Object.freeze({ok:!1,code:"outcome_unavailable"});const s={apikey:n,Authorization:`Bearer ${i}`,"Content-Type":"application/json"};try{const n=classifyRunOutcome({result:c,evidenceRefs:u,pendingControls:await b({fetchImpl:e,supabaseUrl:t,headers:s,name:"list_code_pair_controls",body:{p_session_code:String(r).toUpperCase(),p_status:"pending",p_limit:100}}),runId:o,canceled:l}),i=await b({fetchImpl:e,supabaseUrl:t,headers:s,name:"finish_code_scheduled_run",body:{p_run_id:o,p_outcome:n.outcome,p_outcome_code:n.code,p_bridge_id:d,p_bridge_fencing:a,p_evidence_refs:n.evidence||[],p_decision_item_id:n.controlItemId||null}});return Object.freeze({ok:Boolean(i?.ok),code:i?.code||"outcome_write_failed",outcome:n})}catch{return Object.freeze({ok:!1,code:"outcome_write_failed"})}}export async function finishScheduledRunWithRetry(e={},{attempts:t=3,delays:n=[100,400],sleep:i=e=>new Promise(t=>setTimeout(t,e))}={}){const r=Math.max(1,Math.min(5,Number.isInteger(t)?t:3));let o=Object.freeze({ok:!1,code:"outcome_write_failed"});for(let t=0;t<r;t++){if(o=await finishScheduledRun(e),o.ok)return o;t+1<r&&await i(Math.max(0,Math.min(5e3,Number(n[t]??n.at(-1)??0)||0)))}return o}export{o as OUTCOMES};
|
|
1
|
+
import{randomUUID as e}from"node:crypto";import{SPAWN as t,spawnDecision as n}from"./cross-terminal.mjs";const i=new Set(["once","daily","weekly"]),r=new Set(["claude","codex","hermes"]),o=new Set(["delivered","needs_decision","failed","canceled"]),d=new Set(["artifact","preview","commit","test","flow_task","control_item"]),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._-]{16,}|(?:token|secret|api[_-]?key|authorization)\s*=)/i,c=/(?:^|\s)(?:~\/|\/Users\/|\/home\/|\/private\/|\/tmp\/|[A-Za-z]:\\|\.\.[\\/])/i,u=/^[A-Za-z0-9][A-Za-z0-9._:@-]{0,159}$/,l=/^[A-Za-z0-9][A-Za-z0-9._:-]{0,119}$/,s=new Map,_=new Set([15,30,60]);export const scheduledRunsEnabled=(e=process.env.TP_SCHEDULED_RUNS_ENABLED)=>"1"===e;export const scheduledRunsCapability=(e=process.env.TP_SCHEDULED_RUNS_ENABLED)=>Object.freeze({enabled:scheduledRunsEnabled(e)});export async function admitScheduledRunExecution({terminalId:e,localAdmission:t,memoryAdmission:n,acquireHost:i,acquireScheduled:r,releaseHost:o}={}){if("string"!=typeof e||!u.test(e))return{ok:!1,code:"terminal_id_unavailable"};if("function"!=typeof t||"function"!=typeof n||"function"!=typeof i||"function"!=typeof r||"function"!=typeof o)return{ok:!1,code:"spawn_admission_unavailable"};let d=null;try{d=await t()}catch{d=null}if(!d?.ok)return d||{ok:!1,code:"spawn_not_admitted"};let a=null;try{a=await n()}catch{a=null}if(!a?.ok)return a||{ok:!1,code:"host_memory_unavailable"};let c=null;try{c=await i()}catch{c=null}if(!c?.ok)return c||{ok:!1,code:"capacity_authority_unavailable"};let l=null;try{l=await r()}catch{l=null}if(!l?.ok||!l.lease){try{await o(e)}catch{}return l||{ok:!1,code:"scheduled_admission_unavailable"}}return{ok:!0,code:"admitted",lease:{terminalId:e,scheduled:l.lease}}}export async function releaseScheduledRunExecution(e,{releaseScheduled:t,releaseHost:n}={}){if(!e?.scheduled||"string"!=typeof e.terminalId||"function"!=typeof t||"function"!=typeof n)return{ok:!1,code:"invalid_execution_lease"};let i=null;try{i=await t(e.scheduled)}catch{i=null}try{await n(e.terminalId)}catch{}return i||{ok:!1,code:"scheduled_release_failed"}}const p=(e,t)=>"string"==typeof e&&e.trim().length>0&&e.length<=t&&!a.test(e)&&!c.test(e),m=e=>e instanceof Date?e:new Date(e),f=e=>!Number.isNaN(m(e).getTime()),h=(e,t)=>{let n=s.get(e);n||(n=new Intl.DateTimeFormat("en-CA",{timeZone:e,weekday:"short",hour:"2-digit",minute:"2-digit",hourCycle:"h23"}),s.set(e,n));const i=Object.fromEntries(n.formatToParts(t).filter(e=>"literal"!==e.type).map(e=>[e.type,e.value]));return{weekday:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"].indexOf(i.weekday),time:`${i.hour}:${i.minute}`}};export function scheduleValidationError(e={}){if(!e||"object"!=typeof e||!i.has(e.kind))return"invalid_kind";if(!p(e.title,120)||!p(e.prompt,12e3))return"unsafe_or_invalid_text";if(!r.has(e.runtime))return"invalid_runtime";if(!(null==e.provider||p(e.provider,80)&&u.test(e.provider)))return"invalid_provider";if(!(null==e.model||p(e.model,160)&&u.test(e.model)))return"invalid_model";if(!Number.isInteger(e.maxRuntimeMinutes)||e.maxRuntimeMinutes<1||e.maxRuntimeMinutes>30)return"invalid_max_runtime";try{new Intl.DateTimeFormat("en",{timeZone:e.timezone})}catch{return"invalid_timezone"}return"once"!==e.kind||f(e.at)?null==e.intervalMinutes||_.has(e.intervalMinutes)?"once"!==e.kind&&!/^\d{2}:\d{2}$/.test(e.time)||"once"!==e.kind&&(Number(e.time.slice(0,2))>23||Number(e.time.slice(3))>59)?"invalid_local_time":"weekly"===e.kind&&(!Number.isInteger(e.weekday)||e.weekday<0||e.weekday>6)?"invalid_weekday":null:"invalid_interval":"invalid_once_time"}export function normalizeSchedule(e={},t=new Date){const n=scheduleValidationError(e);if(n)return Object.freeze({ok:!1,code:n});const i={kind:e.kind,title:e.title.trim(),prompt:e.prompt.trim(),runtime:e.runtime,provider:e.provider||null,model:e.model||null,timezone:e.timezone,maxRuntimeMinutes:e.maxRuntimeMinutes,..."once"===e.kind?{at:m(e.at).toISOString()}:{time:e.time,..."weekly"===e.kind?{weekday:e.weekday}:{},...e.intervalMinutes?{interval_minutes:e.intervalMinutes}:{}}},r=nextScheduledAt(i,t);return r?Object.freeze({ok:!0,value:Object.freeze(i),nextRunAt:r.toISOString()}):Object.freeze({ok:!1,code:"schedule_exhausted"})}export function nextScheduledAt(e,t=new Date){if("once"===e?.kind){const n=m(e.at);return f(n)&&n.getTime()>m(t).getTime()?n:null}const n=Number(e?.interval_minutes);if(_.has(n))return new Date(m(t).getTime()+6e4*n);const i=6e4*Math.floor(m(t).getTime()/6e4)+6e4;for(let t=i,n=i+3456e7;t<n;t+=6e4){const n=h(e.timezone,new Date(t));if(n.time===e.time&&("daily"===e.kind||n.weekday===e.weekday))return new Date(t)}return null}export function classifyRunOutcome({result:e=null,evidenceRefs:t=[],pendingControls:n=[],runId:i=null,canceled:r=!1}={}){if("runtime_limit"===e?.subtype)return Object.freeze({outcome:"failed",code:"runtime_limit"});if(r||["aborted","canceled","cancelled","interrupted"].includes(e?.subtype))return Object.freeze({outcome:"canceled",code:"canceled"});const o=(Array.isArray(t)?t:[]).filter(e=>e&&d.has(e.type)&&"string"==typeof e.id&&u.test(e.id)).slice(0,16);if(o.length)return Object.freeze({outcome:"delivered",code:"evidence_delivered",evidence:o});const a=(Array.isArray(n)?n:[]).find(e=>"pending"===e?.status&&e?.id&&e?.request_context?.run_id&&(!i||e.request_context.run_id===i)&&Number.isSafeInteger(Number(e.source_event_from_seq)));return a?Object.freeze({outcome:"needs_decision",code:"pending_pair_control",controlItemId:a.id}):"success"===e?.subtype?Object.freeze({outcome:"failed",code:"missing_deliverable"}):Object.freeze({outcome:"failed",code:e?.subtype||"runtime_failed"})}export function sanitizeScheduledOutcomeIntent(e={}){const{runId:t,result:n=null,evidenceRefs:i=[],canceled:r=!1}=e&&"object"==typeof e?e:{};if("string"!=typeof t||!u.test(t))return null;const o="string"==typeof n?.subtype&&l.test(n.subtype)?n.subtype:"runtime_failed";return Object.freeze({runId:t,result:Object.freeze({subtype:o}),evidenceRefs:Object.freeze((a=i,(Array.isArray(a)?a:[]).filter(e=>e&&d.has(e.type)&&"string"==typeof e.id&&u.test(e.id)).slice(0,16).map(e=>Object.freeze({type:e.type,id:e.id})))),canceled:!0===r});var a}export function scheduledRunDeadlineRequired({runId:e,deadlineAt:t,outcomeRecorded:n=!1,outcomePending:i=null}={}){return Boolean(e&&Number.isFinite(t)&&!n&&!i)}export function scheduledOutcomeReconciliationComplete(e=[]){return Array.isArray(e)&&0===e.length}export function scheduledRunSpawnAdmission({spawnTimes:e=[],now:i=Date.now(),totalLive:r=0,disabled:o=!1}={},d=t){const a={...t,...d||{}},c=(Array.isArray(e)?e:[]).filter(e=>Number.isFinite(e)&&e>i-a.windowMs).slice(-(a.perWindowCap||1)),u=n({hop:0,spawnTimes:c,now:i,spawnedLive:0,totalLive:r,plan:"free",disabled:o},a);return Object.freeze({...u,spawnTimes:Object.freeze(u.ok?[...c,i].slice(-a.perWindowCap):c)})}export function preflightScheduledRun({schedule:e,occurrence:t,ownerId:n,bridgeId:i,bridgeFencing:r,providerAvailable:o,capsOk:d=!0,now:a=new Date}={}){return e?.enabled?t?.id&&t.schedule_revision===e.revision?!n||!i||!Number.isSafeInteger(r)||r<1||t.owner_id!==n||t.bridge_id!==i||t.bridge_fencing!==r?Object.freeze({ok:!1,code:"owner_bridge_mismatch"}):d?"function"==typeof o&&o(e)?!t.lease_expires_at||m(t.lease_expires_at).getTime()<=m(a).getTime()?Object.freeze({ok:!1,code:"lease_expired"}):Object.freeze({ok:!0,code:"admitted"}):Object.freeze({ok:!1,code:"provider_unavailable"}):Object.freeze({ok:!1,code:"runtime_cap_exceeded"}):Object.freeze({ok:!1,code:"stale_schedule_revision"}):Object.freeze({ok:!1,code:"schedule_disabled"})}const b=async({fetchImpl:e,supabaseUrl:t,headers:n,name:i,body:r})=>{const o=await e(`${String(t).replace(/\/$/,"")}/rest/v1/rpc/${i}`,{method:"POST",headers:n,body:JSON.stringify(r)});if(!o?.ok)throw new Error(`${i}_failed`);return o.json()};export async function pollDueScheduledRuns({enabled:t=!1,fetchImpl:n=globalThis.fetch,supabaseUrl:i,anonKey:r,token:o,roomCode:d,bridgeId:a,bridgeFencing:c,ownerId:l,providerAvailable:s,openTerminal:_,admitRun:p,releaseRun:f,makeTerminalId:h=e,capsOk:y=()=>!0,now:g=new Date}={}){if(!t)return Object.freeze({ok:!1,code:"feature_disabled",runs:[]});if(!("function"==typeof n&&i&&r&&o&&d&&a&&Number.isSafeInteger(c))||c<1||!l||"function"!=typeof _||"function"!=typeof p||"function"!=typeof f||"function"!=typeof h)return Object.freeze({ok:!1,code:"runner_unavailable",runs:[]});const k={apikey:r,Authorization:`Bearer ${o}`,"Content-Type":"application/json"},w=String(d).trim().toUpperCase();try{const e=await b({fetchImpl:n,supabaseUrl:i,headers:k,name:"expire_code_scheduled_runs",body:{p_room_code:w,p_bridge_id:a,p_bridge_fencing:c,p_limit:24}});if(!e?.ok)throw new Error("expire_code_scheduled_runs_failed");const t=await b({fetchImpl:n,supabaseUrl:i,headers:k,name:"list_due_code_schedules",body:{p_room_code:w,p_limit:12}}),r=[];for(const e of Array.isArray(t)?t:[]){if(String(e?.session_code||"").trim().toUpperCase()!==w){r.push({scheduleId:e?.id,code:"room_scope_mismatch"});continue}if(!y(e)){r.push({scheduleId:e.id,code:"runtime_cap_exceeded"});continue}if("function"!=typeof s||!s(e)){r.push({scheduleId:e.id,code:"provider_unavailable"});continue}const t=h();if("string"!=typeof t||!u.test(t)){r.push({scheduleId:e.id,code:"terminal_id_unavailable"});continue}const o={...e.schedule_spec||{},kind:e.schedule_kind||e.kind,timezone:e.timezone},d="once"===o.kind?new Date("9999-12-31T23:59:00.000Z"):nextScheduledAt(o,new Date(e.next_run_at));if(!d){r.push({scheduleId:e.id,code:"next_run_invalid"});continue}const v=`${e.id}:${m(e.next_run_at).toISOString()}`,I=Math.min(1860,Math.max(60,60*e.max_runtime_minutes+60)),z=m(g).getTime()+1e3*I;let x=null;try{x=await p({schedule:e,runId:v,terminalId:t,deadlineAt:z})}catch{x=null}if(!x?.ok){r.push({scheduleId:e.id,code:x?.code||"spawn_not_admitted"});continue}let O=!1;try{const o=await b({fetchImpl:n,supabaseUrl:i,headers:k,name:"claim_due_code_schedule",body:{p_schedule_id:e.id,p_expected_revision:e.revision,p_bridge_id:a,p_bridge_fencing:c,p_occurrence_key:v,p_lease_seconds:I}});if(!o?.ok||!o?.run){r.push({scheduleId:e.id,code:o?.code||"claim_failed"});continue}const u=preflightScheduledRun({schedule:e,occurrence:o.run,ownerId:l,bridgeId:a,bridgeFencing:c,providerAvailable:s,capsOk:!0,now:g});if(!u.ok){r.push({scheduleId:e.id,runId:o.run.id,code:u.code});continue}const p=await b({fetchImpl:n,supabaseUrl:i,headers:k,name:"open_code_scheduled_run",body:{p_run_id:o.run.id,p_bridge_id:a,p_bridge_fencing:c,p_terminal_id:t,p_next_run_at:d.toISOString()}});if(!p?.ok){r.push({scheduleId:e.id,runId:o.run.id,code:p?.code||"open_not_persisted"});continue}const m=p.run||o.run;let f=null;try{f=await _({schedule:e,run:m,terminalId:t,admission:x.lease})}catch{f=null}if("string"==typeof f?f:!0===f?t:!0===f?.ok&&"string"==typeof f.terminalId&&f.terminalId){O=!0,r.push({scheduleId:e.id,runId:o.run.id,code:"opened"});continue}const h=!1===f?.ok&&"string"==typeof f.code&&/^terminal_[a-z0-9_]{1,100}$/.test(f.code)?f.code:"terminal_open_failed",y=await b({fetchImpl:n,supabaseUrl:i,headers:k,name:"finish_code_scheduled_run",body:{p_run_id:o.run.id,p_bridge_id:a,p_bridge_fencing:c,p_outcome:"failed",p_outcome_code:h,p_evidence_refs:[],p_decision_item_id:null}});r.push({scheduleId:e.id,runId:o.run.id,code:y?.ok?h:y?.code||"open_failed_unrecorded"})}finally{if(!O)try{await f(x.lease)}catch{}}}return Object.freeze({ok:!0,code:"polled",runs:Object.freeze(r)})}catch{return Object.freeze({ok:!1,code:"runner_read_failed",runs:[]})}}export async function finishScheduledRun({fetchImpl:e=globalThis.fetch,supabaseUrl:t,anonKey:n,token:i,roomCode:r,runId:o,bridgeId:d,bridgeFencing:a,result:c,evidenceRefs:u,canceled:l=!1}={}){if(!(t&&n&&i&&r&&o&&d&&Number.isSafeInteger(a))||a<1)return Object.freeze({ok:!1,code:"outcome_unavailable"});const s={apikey:n,Authorization:`Bearer ${i}`,"Content-Type":"application/json"};try{const n=classifyRunOutcome({result:c,evidenceRefs:u,pendingControls:await b({fetchImpl:e,supabaseUrl:t,headers:s,name:"list_code_pair_controls",body:{p_session_code:String(r).toUpperCase(),p_status:"pending",p_limit:100}}),runId:o,canceled:l}),i=await b({fetchImpl:e,supabaseUrl:t,headers:s,name:"finish_code_scheduled_run",body:{p_run_id:o,p_outcome:n.outcome,p_outcome_code:n.code,p_bridge_id:d,p_bridge_fencing:a,p_evidence_refs:n.evidence||[],p_decision_item_id:n.controlItemId||null}});return Object.freeze({ok:Boolean(i?.ok),code:i?.code||"outcome_write_failed",outcome:n})}catch{return Object.freeze({ok:!1,code:"outcome_write_failed"})}}export async function finishScheduledRunWithRetry(e={},{attempts:t=3,delays:n=[100,400],sleep:i=e=>new Promise(t=>setTimeout(t,e))}={}){const r=Math.max(1,Math.min(5,Number.isInteger(t)?t:3));let o=Object.freeze({ok:!1,code:"outcome_write_failed"});for(let t=0;t<r;t++){if(o=await finishScheduledRun(e),o.ok)return o;t+1<r&&await i(Math.max(0,Math.min(5e3,Number(n[t]??n.at(-1)??0)||0)))}return o}export{o as OUTCOMES};
|