@automagik/genie 4.260421.7 → 4.260421.8
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/dist/genie.js
CHANGED
|
@@ -1897,7 +1897,11 @@ ${body}`;writeFileSync12(filePath,output,"utf-8")}function serializeSdkConfig(sd
|
|
|
1897
1897
|
`,await sql`
|
|
1898
1898
|
UPDATE triggers SET status = 'failed', completed_at = ${now}
|
|
1899
1899
|
WHERE id = ${run.trigger_id} AND status = 'executing'
|
|
1900
|
-
`,orphanCount++}if(orphanCount>0)deps.log({timestamp:now.toISOString(),level:"info",event:"orphaned_runs_reconciled",count:orphanCount,daemon_id:daemonId});return orphanCount}async function recoverOnStartup(deps,daemonId,config){let now=deps.now();deps.log({timestamp:now.toISOString(),level:"info",event:"recovery_started",daemon_id:daemonId});let reclaimed=await reclaimExpiredLeases(deps,daemonId),orphans=await reconcileOrphanedRuns(deps,daemonId),{resumed,failed}=await runAgentRecoveryPass(deps,daemonId,config,"boot");if(deps.log({timestamp:deps.now().toISOString(),level:"info",event:"recovery_completed",reclaimed_leases:reclaimed,orphaned_runs:orphans,resumed_agents:resumed,failed_agents:failed,daemon_id:daemonId}),failed>0)deps.log({timestamp:deps.now().toISOString(),level:"info",event:"recovery_retry_scheduled",daemon_id:daemonId,failed_agents:failed,delay_ms:RECOVERY_RETRY_DELAY_MS}),scheduleRecoveryRetry(deps,daemonId,config)}function scheduleRecoveryRetry(deps,daemonId,config){setTimeout(async()=>{try{let retry=await runAgentRecoveryPass(deps,daemonId,config,"boot");deps.log({timestamp:deps.now().toISOString(),level:"info",event:"recovery_retry_completed",daemon_id:daemonId,resumed_agents:retry.resumed,failed_agents:retry.failed})}catch(err){let message=err instanceof Error?err.message:String(err);deps.log({timestamp:deps.now().toISOString(),level:"error",event:"recovery_retry_error",daemon_id:daemonId,error:message})}},RECOVERY_RETRY_DELAY_MS).unref?.()}async function
|
|
1900
|
+
`,orphanCount++}if(orphanCount>0)deps.log({timestamp:now.toISOString(),level:"info",event:"orphaned_runs_reconciled",count:orphanCount,daemon_id:daemonId});return orphanCount}async function recoverOnStartup(deps,daemonId,config){let now=deps.now();deps.log({timestamp:now.toISOString(),level:"info",event:"recovery_started",daemon_id:daemonId});let reclaimed=await reclaimExpiredLeases(deps,daemonId),orphans=await reconcileOrphanedRuns(deps,daemonId),{resumed,failed}=await runAgentRecoveryPass(deps,daemonId,config,"boot");if(deps.log({timestamp:deps.now().toISOString(),level:"info",event:"recovery_completed",reclaimed_leases:reclaimed,orphaned_runs:orphans,resumed_agents:resumed,failed_agents:failed,daemon_id:daemonId}),failed>0)deps.log({timestamp:deps.now().toISOString(),level:"info",event:"recovery_retry_scheduled",daemon_id:daemonId,failed_agents:failed,delay_ms:RECOVERY_RETRY_DELAY_MS}),scheduleRecoveryRetry(deps,daemonId,config)}function scheduleRecoveryRetry(deps,daemonId,config){setTimeout(async()=>{try{let retry=await runAgentRecoveryPass(deps,daemonId,config,"boot");deps.log({timestamp:deps.now().toISOString(),level:"info",event:"recovery_retry_completed",daemon_id:daemonId,resumed_agents:retry.resumed,failed_agents:retry.failed})}catch(err){let message=err instanceof Error?err.message:String(err);deps.log({timestamp:deps.now().toISOString(),level:"error",event:"recovery_retry_error",daemon_id:daemonId,error:message})}},RECOVERY_RETRY_DELAY_MS).unref?.()}async function isLegitimatelyClosed(deps,worker){try{let sql=await deps.getConnection(),executorId=(await sql`
|
|
1901
|
+
SELECT current_executor_id FROM agents WHERE id = ${worker.id}
|
|
1902
|
+
`)[0]?.current_executor_id;if(!executorId)return!1;let execRows=await sql`
|
|
1903
|
+
SELECT closed_at, outcome FROM executors WHERE id = ${executorId}
|
|
1904
|
+
`;if(execRows.length===0)return!1;return execRows[0].closed_at!==null||execRows[0].outcome!==null}catch{return!1}}async function handleDeadPane(deps,config,daemonId,worker,turnAware,mode){if(mode==="boot"){if(turnAware&&await isLegitimatelyClosed(deps,worker))return deps.log({timestamp:deps.now().toISOString(),level:"debug",event:"agent_resume_skipped_boot_terminal",daemon_id:daemonId,agent_id:worker.id,reason:"executor_already_closed"}),"skipped";return await attemptAgentResume(deps,config,worker)==="resumed"?"resumed":"skipped"}if(turnAware&&worker.state==="idle"){let res=await terminalizeCleanExitUnverified(deps,worker,"reconciler_idle_dead_pane");if(res.terminalized)return deps.log({timestamp:deps.now().toISOString(),level:"warn",event:"agent_terminalized_clean_exit_unverified",daemon_id:daemonId,agent_id:worker.id,executor_id:res.executorId,reason:"idle_dead_pane"}),"terminalized";return"skipped"}if(turnAware&&!TURN_AWARE_RESUMABLE_STATES.has(worker.state))return deps.log({timestamp:deps.now().toISOString(),level:"debug",event:"agent_resume_skipped_turn_aware",daemon_id:daemonId,agent_id:worker.id,state:worker.state,reason:"state_not_in_d3"}),"skipped";return await attemptAgentResume(deps,config,worker)==="resumed"?"resumed":"skipped"}function handleRecoveryProbeError(deps,daemonId,workerId,err){let message=err instanceof Error?err.message:String(err);if(message.includes("no server running")||message.includes("server exited")||message.includes("error connecting"))return deps.log({timestamp:deps.now().toISOString(),level:"debug",event:"recovery_worker_skipped_tmux_down",daemon_id:daemonId,worker_id:workerId}),!0;return deps.log({timestamp:deps.now().toISOString(),level:"warn",event:"recovery_worker_failed",daemon_id:daemonId,worker_id:workerId,error:message}),!1}async function runAgentRecoveryPass(deps,daemonId,config,mode="sweep"){let resolvedConfig=config??resolveConfig(),resumable=(await deps.listWorkers()).filter((w)=>w.state!=="suspended"&&w.state!=="done"&&w.claudeSessionId),turnAware=isTurnAwareReconcilerEnabled(),resumed=0,failed=0,terminalized=0;for(let worker of resumable)try{if(await deps.isPaneAlive(worker.paneId))continue;let outcome=await handleDeadPane(deps,resolvedConfig,daemonId,worker,turnAware,mode);if(outcome==="resumed")resumed++;else if(outcome==="terminalized")terminalized++}catch(err){if(handleRecoveryProbeError(deps,daemonId,worker.id,err))continue;failed++}return{resumed,failed,terminalized}}async function terminalizeCleanExitUnverified(deps,worker,reason){let nowIso=deps.now().toISOString();try{return await(await deps.getConnection()).begin(async(tx)=>{let executorId=(await tx`SELECT current_executor_id FROM agents WHERE id = ${worker.id}`)[0]?.current_executor_id??null;if(!executorId)return await tx`
|
|
1901
1905
|
UPDATE agents
|
|
1902
1906
|
SET state = 'error',
|
|
1903
1907
|
last_state_change = ${nowIso}
|
|
@@ -2612,6 +2616,15 @@ ${label} <TODO>
|
|
|
2612
2616
|
${p.actor},
|
|
2613
2617
|
${tx.json({agent_id:p.agentId,outcome:p.outcome,reason:p.reason})}
|
|
2614
2618
|
)
|
|
2619
|
+
`}async function terminalizeAgentRows(tx,agentId){let ident=(await tx`
|
|
2620
|
+
UPDATE agents
|
|
2621
|
+
SET state = 'done', current_executor_id = NULL
|
|
2622
|
+
WHERE id = ${agentId}
|
|
2623
|
+
RETURNING custom_name, team
|
|
2624
|
+
`)[0];if(!ident?.custom_name||!ident?.team||ident.custom_name===agentId)return;await tx`
|
|
2625
|
+
UPDATE agents
|
|
2626
|
+
SET state = 'done', current_executor_id = NULL
|
|
2627
|
+
WHERE id = ${ident.custom_name} AND team = ${ident.team}
|
|
2615
2628
|
`}async function turnClose(opts){if((opts.outcome==="blocked"||opts.outcome==="failed")&&!opts.reason?.trim())throw Error(`turnClose: --reason is required for outcome '${opts.outcome}'`);let executorId=resolveExecutorId(opts),actor=opts.actor??process.env.GENIE_AGENT_NAME??"cli",reason=opts.reason?.trim()||null,auditInsert=opts.auditInsert??defaultAuditInsert;return(await getConnection()).begin(async(tx)=>{let effectiveId=executorId,rows=await tx`
|
|
2616
2629
|
SELECT state, outcome, agent_id FROM executors
|
|
2617
2630
|
WHERE id = ${executorId}
|
|
@@ -2634,11 +2647,7 @@ ${label} <TODO>
|
|
|
2634
2647
|
state = 'done',
|
|
2635
2648
|
ended_at = ${now}
|
|
2636
2649
|
WHERE id = ${effectiveId}
|
|
2637
|
-
`,await tx`
|
|
2638
|
-
UPDATE agents
|
|
2639
|
-
SET current_executor_id = NULL
|
|
2640
|
-
WHERE current_executor_id = ${effectiveId}
|
|
2641
|
-
`,await auditInsert(tx,{executorId:effectiveId,agentId:row.agent_id,outcome:opts.outcome,reason,actor}),{noop:!1,executorId:effectiveId,outcome:opts.outcome,closedAt:now}})}var TERMINAL_STATES;var init_turn_close=__esm(()=>{init_db();init_emit();TERMINAL_STATES=new Set(["done","terminated","error"])});var exports_done={};__export(exports_done,{doneAction:()=>doneAction});async function doneAction(ref,deps={}){let agentName=process.env.GENIE_AGENT_NAME;if(!ref&&agentName){let result2=await(deps.turnCloseFn??turnClose)({outcome:"done"});if(result2.noop)console.log(`\u2139\uFE0F Executor ${result2.executorId} already closed \u2014 no-op.`);else console.log(`\u2705 Turn closed: outcome=done, executor=${result2.executorId}`);return}if(ref){await(deps.wishDone??(async(r)=>{let{doneCommand:doneCommand2}=await Promise.resolve().then(() => (init_state(),exports_state));await doneCommand2(r)}))(ref);return}console.error("\u274C genie done requires either a <slug>#<group> ref (team-lead) or GENIE_AGENT_NAME (inside agent session)."),process.exit(2)}var init_done=__esm(()=>{init_turn_close()});var exports_blocked={};__export(exports_blocked,{blockedAction:()=>blockedAction});async function blockedAction(options,deps={}){let reason=options.reason?.trim();if(!reason)console.error('\u274C genie blocked requires --reason "<message>"'),process.exit(2);let result2=await(deps.turnCloseFn??turnClose)({outcome:"blocked",reason});if(result2.noop)console.log(`\u2139\uFE0F Executor ${result2.executorId} already closed \u2014 no-op.`);else console.log(`\uD83D\uDD12 Turn closed: outcome=blocked, executor=${result2.executorId}`),console.log(` Reason: ${reason}`)}var init_blocked=__esm(()=>{init_turn_close()});var exports_failed={};__export(exports_failed,{failedAction:()=>failedAction});async function failedAction(options,deps={}){let reason=options.reason?.trim();if(!reason)console.error('\u274C genie failed requires --reason "<message>"'),process.exit(2);let result2=await(deps.turnCloseFn??turnClose)({outcome:"failed",reason});if(result2.noop)console.log(`\u2139\uFE0F Executor ${result2.executorId} already closed \u2014 no-op.`);else console.log(`\uD83D\uDED1 Turn closed: outcome=failed, executor=${result2.executorId}`),console.log(` Reason: ${reason}`)}var init_failed=__esm(()=>{init_turn_close()});async function resolveExecutorId2(sql,opts){if(opts.executorId)return{id:opts.executorId,source:"executorId"};if(opts.paneId){let rows=await sql`
|
|
2650
|
+
`,await terminalizeAgentRows(tx,row.agent_id),await auditInsert(tx,{executorId:effectiveId,agentId:row.agent_id,outcome:opts.outcome,reason,actor}),{noop:!1,executorId:effectiveId,outcome:opts.outcome,closedAt:now}})}var TERMINAL_STATES;var init_turn_close=__esm(()=>{init_db();init_emit();TERMINAL_STATES=new Set(["done","terminated","error"])});var exports_done={};__export(exports_done,{doneAction:()=>doneAction});async function doneAction(ref,deps={}){let agentName=process.env.GENIE_AGENT_NAME;if(!ref&&agentName){let result2=await(deps.turnCloseFn??turnClose)({outcome:"done"});if(result2.noop)console.log(`\u2139\uFE0F Executor ${result2.executorId} already closed \u2014 no-op.`);else console.log(`\u2705 Turn closed: outcome=done, executor=${result2.executorId}`);return}if(ref){await(deps.wishDone??(async(r)=>{let{doneCommand:doneCommand2}=await Promise.resolve().then(() => (init_state(),exports_state));await doneCommand2(r)}))(ref);return}console.error("\u274C genie done requires either a <slug>#<group> ref (team-lead) or GENIE_AGENT_NAME (inside agent session)."),process.exit(2)}var init_done=__esm(()=>{init_turn_close()});var exports_blocked={};__export(exports_blocked,{blockedAction:()=>blockedAction});async function blockedAction(options,deps={}){let reason=options.reason?.trim();if(!reason)console.error('\u274C genie blocked requires --reason "<message>"'),process.exit(2);let result2=await(deps.turnCloseFn??turnClose)({outcome:"blocked",reason});if(result2.noop)console.log(`\u2139\uFE0F Executor ${result2.executorId} already closed \u2014 no-op.`);else console.log(`\uD83D\uDD12 Turn closed: outcome=blocked, executor=${result2.executorId}`),console.log(` Reason: ${reason}`)}var init_blocked=__esm(()=>{init_turn_close()});var exports_failed={};__export(exports_failed,{failedAction:()=>failedAction});async function failedAction(options,deps={}){let reason=options.reason?.trim();if(!reason)console.error('\u274C genie failed requires --reason "<message>"'),process.exit(2);let result2=await(deps.turnCloseFn??turnClose)({outcome:"failed",reason});if(result2.noop)console.log(`\u2139\uFE0F Executor ${result2.executorId} already closed \u2014 no-op.`);else console.log(`\uD83D\uDED1 Turn closed: outcome=failed, executor=${result2.executorId}`),console.log(` Reason: ${reason}`)}var init_failed=__esm(()=>{init_turn_close()});async function resolveExecutorId2(sql,opts){if(opts.executorId)return{id:opts.executorId,source:"executorId"};if(opts.paneId){let rows=await sql`
|
|
2642
2651
|
SELECT id FROM executors
|
|
2643
2652
|
WHERE tmux_pane_id = ${opts.paneId}
|
|
2644
2653
|
ORDER BY started_at DESC
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genie",
|
|
3
|
-
"version": "4.260421.
|
|
3
|
+
"version": "4.260421.8",
|
|
4
4
|
"description": "Human-AI partnership for Claude Code. Share a terminal, orchestrate workers, evolve together. Brainstorm ideas, turn them into wishes, execute with /work, validate with /review, and ship as one team.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Namastex Labs"
|