@x-otto/schedule 0.0.1-alpha.2 → 0.0.1-alpha.4

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
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/registry.ts","../src/cron-parser.ts","../src/schedule-store.ts","../src/fire-ownership.ts","../src/schedule-lease-migrations.ts","../src/remote-schedule-store.ts","../src/remote-fire-ownership.ts","../src/scheduler.ts","../src/schedule-capability.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":["ContextFragment","ContextFragmentId","boundFragment","contextFragmentBytes","AnthropicImageMime","CommonImageMime","NormalizedImage","normalizeImageData","toAnthropicImageMime","A2uiComponent","A2uiContent","Api","AssistantMessage","CONVERSATION_SUMMARY_PREFIX","ContentPart","ImageContent","KnownApi","KnownProvider","Message","Provider","StopReason","SystemNotificationMessage","TextContent","ThinkingContent","ToolCall","ToolResultMessage","Usage","UserMessage","ZodType","getToolCallsByAssistantMessage","hasToolCalls","DismissedSigil","PluginInputRegistry","SigilEntry","SigilKind","SigilPrefix","SigilProvider","SigilResolveContext","SigilResolver","SigilSource","SigilTrigger","SigilTriggerDecision","TextChangeSource","adjustDismissedSigil","applySigilCompletion","applySigilReplacement","evaluateSigilTrigger","extractSigilPrefix","isSigilDismissed","sigilOf","ProviderUsageSnapshot","status","limitType","resetsAt","usedPercent","overageStatus","overageResetsAt","overageDisabledReason","standardLimits","remainingRequests","remainingTokens","limitRequests","limitTokens","resetRequestsMs","resetTokensMs","StreamEvent","Error","type","partial","index","delta","content","toolCall","reason","message","providerUsage","error","ThinkingLevel","ModelStrength","Cost","input","output","cacheRead","cacheWrite","Model","T","id","name","api","provider","baseUrl","reasoning","cost","contextWindow","maxOutputTokens","thinkingLevels","thinkingMode","strengths","imageConstraints","maxImagesPerRequest","maxDimensionPxIfOverLimit","supportsTools","responseBodyPolicy","store","sendMaxOutputTokens","ModelSpec","CapabilityFact","state","value","modelImageCapability","Pick","model","modelSupportsImages","ModelCapabilityFacts","vision","collectModelCapabilityFacts","SystemPromptLane","SystemPromptSectionSpec","priority","lane","budgetBytes","SYSTEM_PROMPT_SECTIONS","toolGuidance","skillLoopGuidance","environment","agentKnowledge","skillCatalog","lessonRelevantHints","internalize","memoryDelta","todoReminder","docSyncReminder","SYSTEM_PROMPT_SECTION_ORDER","applySectionBudget","ToolErrorKind","ToolResult","Record","isError","errorKind","details","pluginSource","extractToolResultText","result","ToolCallContext","Params","AbortSignal","params","signal","sessionId","agentName","depth","parentTaskId","onUpdate","update","ToolCallEvent","arguments","ToolDescriptionContext","projectRoot","AgentTool","Promise","description","ctx","parameters","execute","ToolExecutionPolicy","exposure","readonly","interruptBehavior","resultBudgetChars","isConcurrencySafe","pathParams","resolvePath","rawPath","async","lifecycleAsync","lifecycleAsyncNote","regenerableOutput","AgentToolDefinition","Partial","AskUserQuestion","text","options","GrillOption","label","rationale","recommended","preview","GrillQuestion","header","question","background","recommendation","allowFreeform","multiSelect","evidence","askedBy","GrillAnswer","answer","selectedOptionLabels","acceptedRecommendation","resolvedBy","freeformText","GrillRequest","Omit","AgentSessionEventType","AgentSessionEvent","PromptStopReason","tokenUsage","thinkingLevel","stopReason","errorMessage","round","maxRounds","incompleteCount","event","role","from","to","turnIndex","toolTurnCount","maxToolTurns","promptOutputTokens","promptOutputTokenBudget","maxTurns","extended","steered","progressDenied","dimension","used","budget","windowTurns","maxRepeat","outcome","retryCount","totalCostUSD","budgetUSD","resultText","resultTokensEstimate","messageCount","retainedCount","summary","messagesBefore","messagesAfter","degradedCount","trigger","tokensSaved","prunedCount","clearedCount","removedCount","capValue","lossy","attemptedCount","describedCount","failedCount","lostTurns","lastPersistedAt","lastTraceAt","toolName","risk","semanticVerdict","approved","requestId","planContent","action","componentId","payload","AgentSessionSubscriber","AgentSessionEventMap","E","EVENT_DOMAIN","EventDomain","getEventDomain","eventType","EngineCommand","kind","approvalId","modelId","replacement","todos","files","subagents","count","FileCommand","argumentHint","allowedTools","body","source","scope","pluginId","filePath","TodoStatus","TodoItem","title","ChildProcessConfig","command","args","owner","category","lifecycle","cwd","ProcessTracker","registerChild","config","pid","child","PluginPerfMetricResult"],"sources":["../../interchange/dist/index.d.ts","../src/types.ts","../src/registry.ts","../src/schedule-store.ts","../src/fire-ownership.ts","../src/schedule-config.ts","../src/fire-target.ts","../src/trigger.ts","../src/scheduler.ts","../src/cron-parser.ts","../src/remote-schedule-store.ts","../src/schedule-lease-migrations.ts","../src/remote-fire-ownership.ts","../src/fire-logger.ts","../src/fire-targets/job-fire-target.ts","../src/fire-targets/session-fire-target.ts","../src/fire-targets/subscriber-fire-target.ts","../src/triggers/in-process-event-trigger.ts","../src/schedule-capability.ts"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
- import{RemotePersistence as e,createPersistence as t}from"@x-otto/persistence";import{OTTO_HOME as n,currentHostname as r,decodeLeaseToken as i,encodeLeaseToken as a,isProcessAlive as o,isShadowModeEnabled as s}from"@x-otto/env";import{resolve as c}from"node:path";import{closeSync as l,mkdirSync as u,openSync as d,readFileSync as f,readdirSync as p,renameSync as m,rmSync as h,statSync as g,unlinkSync as _,utimesSync as v,writeFileSync as y,writeSync as b}from"node:fs";import{randomUUID as x}from"node:crypto";var S=class{tasks;constructor(){this.tasks=new Map}add(e){if(this.tasks.has(e.id))throw Error(`ScheduleRegistry: duplicate task id "${e.id}"`);this.tasks.set(e.id,e)}remove(e){return this.tasks.delete(e)}update(e,t){let n=this.tasks.get(e);return n?(t.enabled!==void 0&&(n.enabled=t.enabled),t.lastFiredAt!==void 0&&(n.lastFiredAt=t.lastFiredAt),t.nextFireAt!==void 0&&(n.nextFireAt=t.nextFireAt),t.maxDurationMs!==void 0&&(n.maxDurationMs=t.maxDurationMs),t.maxRetries!==void 0&&(n.maxRetries=t.maxRetries),t.lastFireFailed!==void 0&&(n.lastFireFailed=t.lastFireFailed),t.lastFireError!==void 0&&(n.lastFireError=t.lastFireError),t.lastFireCancelled!==void 0&&(n.lastFireCancelled=t.lastFireCancelled),!0):!1}get(e){return this.tasks.get(e)}list(){return[...this.tasks.values()].sort((e,t)=>e.nextFireAt-t.nextFireAt)}findDue(e){let t=[];for(let n of this.tasks.values())n.enabled&&n.nextFireAt<=e&&t.push(n);return t.sort((e,t)=>e.nextFireAt-t.nextFireAt),t}count(){return this.tasks.size}has(e){return this.tasks.has(e)}};function C(e,t){let{validMinute:n,validHour:r,validDom:i,validMonth:a,validDow:o,domConstrained:s,dowConstrained:c}=w(e),l=t?new Date(t.getTime()):new Date;l.setSeconds(0,0);let u=new Date(l.getTime()+366*24*60*60*1e3),d=new Date(l.getTime());for(;d.getTime()<=u.getTime();){let e=d.getMinutes(),t=A(n,e);if(t===null){d.setMinutes(j(n)),d.setHours(d.getHours()+1),d.setSeconds(0,0);continue}if(t!==e){d.setMinutes(t),d.setSeconds(0,0);continue}let l=d.getHours(),u=A(r,l);if(u===null){d.setHours(j(r)),d.setMinutes(j(n)),d.setDate(d.getDate()+1),d.setSeconds(0,0);continue}if(u!==l){d.setHours(u),d.setMinutes(j(n)),d.setSeconds(0,0);continue}let f=d.getDate(),p=d.getDay(),m=i.has(f),h=o.has(p),g;if(g=s&&c?m||h:s?m:c?h:!0,!g){d.setDate(d.getDate()+1),d.setHours(j(r)),d.setMinutes(j(n)),d.setSeconds(0,0);continue}let _=d.getMonth()+1,v=A(a,_);if(v===null){d.setMonth(j(a)-1),d.setFullYear(d.getFullYear()+1),d.setDate(1),d.setHours(j(r)),d.setMinutes(j(n)),d.setSeconds(0,0);continue}if(v!==_){d.setMonth(v-1),d.setDate(1),d.setHours(j(r)),d.setMinutes(j(n)),d.setSeconds(0,0);continue}return d}throw Error(`No matching time found for cron "${e}" within 366 days of ${l.toISOString()}`)}function w(e){if(!e||!e.trim())throw Error(`Invalid cron expression: empty string`);let t=e.trim().split(/\s+/);if(t.length!==5)throw Error(`Invalid cron expression: expected 5 fields, got ${t.length} (${e})`);let[n,r,i,a,o]=t,s=T(n,0,59),c=T(r,0,23),l=T(i,1,31),u=T(a,1,12),d=T(o,0,7);d.has(7)&&d.add(0);let f=e=>e===`*`||e===`*/1`;return{validMinute:s,validHour:c,validDom:l,validMonth:u,validDow:d,domConstrained:!f(i),dowConstrained:!f(o)}}function T(e,t,n){E(e);let r=new Set,i=e.split(`,`);for(let a of i){let{range:i,step:o}=D(a);if(O(o,a),i===`*`)for(let e=t;e<=n;e+=o)r.add(e);else if(i.includes(`-`)){let[s,c]=i.split(`-`),l=k(s,a),u=k(c,a);if(l<t||u>n||l>u)throw Error(`Invalid cron field "${e}": range [${l},${u}] out of bounds [${t},${n}]`);for(let e=l;e<=u;e+=o)r.add(e)}else{let s=k(i,a);if(s<t||s>n)throw Error(`Invalid cron field "${e}": value ${s} out of range [${t},${n}]`);if(o>1)for(let e=s;e<=n;e+=o)r.add(e);else r.add(s)}}return r}function E(e){if(e.replace(/[\d*\/\-,]/g,``).length>0)throw Error(`Invalid cron field "${e}": unsupported syntax`)}function D(e){let t=e.indexOf(`/`);return t===-1?{range:e,step:1}:{range:e.substring(0,t),step:parseInt(e.substring(t+1),10)}}function O(e,t){if(isNaN(e)||e<1)throw Error(`Invalid cron field: invalid step in "${t}"`)}function k(e,t){let n=parseInt(e,10);if(isNaN(n))throw Error(`Invalid cron field: expected number, got "${e}" in "${t}"`);return n}function A(e,t){let n=null;for(let r of e)r>=t&&(n===null||r<n)&&(n=r);return n}function j(e){let t=1/0;for(let n of e)n<t&&(t=n);return t}function M(e){return c(n,`schedules`,e)}function N(e,n={}){let r=n.persistence??(s()?t({type:`memory`}):t({type:`file`,baseDir:M(e)})),i=n.logger;return{async saveTask(e){let t={version:1,id:e.id,data:e,metadata:{createdAt:e.createdAt,updatedAt:Date.now(),tags:[`schedule`]}};await r.save(t)},async loadAllTasks(){let e;try{e=await r.list()}catch(e){return i?.error(`[schedules] Failed to list schedule snapshots:`,e),[]}let t=[];for(let n of e)try{let e=await r.load(n);e&&t.push(e.data)}catch(e){i?.error(`[schedules] Failed to load schedule "${n}":`,e)}return t.sort((e,t)=>e.nextFireAt-t.nextFireAt),t},async deleteTask(e){try{return await r.delete(e)}catch(t){return i?.error(`[schedules] Failed to delete schedule "${e}":`,t),!1}}}}function P(e){return c(n,`schedule-owner-${e}.lock`)}function F(e){let t=x(),c=P(e),p=r(),y=!1,S=()=>{try{u(n,{recursive:!0});let e=d(c,`wx`);try{b(e,a(t,process.pid,p))}finally{l(e)}return y=!0,!0}catch(e){if(e.code!==`EEXIST`)throw e;return!1}},C=()=>{try{return i(f(c,`utf-8`).trim())}catch{return null}},w=()=>C()?.token??null,T=e=>e.pid===void 0||e.host===void 0||e.host!==p?!1:!o(e.pid),E=e=>e.pid===void 0||e.host===void 0||e.host!==p?!1:o(e.pid),D=()=>{if(y)return!0;if(s())return!1;if(S())return!0;let e=C(),t;try{t=g(c).mtimeMs}catch{return S()}if(e!==null&&E(e)||!(e!==null&&T(e))&&Date.now()-t<=3e5)return!1;let n=`${c}.stale-${x()}`;try{m(c,n),h(n,{force:!0})}catch{return!1}return S()};return{async tryAcquire(){return D()},async renew(){if(y){if(w()!==t){y=!1;return}try{let e=new Date;v(c,e,e)}catch{y=!1}}},async release(){if(y){if(w()===t)try{_(c)}catch{}y=!1}},isOwner(){return y&&w()===t}}}const I=[{version:1,up:e=>{e.exec(`
1
+ import{closeSync as e,mkdirSync as t,openSync as n,readFileSync as r,readdirSync as i,renameSync as a,rmSync as o,statSync as s,unlinkSync as c,utimesSync as l,writeFileSync as u,writeSync as d}from"node:fs";import{resolve as f}from"node:path";import{OTTO_HOME as p,currentHostname as m,decodeLeaseToken as h,encodeLeaseToken as g,isProcessAlive as _,isShadowModeEnabled as v}from"@x-otto/env";import{RemotePersistence as y,createPersistence as b}from"@x-otto/persistence";import{randomUUID as x}from"node:crypto";function S(e,t){let{validMinute:n,validHour:r,validDom:i,validMonth:a,validDow:o,domConstrained:s,dowConstrained:c}=C(e),l=t?new Date(t.getTime()):new Date;l.setSeconds(0,0);let u=new Date(l.getTime()+366*24*60*60*1e3),d=new Date(l.getTime());for(;d.getTime()<=u.getTime();){let e=d.getMinutes(),t=k(n,e);if(t===null){d.setMinutes(A(n)),d.setHours(d.getHours()+1),d.setSeconds(0,0);continue}if(t!==e){d.setMinutes(t),d.setSeconds(0,0);continue}let l=d.getHours(),u=k(r,l);if(u===null){d.setHours(A(r)),d.setMinutes(A(n)),d.setDate(d.getDate()+1),d.setSeconds(0,0);continue}if(u!==l){d.setHours(u),d.setMinutes(A(n)),d.setSeconds(0,0);continue}let f=d.getDate(),p=d.getDay(),m=i.has(f),h=o.has(p),g;if(g=s&&c?m||h:s?m:c?h:!0,!g){d.setDate(d.getDate()+1),d.setHours(A(r)),d.setMinutes(A(n)),d.setSeconds(0,0);continue}let _=d.getMonth()+1,v=k(a,_);if(v===null){d.setMonth(A(a)-1),d.setFullYear(d.getFullYear()+1),d.setDate(1),d.setHours(A(r)),d.setMinutes(A(n)),d.setSeconds(0,0);continue}if(v!==_){d.setMonth(v-1),d.setDate(1),d.setHours(A(r)),d.setMinutes(A(n)),d.setSeconds(0,0);continue}return d}throw Error(`No matching time found for cron "${e}" within 366 days of ${l.toISOString()}`)}function C(e){if(!e||!e.trim())throw Error(`Invalid cron expression: empty string`);let t=e.trim().split(/\s+/);if(t.length!==5)throw Error(`Invalid cron expression: expected 5 fields, got ${t.length} (${e})`);let[n,r,i,a,o]=t,s=w(n,0,59),c=w(r,0,23),l=w(i,1,31),u=w(a,1,12),d=w(o,0,7);d.has(7)&&d.add(0);let f=e=>e===`*`||e===`*/1`;return{validMinute:s,validHour:c,validDom:l,validMonth:u,validDow:d,domConstrained:!f(i),dowConstrained:!f(o)}}function w(e,t,n){T(e);let r=new Set,i=e.split(`,`);for(let a of i){let{range:i,step:o}=E(a);if(D(o,a),i===`*`)for(let e=t;e<=n;e+=o)r.add(e);else if(i.includes(`-`)){let[s,c]=i.split(`-`),l=O(s,a),u=O(c,a);if(l<t||u>n||l>u)throw Error(`Invalid cron field "${e}": range [${l},${u}] out of bounds [${t},${n}]`);for(let e=l;e<=u;e+=o)r.add(e)}else{let s=O(i,a);if(s<t||s>n)throw Error(`Invalid cron field "${e}": value ${s} out of range [${t},${n}]`);if(o>1)for(let e=s;e<=n;e+=o)r.add(e);else r.add(s)}}return r}function T(e){if(e.replace(/[\d*/\-,]/g,``).length>0)throw Error(`Invalid cron field "${e}": unsupported syntax`)}function E(e){let t=e.indexOf(`/`);return t===-1?{range:e,step:1}:{range:e.substring(0,t),step:parseInt(e.substring(t+1),10)}}function D(e,t){if(isNaN(e)||e<1)throw Error(`Invalid cron field: invalid step in "${t}"`)}function O(e,t){let n=parseInt(e,10);if(isNaN(n))throw Error(`Invalid cron field: expected number, got "${e}" in "${t}"`);return n}function k(e,t){let n=null;for(let r of e)r>=t&&(n===null||r<n)&&(n=r);return n}function A(e){let t=1/0;for(let n of e)n<t&&(t=n);return t}var j=class{tasks;constructor(){this.tasks=new Map}add(e){if(this.tasks.has(e.id))throw Error(`ScheduleRegistry: duplicate task id "${e.id}"`);this.tasks.set(e.id,e)}remove(e){return this.tasks.delete(e)}update(e,t){let n=this.tasks.get(e);return n?(t.enabled!==void 0&&(n.enabled=t.enabled),t.lastFiredAt!==void 0&&(n.lastFiredAt=t.lastFiredAt),t.nextFireAt!==void 0&&(n.nextFireAt=t.nextFireAt),t.maxDurationMs!==void 0&&(n.maxDurationMs=t.maxDurationMs),t.maxRetries!==void 0&&(n.maxRetries=t.maxRetries),t.lastFireFailed!==void 0&&(n.lastFireFailed=t.lastFireFailed),t.lastFireError!==void 0&&(n.lastFireError=t.lastFireError),t.lastFireCancelled!==void 0&&(n.lastFireCancelled=t.lastFireCancelled),!0):!1}get(e){return this.tasks.get(e)}list(){return[...this.tasks.values()].sort((e,t)=>e.nextFireAt-t.nextFireAt)}findDue(e){let t=[];for(let n of this.tasks.values())n.eventTrigger||n.enabled&&n.nextFireAt<=e&&t.push(n);return t.sort((e,t)=>e.nextFireAt-t.nextFireAt),t}count(){return this.tasks.size}has(e){return this.tasks.has(e)}},M=class{handlers=[];register(e){this.handlers.push(e)}find(e){return this.handlers.find(t=>t.canHandle(e))}},N=class{registry=new M;firing=new Set;deps;constructor(e){this.deps=e;for(let t of e.fireTargets)this.registry.register(t)}has(e){return this.firing.has(e)}addFiring(e){this.firing.add(e)}async fire(e,t){if(!e.enabled||!this.deps.isFireOwner()){this.firing.delete(e.id);return}let n={scheduledFor:t,now:this.deps.now,logger:this.deps.logger},r;try{if(r=this.registry.find(e),!r){this.deps.fireLogger.write(e.id,`no fire target handler for task (subscriber=${!!e.subscriber}, target=${e.target??`default`})`),this.handleOneShotCompletion(e,{outcome:`failed`,error:`no fire target handler (headless mode)`});return}let t=await r.fire(e,n);t.outcome===`success`&&!t.cancelled&&(this.deps.registry.update(e.id,{lastFiredAt:this.deps.now(),lastFireFailed:!1,lastFireError:void 0}),e.target!==`session`&&this.deps.persistence.saveOne(e)),this.handleOneShotCompletion(e,t)}catch(t){this.deps.logger?.error(`[schedules] fire failed for task ${e.id}:`,t),this.deps.fireLogger.write(e.id,`error: ${t instanceof Error?t.message:String(t)}`),this.handleOneShotCompletion(e,{outcome:`failed`,error:t instanceof Error?t.message:String(t)})}finally{r?.cleanup?.(e.id),this.firing.delete(e.id)}}handleOneShotCompletion(e,t){e.recurring||(t.outcome===`success`?this.deps.onTerminate(e.id,`one-shot-complete`):t.cancelled?(this.deps.registry.update(e.id,{lastFireCancelled:!0,lastFireError:void 0}),this.deps.persistence.saveOne(e)):(this.deps.registry.update(e.id,{lastFireFailed:!0,lastFireError:t.error}),this.deps.persistence.saveOne(e)))}},P=class{constructor(e){this.config=e}write(e,n){if(v())return;let r=f(p,`schedule-logs`),i=f(r,`${e}-${Date.now()}.log`);try{t(r,{recursive:!0}),u(i,`${new Date().toISOString()} ${n}\n`,`utf-8`),this.prune(r,e)}catch{}}prune(e,t){try{let n=`${t}-`,r=i(e).filter(e=>e.startsWith(n)&&e.endsWith(`.log`)).sort(),a=r.length-this.config.maxFireLogsPerTask;if(a<=0)return;for(let t of r.slice(0,a))try{c(f(e,t))}catch{}}catch{}}read(e,t=20){let n=f(p,`schedule-logs`),a=`${e}-`;try{let e=i(n).filter(e=>e.startsWith(a)&&e.endsWith(`.log`)).sort().reverse(),o=[];for(let i=0;i<e.length&&o.length<t;i++)try{let t=r(f(n,e[i]),`utf-8`).trim(),a=t.indexOf(` `),s=a>0?t.slice(0,a):t,c=a>0?t.slice(a+1):``;o.push({timestamp:s,status:c})}catch{}return o}catch{return[]}}};const F={maxTasks:50,recurringEvictionMs:10080*60*1e3,recurringJitterWindowMs:1800*1e3,oneShotJitterWindowMs:90*1e3,defaultMaxDurationMs:3e5,defaultMaxRetries:0,tickIntervalMs:1e3,needsInputMaxExtensionFactor:3,maxFireLogsPerTask:20,reloadIntervalTicks:30,recoveryRetryIntervalMs:3e4};function I(e,t,n,r){let i=0;for(let e=0;e<t.length;e++)i=(i<<5)-i+t.charCodeAt(e),i|=0;let a=r?e.recurringJitterWindowMs:e.oneShotJitterWindowMs,o=Math.abs(i)%a;return n.getTime()+o}var L=class{deps;ticker=null;tickInProgress=!1;tickCount=0;constructor(e){this.deps=e}start(){this.ticker||(this.ticker=setInterval(()=>{this.tick()},this.deps.config.tickIntervalMs),this.ticker.unref())}stop(){this.ticker&&=(clearInterval(this.ticker),null)}async tickOnce(){await this.tick()}async tick(){if(!this.tickInProgress){this.tickInProgress=!0;try{if(await this.deps.ownership.renew(),!this.deps.ownership.isOwner()){this.stop(),this.deps.onOwnershipLost();return}this.tickCount++,this.tickCount%this.deps.config.reloadIntervalTicks===0&&await this.reloadFromStore();let e=this.deps.now();for(let t of this.deps.registry.list())t.eventTrigger||t.recurring&&e-t.nextFireAt>this.deps.config.recurringEvictionMs&&this.deps.onTerminate(t.id,`stale-evicted`);let t=this.deps.registry.findDue(e);for(let n of t){if(this.deps.fireExecutor.has(n.id)||!n.recurring&&(n.lastFireFailed||n.lastFireCancelled))continue;let t=n.nextFireAt,r=S(n.cronExpression,new Date(e+6e4)),i=I(this.deps.config,n.id,r,n.recurring);this.deps.registry.update(n.id,{nextFireAt:i}),this.deps.persistence.saveOne(n),this.deps.fireExecutor.addFiring(n.id),this.deps.fireExecutor.fire(n,t)}}finally{this.tickInProgress=!1}}}async reloadFromStore(){let e;try{e=await this.deps.store.loadAllTasks()}catch(e){this.deps.logger?.error(`[schedules] Failed to reload schedules from store:`,e);return}let t=new Set(e.map(e=>e.id));for(let t of e){if(this.deps.fireExecutor.has(t.id))continue;if(!t.recurring&&t.lastFiredAt!=null&&!this.deps.registry.get(t.id)){this.deps.persistence.deleteOne(t.id).catch(e=>{this.deps.logger?.error(`[schedules] Failed to delete zombie one-shot ${t.id}:`,e)});continue}let e=this.deps.registry.get(t.id);if(e)e.enabled=t.enabled,e.name=t.name,e.prompt=t.prompt,e.cronExpression=t.cronExpression,e.maxDurationMs=t.maxDurationMs,e.maxRetries=t.maxRetries;else try{this.deps.registry.add(t)}catch{}}for(let e of this.deps.registry.list())e.target!==`session`&&!t.has(e.id)&&!this.deps.fireExecutor.has(e.id)&&this.deps.onEvictFromMemory(e.id)}},R=class{constructor(e){this.deps=e}saveOne(e){e.target!==`session`&&this.deps.store.saveTask(e).catch(t=>{this.deps.logger?.error(`[schedules] Failed to save schedule ${e.id}:`,t)})}async deleteOne(e){if(this.deps.registry.get(e)?.target===`session`)return!0;try{return await this.deps.store.deleteTask(e)}catch(t){return this.deps.logger?.error(`[schedules] Failed to delete schedule ${e}:`,t),!1}}async flushAll(e){try{for(let t of e)t.target!==`session`&&await this.deps.store.saveTask(t)}catch(e){this.deps.logger?.error(`[schedules] Failed to flush schedules:`,e)}}},z=class{deps;registry;persistence;fireExecutor;fireLogger;tickLoop;config;recoveryTimer=null;ensureOwnershipTimer=null;running=!1;triggers;armedTriggers=new Map;constructor(e){this.deps=e,this.registry=e.registry,this.config={...F,...e.config},this.fireLogger=new P(this.config),this.persistence=new R({registry:e.registry,store:e.store,logger:e.logger}),this.fireExecutor=new N({registry:e.registry,persistence:this.persistence,fireLogger:this.fireLogger,fireTargets:e.fireTargets,now:e.now??Date.now,logger:e.logger,onTerminate:(e,t)=>{this.terminate(e,t)},isFireOwner:()=>this.deps.ownership.isOwner()}),this.tickLoop=new L({registry:e.registry,store:e.store,persistence:this.persistence,ownership:e.ownership,fireExecutor:this.fireExecutor,config:this.config,now:e.now??Date.now,logger:e.logger,onOwnershipLost:()=>this.startRecovery(),onTerminate:(e,t)=>{this.terminate(e,t)},onEvictFromMemory:e=>{this.evictFromMemory(e)}}),this.triggers=e.triggers??[]}isFireOwner(){return this.deps.ownership.isOwner()}fireOwnerFailureReason(){return this.deps.ownership.lastFailureReason?.()}async start(){if(!this.running){if(!await this.deps.ownership.tryAcquire()){try{let e=await this.deps.store.loadAllTasks();for(let t of e)try{this.registry.add(t)}catch{}}catch(e){this.deps.logger?.error(`[schedules] Failed to load schedules (read-only mode):`,e)}this.startEnsureOwnership();return}try{let e=this.deps.now?.()??Date.now(),t=await this.deps.store.loadAllTasks();for(let n of t){if(n.recurring&&n.nextFireAt<e)try{let t=S(n.cronExpression,new Date(e+6e4));n.nextFireAt=I(this.config,n.id,t,!0)}catch{}try{this.registry.add(n)}catch{}}}catch(e){this.deps.logger?.error(`[schedules] Failed to load schedules:`,e)}for(let e of this.registry.list())this.armIfEventDriven(e);this.running=!0,this.tickLoop.start()}}terminate(e,t){if(this.disarmIfArmed(e),!this.registry.has(e))return!1;this.persistence.deleteOne(e);let n=this.registry.remove(e);return this.deps.logger?.debug?.(`[schedules] terminated ${e} (${t})`),n}evictFromMemory(e){return this.disarmIfArmed(e),this.registry.remove(e)}async stop(){this.stopEnsureOwnership(),!(!this.running&&!this.deps.ownership.isOwner())&&(this.stopRecovery(),this.tickLoop.stop(),this.disarmAll(),this.running=!1,await this.deps.ownership.release(),await this.persistence.flushAll(this.registry.list()))}startRecovery(){this.recoveryTimer||(this.deps.logger?.error(`[schedules] Lost fire ownership — entering recovery mode`),this.recoveryTimer=setInterval(()=>{this.recoveryAttempt()},this.config.recoveryRetryIntervalMs),this.recoveryTimer.unref())}async recoveryAttempt(){try{if(await this.deps.ownership.tryAcquire()&&this.deps.ownership.isOwner()){this.stopRecovery(),this.running=!0;for(let e of this.registry.list())this.armIfEventDriven(e);this.tickLoop.start(),this.deps.logger?.error(`[schedules] Re-acquired fire ownership — recovery complete`)}}catch{}}stopRecovery(){this.recoveryTimer&&=(clearInterval(this.recoveryTimer),null)}startEnsureOwnership(){this.ensureOwnershipTimer||(this.ensureOwnershipTimer=setInterval(()=>{this.ensureOwnershipAttempt()},this.config.recoveryRetryIntervalMs),this.ensureOwnershipTimer.unref())}async ensureOwnershipAttempt(){try{if(await this.deps.ownership.tryAcquire()&&this.deps.ownership.isOwner()){this.stopEnsureOwnership();try{let e=await this.deps.store.loadAllTasks();for(let t of e)try{this.registry.add(t)}catch{}}catch(e){this.deps.logger?.error(`[schedules] Failed to reload schedules after acquiring ownership:`,e)}for(let e of this.registry.list())this.armIfEventDriven(e);this.running=!0,this.tickLoop.start(),this.deps.logger?.error(`[schedules] Acquired fire ownership (was waiting for release)`)}}catch{}}stopEnsureOwnership(){this.ensureOwnershipTimer&&=(clearInterval(this.ensureOwnershipTimer),null)}add(e){if(this.registry.count()>=this.config.maxTasks)throw Error(`Schedule limit reached (max ${this.config.maxTasks}). Remove some tasks before adding more.`);let t=e.target===`session`&&!e.subscriber;if(t&&!this.deps.ownership.isOwner())throw Error(this.describeSessionOwnershipRefusal());if(e.eventTrigger&&!e.subscriber&&e.target!==`session`)throw Error(`Event-triggered tasks must deliver to a session (target:"session") or a plugin subscriber, not an isolated job — job delivery from an event trigger risks a self-firing loop (RFC-423 D4).`);let n=crypto.randomUUID().slice(0,8),r=this.deps.now?.()??Date.now(),i=S(e.cronExpression,new Date(r+6e4)),a=I(this.config,n,i,e.recurring),o={id:n,name:e.name,prompt:e.prompt,cronExpression:e.cronExpression,enabled:!0,recurring:e.recurring,origin:e.origin,createdAt:r,nextFireAt:a,maxDurationMs:e.maxDurationMs??this.config.defaultMaxDurationMs,maxRetries:e.maxRetries??this.config.defaultMaxRetries,...e.subscriber?{subscriber:e.subscriber}:{},...t?{target:`session`,boundSessionId:this.getSessionIdForTask()}:{},...e.eventTrigger?{eventTrigger:e.eventTrigger}:{},...e.modelId?{modelId:e.modelId}:{},...e.thinkingLevel?{thinkingLevel:e.thinkingLevel}:{}};return this.registry.add(o),this.persistence.saveOne(o),this.armIfEventDriven(o),o}remove(e){return this.terminate(e,`user-removed`)}update(e,t){let n=this.registry.get(e);if(!n)return!1;if(t.name!==void 0&&(n.name=t.name),t.prompt!==void 0&&(n.prompt=t.prompt),t.enabled!==void 0&&(n.enabled=t.enabled),t.cronExpression!==void 0){n.cronExpression=t.cronExpression;let e=this.deps.now?.()??Date.now(),r=S(n.cronExpression,new Date(e+6e4));n.nextFireAt=I(this.config,n.id,r,n.recurring)}return this.persistence.saveOne(n),!0}list(){return this.registry.list()}getRunningTaskIds(){for(let e of this.deps.fireTargets)if(e.getRunningTaskIds)return e.getRunningTaskIds();return new Set}readFireLogs(e,t=20){return this.fireLogger.read(e,t)}runNow(e){let t=this.registry.get(e);if(!t)throw Error(`Schedule task "${e}" not found`);if(!t.enabled)throw Error(`Schedule task "${e}" is disabled`);if(!this.deps.ownership.isOwner())throw Error(`Schedule task "${e}" cannot be run now: another process holds the fire ownership`);if(this.fireExecutor.has(t.id))throw Error(`Schedule task "${e}" is already firing`);this.fireExecutor.addFiring(t.id),this.fireExecutor.fire(t)}cancel(e){if(!this.registry.get(e))return{ok:!1,reason:`task_not_found`};for(let t of this.deps.fireTargets)if(t.requestCancel)return t.requestCancel(e);return{ok:!1,reason:`not_running`}}armIfEventDriven(e){if(!e.eventTrigger)return;let t=this.triggers.find(t=>t.canHandle(e));if(!t){this.deps.logger?.error(`[schedules] event-trigger task ${e.id} has no matching trigger (source=${e.eventTrigger.source}) — will never fire`);return}this.disarmIfArmed(e.id);let n=t.arm(e,e=>{this.fireExecutor.has(e.id)||(this.fireExecutor.addFiring(e.id),this.fireExecutor.fire(e))});this.armedTriggers.set(e.id,n)}disarmIfArmed(e){let t=this.armedTriggers.get(e);t&&(t(),this.armedTriggers.delete(e))}disarmAll(){for(let e of this.armedTriggers.values())e();this.armedTriggers.clear()}describeSessionOwnershipRefusal(){let e=`Cannot create a session-local scheduled task: this terminal does not hold fire ownership.`;if(this.deps.ownership.lastFailureReason?.()===`network-error`)return`${e} Could not reach the remote schedule service — check network/persistenced connectivity, then retry.`;let t=this.deps.ownership.describeOwner?.();return`${e}${t?.pid===void 0?` It is currently held by another otto process for this workspace.`:` It is currently held by another otto process (pid ${t.pid}${t.host===void 0?``:` on ${t.host}`}).`} Create the task in that terminal instead, or close it — this process retries acquiring ownership every ${Math.round(this.config.recoveryRetryIntervalMs/1e3)}s and will take over automatically once the lease is released (no restart needed).`}getSessionIdForTask(){for(let e of this.deps.fireTargets)if(e.getSessionId)return e.getSessionId();return``}};function B(e){return f(p,`schedules`,e)}function V(e,t={}){let n=t.persistence??(v()?b({type:`memory`}):b({type:`file`,baseDir:B(e)})),r=t.logger;return{async saveTask(e){let t={version:1,id:e.id,data:e,metadata:{createdAt:e.createdAt,updatedAt:Date.now(),tags:[`schedule`]}};await n.save(t)},async loadAllTasks(){let e;try{e=await n.list()}catch(e){return r?.error(`[schedules] Failed to list schedule snapshots:`,e),[]}let t=[];for(let i of e)try{let e=await n.load(i);e&&t.push(e.data)}catch(e){r?.error(`[schedules] Failed to load schedule "${i}":`,e)}return t.sort((e,t)=>e.nextFireAt-t.nextFireAt),t},async deleteTask(e){try{return await n.delete(e)}catch(t){return r?.error(`[schedules] Failed to delete schedule "${e}":`,t),!1}}}}var H=class extends y{get serviceLabel(){return`schedule 远程服务`}get endpointFlag(){return`--session-url`}extractId(e){return e.id}async saveTask(e){await this.save({version:1,id:e.id,data:e})}async loadAllTasks(){let e=await this.list(),t=[];for(let n of e){let e=await this.load(n);e&&t.push(e.data)}return t.sort((e,t)=>e.nextFireAt-t.nextFireAt),t}async deleteTask(e){return this.delete(e)}};function U(e){return new H({baseUrl:`${new URL(e.sessionUrl).origin}/api/storage/schedules`,getAuth:e.getAuth,fetch:e.fetch??globalThis.fetch,timeoutMs:e.timeoutMs??1e4,wsKey:e.wsKey})}const W=[{version:1,up:e=>{e.exec(`
2
2
  CREATE TABLE IF NOT EXISTS schedule_lease (
3
3
  ws_key TEXT PRIMARY KEY,
4
4
  token TEXT NOT NULL,
5
5
  renewed_at INTEGER NOT NULL
6
6
  );
7
- `)}}];var L=class extends e{get serviceLabel(){return`schedule 远程服务`}get endpointFlag(){return`--session-url`}extractId(e){return e.id}async saveTask(e){await this.save({version:1,id:e.id,data:e})}async loadAllTasks(){let e=await this.list(),t=[];for(let n of e){let e=await this.load(n);e&&t.push(e.data)}return t.sort((e,t)=>e.nextFireAt-t.nextFireAt),t}async deleteTask(e){return this.delete(e)}};function R(e){return new L({baseUrl:`${new URL(e.sessionUrl).origin}/api/storage/schedules`,getAuth:e.getAuth,fetch:e.fetch??globalThis.fetch,timeoutMs:e.timeoutMs??1e4,wsKey:e.wsKey})}function z(e){let t=x(),n=e.fetch??globalThis.fetch,r=e.timeoutMs??1e4,i=new URL(e.sessionUrl).origin,a=e.now??Date.now,o=!1,s=0,c,l,u=async a=>{let o=await e.getAuth(),s=new AbortController,c=setTimeout(()=>s.abort(),r);try{let r=await n(`${i}/api/schedules/${encodeURIComponent(e.wsKey)}/lease/${a}`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${o.token}`},body:JSON.stringify({token:t}),signal:s.signal});return r.ok?{ok:!0,data:await r.json()}:{ok:!1,reason:`network-error`}}catch{return{ok:!1,reason:`network-error`}}finally{clearTimeout(c)}},d=()=>{if(c)return c;let e=(async()=>{s=a();let e=await u(`acquire`);if(!e.ok)return o=!1,l=`network-error`,!1;let t=e.data.acquired===!0;return o=t,l=t?void 0:`occupied`,t})();return c=e,e.finally(()=>{c===e&&(c=void 0)}),e};return{tryAcquire:d,async renew(){if(a()-s<3e4)return;if(!o){await d();return}s=a();let e=await u(`renew`);if(!e.ok){o=!1,l=`network-error`;return}e.data.renewed===!0?l=void 0:(o=!1,l=`occupied`)},async release(){o&&=(await u(`release`),!1)},isOwner(){return o},lastFailureReason(){return o?void 0:l}}}const B=1e3;var V=class{deps;registry;ticker=null;recoveryTimer=null;firing=new Set;tickInProgress=!1;running=!1;tickCount=0;runningJobsByTaskId=new Map;cancelRequested=new Set;_nextFireToken=0;constructor(e){this.deps=e,this.registry=e.registry}isFireOwner(){return this.deps.ownership.isOwner()}fireOwnerFailureReason(){return this.deps.ownership.lastFailureReason?.()}async start(){if(!this.running){if(!await this.deps.ownership.tryAcquire()){try{let e=await this.deps.store.loadAllTasks();for(let t of e)try{this.registry.add(t)}catch{}}catch(e){this.deps.logger?.error(`[schedules] Failed to load schedules (read-only mode):`,e)}return}try{let e=this.deps.now?.()??Date.now(),t=await this.deps.store.loadAllTasks();for(let n of t){if(n.recurring&&n.nextFireAt<e)try{let t=C(n.cronExpression,new Date(e+6e4));n.nextFireAt=this.applyJitter(n.id,t,!0)}catch{}try{this.registry.add(n)}catch{}}}catch(e){this.deps.logger?.error(`[schedules] Failed to load schedules:`,e)}this.running=!0,this.ticker=setInterval(()=>{this.tick()},B),this.ticker.unref()}}async reloadFromStore(){let e;try{e=await this.deps.store.loadAllTasks()}catch(e){this.deps.logger?.error(`[schedules] Failed to reload schedules from store:`,e);return}let t=new Set(e.map(e=>e.id));for(let t of e){if(this.firing.has(t.id))continue;if(!t.recurring&&t.lastFiredAt!=null&&!this.registry.get(t.id)){this.deps.store.deleteTask(t.id).catch(e=>{this.deps.logger?.error(`[schedules] Failed to delete zombie one-shot ${t.id}:`,e)});continue}let e=this.registry.get(t.id);if(e)e.enabled=t.enabled,e.name=t.name,e.prompt=t.prompt,e.cronExpression=t.cronExpression,e.maxDurationMs=t.maxDurationMs,e.maxRetries=t.maxRetries;else try{this.registry.add(t)}catch{}}for(let e of this.registry.list())e.target!==`session`&&!t.has(e.id)&&!this.firing.has(e.id)&&this.registry.remove(e.id)}async stop(){!this.running&&!this.deps.ownership.isOwner()||(this.stopRecovery(),this.ticker&&=(clearInterval(this.ticker),null),this.running=!1,await this.deps.ownership.release(),await this.flushAll())}startRecovery(){this.recoveryTimer||(this.deps.logger?.error(`[schedules] Lost fire ownership — entering recovery mode`),this.recoveryTimer=setInterval(()=>{this.recoveryAttempt()},3e4),this.recoveryTimer.unref())}async recoveryAttempt(){try{await this.deps.ownership.tryAcquire()&&this.deps.ownership.isOwner()&&(this.stopRecovery(),this.running=!0,this.ticker=setInterval(()=>{this.tick()},B),this.ticker.unref(),this.deps.logger?.error(`[schedules] Re-acquired fire ownership — recovery complete`))}catch{}}stopRecovery(){this.recoveryTimer&&=(clearInterval(this.recoveryTimer),null)}add(e){if(this.registry.count()>=50)throw Error(`Schedule limit reached (max 50). Remove some tasks before adding more.`);let t=e.target===`session`&&!e.subscriber;if(t&&!this.deps.ownership.isOwner())throw Error(`Cannot create a session-local scheduled task: this terminal does not hold fire ownership. Session-local tasks must be created in the terminal that will actually fire them.`);let n=crypto.randomUUID().slice(0,8),r=this.deps.now?.()??Date.now(),i=C(e.cronExpression,new Date(r+6e4)),a=this.applyJitter(n,i,e.recurring),o={id:n,name:e.name,prompt:e.prompt,cronExpression:e.cronExpression,enabled:!0,recurring:e.recurring,origin:e.origin,createdAt:r,nextFireAt:a,maxDurationMs:e.maxDurationMs??3e5,maxRetries:e.maxRetries??0,...e.subscriber?{subscriber:e.subscriber}:{},...t?{target:`session`,boundSessionId:this.deps.getSessionId()}:{}};return this.registry.add(o),this.saveOne(o),o}remove(e){let t=this.registry.remove(e);return t&&this.deleteOne(e),t}update(e,t){let n=this.registry.get(e);if(!n)return!1;if(t.name!==void 0&&(n.name=t.name),t.prompt!==void 0&&(n.prompt=t.prompt),t.enabled!==void 0&&(n.enabled=t.enabled),t.cronExpression!==void 0){n.cronExpression=t.cronExpression;let e=this.deps.now?.()??Date.now(),r=C(n.cronExpression,new Date(e+6e4));n.nextFireAt=this.applyJitter(n.id,r,n.recurring)}return this.saveOne(n),!0}list(){return this.registry.list()}getRunningTaskIds(){return new Set(this.runningJobsByTaskId.keys())}readFireLogs(e,t=20){let r=c(n,`schedule-logs`),i=`${e}-`;try{let e=p(r).filter(e=>e.startsWith(i)&&e.endsWith(`.log`)).sort().reverse(),n=[];for(let i=0;i<e.length&&n.length<t;i++)try{let t=f(c(r,e[i]),`utf-8`).trim(),a=t.indexOf(` `),o=a>0?t.slice(0,a):t,s=a>0?t.slice(a+1):``;n.push({timestamp:o,status:s})}catch{}return n}catch{return[]}}runNow(e){let t=this.registry.get(e);if(!t)throw Error(`Schedule task "${e}" not found`);if(!t.enabled)throw Error(`Schedule task "${e}" is disabled`);if(this.firing.has(t.id))throw Error(`Schedule task "${e}" is already firing`);this.firing.add(t.id),this.fire(t)}cancel(e){let t=this.registry.get(e);if(!t)return{ok:!1,reason:`task_not_found`};let n,r=this.runningJobsByTaskId.get(e);if(r)n=r.jobId;else{let e=this.deps.jobRegistry.list().filter(e=>e.status===`running`||e.status===`needs_input`);e.length===1&&(n=e[0].id)}if(!n)return{ok:!1,reason:`not_running`};let i=this.deps.jobRegistry.get(n);return i?i.status===`ready`?{ok:!1,reason:`job_is_ready`}:i.status===`applied`?{ok:!1,reason:`job_already_applied`}:i.status===`failed`?{ok:!1,reason:`job_already_failed`}:i.status===`canceled`?{ok:!1,reason:`job_already_canceled`}:(this.cancelRequested.add(t.id),this.deps.jobRegistry.cancel(n),{ok:!0}):{ok:!1,reason:`job_not_found`}}async tick(){if(!this.tickInProgress){this.tickInProgress=!0;try{if(await this.deps.ownership.renew(),!this.deps.ownership.isOwner()){this.running=!1,this.ticker&&=(clearInterval(this.ticker),null),this.startRecovery();return}this.tickCount++,this.tickCount%30==0&&await this.reloadFromStore();let e=this.deps.now?.()??Date.now();for(let t of this.registry.list())t.recurring&&e-t.nextFireAt>6048e5&&(this.registry.remove(t.id),this.deleteOne(t.id));let t=this.registry.findDue(e);for(let n of t){if(this.firing.has(n.id)||!n.recurring&&(n.lastFireFailed||n.lastFireCancelled))continue;let t=n.nextFireAt,r=C(n.cronExpression,new Date(e+6e4)),i=this.applyJitter(n.id,r,n.recurring);this.registry.update(n.id,{nextFireAt:i}),this.saveOne(n),this.firing.add(n.id),this.fire(n,t)}}finally{this.tickInProgress=!1}}}fireSubscriber(e,t){let n=e.subscriber;if(!n)return!1;let r=this.deps.notifySubscriber;if(!r)return this.writeFireLog(e.id,`subscriber tick skipped: host has no notifySubscriber port`),!1;let i=this.deps.now?.()??Date.now(),a=`${e.id}@${t??i}`,o=!1;try{o=r(n,{scheduleId:e.id,occurrenceId:a,occurredAt:i})}catch(t){return this.deps.logger?.error(`[schedules] subscriber notify threw for task ${e.id}:`,t),this.writeFireLog(e.id,`subscriber tick error: ${t instanceof Error?t.message:String(t)}`),!1}return this.writeFireLog(e.id,o?`subscriber tick delivered (${n.pluginId}:${n.serviceId}, occurrence ${a})`:`subscriber tick not delivered (${n.pluginId}:${n.serviceId} not running)`),o}fireSession(e){if(!e.boundSessionId)return this.writeFireLog(e.id,`session tick skipped: task has no boundSessionId (invalid state)`),!1;let t=this.deps.followUpCurrentSession;if(!t)return this.writeFireLog(e.id,`session tick skipped: host has no followUpCurrentSession port`),!1;let n=e.origin===`model`&&e.lastFiredAt==null,r=`⏰ scheduled: ${e.name}`,i=n?`${r} [created by the model — first fire, use /schedule cancel ${e.id} to stop it]\n\n${e.prompt}`:`${r}\n\n${e.prompt}`,a=!1;try{a=t({prompt:i,boundSessionId:e.boundSessionId,name:e.name,origin:e.origin})}catch(t){return this.deps.logger?.error(`[schedules] session followUp threw for task ${e.id}:`,t),this.writeFireLog(e.id,`session tick error: ${t instanceof Error?t.message:String(t)}`),!1}return this.writeFireLog(e.id,a?`session tick delivered (session ${e.boundSessionId})`:`session tick not delivered (session ${e.boundSessionId} unavailable — evicted/disposed/archived/paused/mismatched)`),a}async fire(e,t){let n=`failed`,r=!1,i,a=++this._nextFireToken;try{if(e.subscriber){n=this.fireSubscriber(e,t)?`success`:`failed`;return}if(e.target===`session`){let t=this.fireSession(e);n=t?`success`:`failed`,t&&this.registry.update(e.id,{lastFiredAt:this.deps.now?.()??Date.now(),lastFireFailed:!1,lastFireError:void 0});return}let o=e.origin===`model`?`main`:`user`,s=this.deps.getSessionId();for(let t=0;t<=e.maxRetries;t++){if(this.cancelRequested.has(e.id)){this.writeFireLog(e.id,`canceled by user (attempt ${t+1})`),r=!0;break}let c=this.deps.startJob({title:e.name,prompt:e.prompt,sessionId:s,origin:o});this.runningJobsByTaskId.set(e.id,{jobId:c.id,fireToken:a,attempt:t});let l=await this.waitForCompletion(c.id,e.maxDurationMs);if(l===`success`){this.registry.update(e.id,{lastFiredAt:this.deps.now?.()??Date.now(),lastFireFailed:!1,lastFireError:void 0}),this.saveOne(e);let r=this.deps.jobRegistry.get(c.id),i=r?.status===`ready`&&!!r.diff?.trim();this.writeFireLog(e.id,i?`completed (attempt ${t+1}) — diff ready, /job apply ${c.id}`:`completed (attempt ${t+1})`),n=`success`;return}if(l===`canceled`){this.writeFireLog(e.id,`canceled by user (attempt ${t+1})`),r=!0;break}if(i=l===`timeout`?`timed out`:`job failed`,t<e.maxRetries){let e=this.deps.retryBackoffMs??0;await(this.deps.sleep??(e=>new Promise(t=>setTimeout(t,e))))(e)}}r||this.writeFireLog(e.id,`failed after ${e.maxRetries+1} attempt(s)`)}catch(t){i=t instanceof Error?t.message:String(t),this.deps.logger?.error(`[schedules] fire failed for task ${e.id}:`,t),this.writeFireLog(e.id,`error: ${i}`)}finally{this.firing.delete(e.id),this.runningJobsByTaskId.delete(e.id);let t=this.cancelRequested.has(e.id);this.cancelRequested.delete(e.id),e.recurring||(n===`success`?(this.registry.remove(e.id),await this.deleteOne(e.id)):r?(this.registry.update(e.id,{lastFireCancelled:!0,lastFireError:void 0}),this.saveOne(e)):t||(this.registry.update(e.id,{lastFireFailed:!0,lastFireError:i}),this.saveOne(e)))}}waitForCompletion(e,t){return new Promise(n=>{let r=!1,i,a,o,s=(this.deps.now?.()??Date.now())+t*3,c=()=>{i&&clearTimeout(i),a?.(),o?.()},l=e=>{r||(r=!0,c(),n(e))},u=t=>{i&&clearTimeout(i),i=setTimeout(()=>{this.deps.jobRegistry.cancel(e),l(`failed`)},t)};o=this.deps.jobRegistry.onUpdate(n=>{if(n.id===e){if(n.status===`ready`)l(`success`);else if(n.status===`needs_input`){let n=this.deps.now?.()??Date.now(),r=Math.min(t,s-n);if(r<=0){this.deps.jobRegistry.cancel(e),l(`failed`);return}u(r)}}}),a=this.deps.jobRegistry.onExit(t=>{t.id===e&&(t.status===`failed`?l(`failed`):t.status===`canceled`?l(`canceled`):t.status===`applied`&&l(`success`))}),u(t)})}applyJitter(e,t,n){let r=0;for(let t=0;t<e.length;t++)r=(r<<5)-r+e.charCodeAt(t),r|=0;let i=Math.abs(r)%(n?18e5:9e4);return t.getTime()+i}saveOne(e){e.target!==`session`&&this.deps.store.saveTask(e).catch(t=>{this.deps.logger?.error(`[schedules] Failed to save schedule ${e.id}:`,t)})}async deleteOne(e){if(this.registry.get(e)?.target===`session`)return!0;try{return await this.deps.store.deleteTask(e)}catch(t){return this.deps.logger?.error(`[schedules] Failed to delete schedule ${e}:`,t),!1}}async flushAll(){try{for(let e of this.registry.list())e.target!==`session`&&await this.deps.store.saveTask(e)}catch(e){this.deps.logger?.error(`[schedules] Failed to flush schedules:`,e)}}writeFireLog(e,t){if(s())return;let r=c(n,`schedule-logs`),i=c(r,`${e}-${Date.now()}.log`);try{u(r,{recursive:!0}),y(i,`${new Date().toISOString()} ${t}\n`,`utf-8`),this.pruneFireLogs(r,e)}catch{}}pruneFireLogs(e,t){try{let n=`${t}-`,r=p(e).filter(e=>e.startsWith(n)&&e.endsWith(`.log`)).sort(),i=r.length-20;if(i<=0)return;for(let t of r.slice(0,i))try{_(c(e,t))}catch{}}catch{}}};function H(e){return{create:t=>{let n=e();if(!n)throw Error(`Schedule scheduler is not available in this session.`);let r=n.add({name:t.name??`schedule`,prompt:t.prompt,cronExpression:t.cron,recurring:t.recurring,origin:`model`,maxDurationMs:t.maxDurationMs,target:t.target});return{taskId:r.id,nextFireAt:r.nextFireAt,name:r.name,target:r.target}},list:()=>(e()?.list()??[]).map(e=>({id:e.id,name:e.name,cronExpression:e.cronExpression,enabled:e.enabled,recurring:e.recurring,nextFireAt:e.nextFireAt,lastFiredAt:e.lastFiredAt,lastFireFailed:e.lastFireFailed,lastFireError:e.lastFireError,lastFireCancelled:e.lastFireCancelled})),delete:t=>e()?.remove(t)??!1,run:t=>{e()?.runNow(t)},cancel:t=>e()?.cancel(t)??{ok:!1,reason:`Schedule scheduler is not available.`}}}export{I as SCHEDULE_LEASE_MIGRATIONS,S as ScheduleRegistry,V as SchedulerService,F as createLocalFireOwnership,z as createRemoteFireOwnership,R as createRemoteScheduleStore,H as createScheduleCapability,N as createScheduleStore,C as parseCron};
7
+ `)}}];function G(e){return f(p,`schedule-owner-${e}.lock`)}function K(i){let u=x(),f=G(i),y=m(),b=!1,S=()=>{try{t(p,{recursive:!0});let r=n(f,`wx`);try{d(r,g(u,process.pid,y))}finally{e(r)}return b=!0,!0}catch(e){if(e.code!==`EEXIST`)throw e;return!1}},C=()=>{try{return h(r(f,`utf-8`).trim())}catch{return null}},w=()=>C()?.token??null,T=e=>e.pid===void 0||e.host===void 0||e.host!==y?!1:!_(e.pid),E=e=>e.pid===void 0||e.host===void 0||e.host!==y?!1:_(e.pid),D=()=>{if(b)return!0;if(v())return!1;if(S())return!0;let e=C(),t;try{t=s(f).mtimeMs}catch{return S()}if(e!==null&&E(e)||!(e!==null&&T(e))&&Date.now()-t<=3e5)return!1;let n=`${f}.stale-${x()}`;try{a(f,n),o(n,{force:!0})}catch{return!1}return S()};return{async tryAcquire(){return D()},async renew(){if(b){if(w()!==u){b=!1;return}try{let e=new Date;l(f,e,e)}catch{b=!1}}},async release(){if(b){if(w()===u)try{c(f)}catch{}b=!1}},isOwner(){return b&&w()===u},describeOwner(){let e=C();if(e!==null&&!(e.pid===void 0&&e.host===void 0))return{...e.pid===void 0?{}:{pid:e.pid},...e.host===void 0?{}:{host:e.host}}}}}function q(e){let t=x(),n=e.fetch??globalThis.fetch,r=e.timeoutMs??1e4,i=new URL(e.sessionUrl).origin,a=e.now??Date.now,o=!1,s=0,c,l,u=async a=>{let o=await e.getAuth(),s=new AbortController,c=setTimeout(()=>s.abort(),r);try{let r=await n(`${i}/api/schedules/${encodeURIComponent(e.wsKey)}/lease/${a}`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${o.token}`},body:JSON.stringify({token:t}),signal:s.signal});return r.ok?{ok:!0,data:await r.json()}:{ok:!1,reason:`network-error`}}catch{return{ok:!1,reason:`network-error`}}finally{clearTimeout(c)}},d=()=>{if(c)return c;let e=(async()=>{s=a();let e=await u(`acquire`);if(!e.ok)return o=!1,l=`network-error`,!1;let t=e.data.acquired===!0;return o=t,l=t?void 0:`occupied`,t})();return c=e,e.finally(()=>{c===e&&(c=void 0)}),e};return{tryAcquire:d,async renew(){if(a()-s<3e4)return;if(!o){await d();return}s=a();let e=await u(`renew`);if(!e.ok){o=!1,l=`network-error`;return}e.data.renewed===!0?l=void 0:(o=!1,l=`occupied`)},async release(){o&&=(await u(`release`),!1)},isOwner(){return o},lastFailureReason(){return o?void 0:l}}}var J=class{type=`job`;runningJobsByTaskId=new Map;cancelRequested=new Set;_nextFireToken=0;constructor(e){this.deps=e}canHandle(e){return!e.subscriber&&e.target!==`session`}async fire(e,t){let n=`failed`,r=!1,i,a=++this._nextFireToken,o=e.origin===`model`?`main`:`user`,s=this.deps.getSessionId?.()??``;for(let c=0;c<=e.maxRetries;c++){if(this.cancelRequested.has(e.id)){this.deps.fireLogger.write(e.id,`canceled by user (attempt ${c+1})`),r=!0;break}let l;try{l=this.deps.startJob({title:e.name,prompt:e.prompt,sessionId:s,origin:o,...e.modelId?{model:{id:e.modelId,thinkingLevel:e.thinkingLevel}}:{}})}catch(t){if(i=t instanceof Error?t.message:String(t),this.deps.fireLogger.write(e.id,`startJob failed (attempt ${c+1}): ${i}`),c<e.maxRetries){let e=this.deps.retryBackoffMs??0;await(this.deps.sleep??(e=>new Promise(t=>setTimeout(t,e))))(e)}continue}this.runningJobsByTaskId.set(e.id,{jobId:l.id,fireToken:a,attempt:c});let u=await this.waitForCompletion(l.id,e.maxDurationMs,t);if(u===`success`){let t=this.deps.jobRegistry.get(l.id),r=t?.status===`ready`&&!!t.diff?.trim();return this.deps.fireLogger.write(e.id,r?`completed (attempt ${c+1}) — diff ready, /job apply ${l.id}`:`completed (attempt ${c+1})`),n=`success`,{outcome:n,jobId:l.id}}if(u===`canceled`){this.deps.fireLogger.write(e.id,`canceled by user (attempt ${c+1})`),r=!0;break}if(i=u===`timeout`?`timed out`:`job failed`,c<e.maxRetries){let e=this.deps.retryBackoffMs??0;await(this.deps.sleep??(e=>new Promise(t=>setTimeout(t,e))))(e)}}return r||this.deps.fireLogger.write(e.id,`failed after ${e.maxRetries+1} attempt(s)`),{outcome:n,cancelled:r,error:i}}requestCancel(e){let t,n=this.runningJobsByTaskId.get(e);if(n)t=n.jobId;else{let e=this.deps.jobRegistry.list().filter(e=>e.status===`running`||e.status===`needs_input`);e.length===1&&(t=e[0].id)}if(!t)return{ok:!1,reason:`not_running`};let r=this.deps.jobRegistry.get(t);return r?r.status===`ready`?{ok:!1,reason:`job_is_ready`}:r.status===`applied`?{ok:!1,reason:`job_already_applied`}:r.status===`failed`?{ok:!1,reason:`job_already_failed`}:r.status===`canceled`?{ok:!1,reason:`job_already_canceled`}:(this.cancelRequested.add(e),this.deps.jobRegistry.cancel(t),{ok:!0}):{ok:!1,reason:`job_not_found`}}cleanup(e){this.runningJobsByTaskId.delete(e),this.cancelRequested.delete(e)}getRunningTaskIds(){return new Set(this.runningJobsByTaskId.keys())}waitForCompletion(e,t,n){let r=this.deps.needsInputMaxExtensionFactor??3;return new Promise(i=>{let a=!1,o,s,c,l=n.now()+t*r,u=()=>{o&&clearTimeout(o),s?.(),c?.()},d=e=>{a||(a=!0,u(),i(e))},f=t=>{o&&clearTimeout(o),o=setTimeout(()=>{this.deps.jobRegistry.cancel(e),d(`failed`)},t)};c=this.deps.jobRegistry.onUpdate(r=>{if(r.id===e){if(r.status===`ready`)d(`success`);else if(r.status===`needs_input`){let r=n.now(),i=Math.min(t,l-r);if(i<=0){this.deps.jobRegistry.cancel(e),d(`failed`);return}f(i)}}}),s=this.deps.jobRegistry.onExit(t=>{t.id===e&&(t.status===`failed`?d(`failed`):t.status===`canceled`?d(`canceled`):t.status===`applied`&&d(`success`))}),f(t)})}},Y=class{type=`session`;constructor(e){this.deps=e}canHandle(e){return e.target===`session`}getSessionId(){return this.deps.getSessionId()}async fire(e,t){if(!e.boundSessionId)return this.deps.fireLogger.write(e.id,`session tick skipped: task has no boundSessionId (invalid state)`),{outcome:`failed`,error:`no boundSessionId`};let n=e.origin===`model`&&e.lastFiredAt==null,r=`⏰ scheduled: ${e.name}`,i=n?`${r} [created by the model — first fire, use /schedule cancel ${e.id} to stop it]\n\n${e.prompt}`:`${r}\n\n${e.prompt}`,a=!1;try{a=this.deps.followUp({prompt:i,boundSessionId:e.boundSessionId,name:e.name,origin:e.origin})}catch(t){return this.deps.fireLogger.write(e.id,`session tick error: ${t instanceof Error?t.message:String(t)}`),{outcome:`failed`,error:t instanceof Error?t.message:String(t)}}return this.deps.fireLogger.write(e.id,a?`session tick delivered (session ${e.boundSessionId})`:`session tick not delivered (session ${e.boundSessionId} unavailable — evicted/disposed/archived/paused/mismatched)`),{outcome:a?`success`:`failed`}}},X=class{type=`plugin-service`;constructor(e){this.deps=e}canHandle(e){return!!e.subscriber}async fire(e,t){let n=e.subscriber;if(!n)return{outcome:`failed`,error:`no subscriber on task`};let r=t.now(),i=`${e.id}@${t.scheduledFor??r}`,a=!1;try{a=this.deps.notify(n,{scheduleId:e.id,occurrenceId:i,occurredAt:r})}catch(t){return this.deps.fireLogger.write(e.id,`subscriber tick error: ${t instanceof Error?t.message:String(t)}`),{outcome:`failed`,error:t instanceof Error?t.message:String(t)}}return this.deps.fireLogger.write(e.id,a?`subscriber tick delivered (${n.pluginId}:${n.serviceId}, occurrence ${i})`:`subscriber tick not delivered (${n.pluginId}:${n.serviceId} not running)`),{outcome:a?`success`:`failed`}}},Z=class{type=`in-process-event`;fireTimestamps=new Map;now;debounceWindowMs;maxFiresPerWindow;constructor(e){this.deps=e,this.now=e.now??Date.now,this.debounceWindowMs=e.debounceWindowMs??6e4,this.maxFiresPerWindow=e.maxFiresPerWindow??5}canHandle(e){return e.eventTrigger?.source===`job`}arm(e,t){let n=e.eventTrigger;return!n||n.source!==`job`?()=>{}:this.deps.jobRegistry.onExit(r=>{if(this.matches(r,n)){if(!this.passesDebounce(e.id)){this.deps.logger?.error(`[schedules] event-trigger ${e.id} debounced (>${this.maxFiresPerWindow} fires / ${this.debounceWindowMs}ms)`);return}t(e)}})}matches(e,t){return!(t.event!==e.status||t.filter?.sessionId&&t.filter.sessionId!==e.sessionId)}passesDebounce(e){let t=this.now(),n=t-this.debounceWindowMs,r=(this.fireTimestamps.get(e)??[]).filter(e=>e>n);return r.length>=this.maxFiresPerWindow?(this.fireTimestamps.set(e,r),!1):(r.push(t),this.fireTimestamps.set(e,r),!0)}};function Q(e,t={}){return{create:n=>{let r=e();if(!r)throw Error(`Schedule scheduler is not available in this session.`);if(n.modelId){let e=t.validateModelId?.(n.modelId);if(e)throw Error(e)}let i=r.add({name:n.name??`schedule`,prompt:n.prompt,cronExpression:n.cron,recurring:n.recurring,origin:`model`,maxDurationMs:n.maxDurationMs,target:n.target,eventTrigger:n.eventTrigger,modelId:n.modelId,thinkingLevel:n.thinkingLevel});return{taskId:i.id,nextFireAt:i.nextFireAt,name:i.name,target:i.target}},list:()=>(e()?.list()??[]).map(e=>({id:e.id,name:e.name,cronExpression:e.cronExpression,enabled:e.enabled,recurring:e.recurring,nextFireAt:e.nextFireAt,lastFiredAt:e.lastFiredAt,lastFireFailed:e.lastFireFailed,lastFireError:e.lastFireError,lastFireCancelled:e.lastFireCancelled})),delete:t=>e()?.remove(t)??!1,run:t=>{e()?.runNow(t)},cancel:t=>e()?.cancel(t)??{ok:!1,reason:`Schedule scheduler is not available.`}}}export{F as DEFAULT_SCHEDULE_CONFIG,P as FireLogger,Z as InProcessEventTrigger,J as JobFireTarget,W as SCHEDULE_LEASE_MIGRATIONS,j as ScheduleRegistry,z as SchedulerService,Y as SessionFireTarget,X as SubscriberFireTarget,K as createLocalFireOwnership,q as createRemoteFireOwnership,U as createRemoteScheduleStore,Q as createScheduleCapability,V as createScheduleStore,S as parseCron};
8
8
  //# sourceMappingURL=index.js.map