cctally 1.115.0 → 1.116.0

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.
Files changed (55) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/bin/_cctally_cache.py +85 -4
  3. package/bin/_cctally_completion.py +80 -12
  4. package/bin/_cctally_core.py +106 -9
  5. package/bin/_cctally_dashboard.py +6 -9
  6. package/bin/_cctally_dashboard_envelope.py +26 -32
  7. package/bin/_cctally_db.py +85 -4
  8. package/bin/_cctally_doctor.py +38 -5
  9. package/bin/_cctally_five_hour.py +83 -1017
  10. package/bin/_cctally_journal.py +1307 -180
  11. package/bin/_cctally_journal_repair.py +9 -7
  12. package/bin/_cctally_oauth_samples.py +280 -0
  13. package/bin/_cctally_parser.py +5 -0
  14. package/bin/_cctally_quarantine.py +14 -4
  15. package/bin/_cctally_quota.py +70 -8
  16. package/bin/_cctally_quota_model.py +35 -4
  17. package/bin/_cctally_record.py +414 -123
  18. package/bin/_cctally_rederive.py +632 -235
  19. package/bin/_cctally_refresh.py +29 -0
  20. package/bin/_cctally_statusline.py +984 -47
  21. package/bin/_cctally_store.py +972 -58
  22. package/bin/_cctally_tui.py +62 -7
  23. package/bin/_cctally_update.py +25 -0
  24. package/bin/_lib_account_protocol.py +201 -18
  25. package/bin/_lib_clone_copy.py +46 -11
  26. package/bin/_lib_dashboard_sources.py +57 -15
  27. package/bin/_lib_detector_access_registry.py +273 -52
  28. package/bin/_lib_doctor.py +302 -1
  29. package/bin/_lib_journal.py +145 -25
  30. package/bin/_lib_journal_router.py +166 -48
  31. package/bin/_lib_oauth_samples.py +238 -0
  32. package/bin/_lib_pricing_check.py +0 -12
  33. package/bin/_lib_provider_activity.py +770 -0
  34. package/bin/_lib_quarantine.py +3 -2
  35. package/bin/_lib_quota_model.py +96 -6
  36. package/bin/_lib_rebuild_progress.py +146 -0
  37. package/bin/_lib_record.py +22 -0
  38. package/bin/_lib_rederive.py +299 -3
  39. package/bin/_lib_snapshot_cache.py +43 -1
  40. package/bin/_lib_stale_proof.py +708 -0
  41. package/bin/_lib_statusline_candidates.py +65 -5
  42. package/bin/_lib_worker_launches.py +315 -0
  43. package/bin/cctally +6 -11
  44. package/dashboard/static/assets/{ConversationsView-Bc8LCOAZ.js → ConversationsView-Dflb_myA.js} +1 -1
  45. package/dashboard/static/assets/DoctorModal-DFX5CfIs.js +1 -0
  46. package/dashboard/static/assets/{ModalRoot-DLPgyAM_.js → ModalRoot-HlxoagIa.js} +1 -1
  47. package/dashboard/static/assets/{ProjectsDrillPanel-z53a4v4M.js → ProjectsDrillPanel-C3PJy1xx.js} +1 -1
  48. package/dashboard/static/assets/{SourceDetailModal-Bw0T8W-W.js → SourceDetailModal-BczsWKhD.js} +1 -1
  49. package/dashboard/static/assets/{UpdateModal-D5AKx4Yw.js → UpdateModal-Os-Lo5cs.js} +1 -1
  50. package/dashboard/static/assets/{index-BXDOzSng.js → index-CYZ3NLqF.js} +3 -3
  51. package/dashboard/static/assets/{outlineNavigation-JObY7cUY.js → outlineNavigation-k-zIif6W.js} +1 -1
  52. package/dashboard/static/dashboard.html +1 -1
  53. package/package.json +7 -2
  54. package/bin/_lib_merge_gate.py +0 -452
  55. package/dashboard/static/assets/DoctorModal-D--qVBwe.js +0 -1
@@ -1,4 +1,4 @@
1
- import{Ft as e,Rt as t,_t as n,ft as r,ht as i}from"./useKeymap-CW7Up0Ay.js";import{Ft as a}from"./index-BXDOzSng.js";var o=t(e(),1),s=class extends Error{status;constructor(e){super(`HTTP ${e}`),this.status=e,this.name=`HttpError`}};function c(e){return e?.name===`AbortError`}async function l(e,t){let n=await fetch(e,t?{signal:t}:void 0);if(!n.ok)throw new s(n.status);return await n.json()}function u(e){let t=e?.data_version;return typeof t==`string`&&t!==``?t:e?.generated_at??``}var d={legacy_bridge_pending:{reason:`legacy_bridge_pending`,message:`Transcripts have not finished moving into the conversation store. Run cctally cache-sync to finish the import.`,retryable:!1},maintenance:{reason:`maintenance`,message:`The conversation store is busy with maintenance. Conversations return once it finishes.`,retryable:!0},schema_behind:{reason:`schema_behind`,message:`The conversation store is behind this version of cctally. Run cctally cache-sync to bring it up to date.`,retryable:!1},schema_ahead:{reason:`schema_ahead`,message:`The conversation store was written by a newer version of cctally. Update cctally to read it.`,retryable:!1}},f={reason:`unavailable`,message:`The conversation store is not available right now.`,retryable:!0};function p(e){if(typeof e!=`object`||!e)return null;let t=e;return t.status===`degraded`?typeof t.degraded_reason==`string`&&t.degraded_reason?t.degraded_reason:f.reason:null}function m(e){return d[e]??{...f,reason:e||f.reason}}function h(e,t,n){n!==void 0&&e.append(t,String(n))}function g(e,t={}){let n=new URLSearchParams;return n.append(`source`,e),h(n,`account`,t.accountKey),h(n,`project_key`,t.projectKey),h(n,`model`,t.model),h(n,`limit`,t.limit),h(n,`cursor`,t.cursor),h(n,`selected`,t.selected),`/api/conversations?${n.toString()}`}function _(e,t){let n=new URLSearchParams({source:e});return h(n,`account`,t),`/api/conversations/facets?${n.toString()}`}function v(e,t){let n=new URLSearchParams;return n.append(`source`,e),h(n,`account`,t.accountKey),n.append(`q`,t.query),h(n,`kind`,t.kind),h(n,`limit`,t.limit),h(n,`cursor`,t.cursor),`/api/conversation/search?${n.toString().replace(/\+/g,`%20`)}`}var y={detail:``,outline:`/outline`,find:`/find`,prompts:`/prompts`,payload:`/payload`,export:`/export`,"anon-map":`/anon-map`,events:`/events`,media:`/media`};function b(e,t,r){let i=n(e);if(i.source===`codex`&&!i.key.startsWith(`v1.`))throw Error(`Codex conversation keys must be qualified`);let a=new URLSearchParams;h(a,`account`,i.account_key);for(let[e,t]of Object.entries(r??{}))t!==void 0&&a.append(e,typeof t==`boolean`?t?`1`:`0`:String(t));let o=a.size?`?${a.toString().replace(/\+/g,`%20`)}`:``;return`/api/conversation/${encodeURIComponent(i.key)}${y[t]}${o}`}function x(e){let t=e.native_card;return t?.type===`session_ref`?t.scope===`shell`&&t.ref!=null?[t.ref]:[]:t?.type===`program`?t.invocations.flatMap(e=>e.kind===`session`&&e.scope===`shell`&&e.ref!=null?[e.ref]:[]):[]}function S(e,t){return t==null?``:e===`shell`?`session ${t}`:`cell ${t}`}function C(e,t){return t==null?``:e===`shell`?`s${t}`:`c${t}`}function w(e){return e===`write`?`wrote to`:`polled`}function T(e){return e===`write`?`wrote`:`poll`}var E=60;function D(e){let t=e.replace(/\s+/g,` `).trim();return t.length>E?`${t.slice(0,E)}…`:t}function O(e){let t=new Set(e.flatMap(e=>x(e)));return t.size===1?[...t][0]:null}function k(e,t,n,r){if(!e||t!==`shell`||n==null)return`silent`;let i=e.sessions[n];return i?.opener_block_key==null?e.truncated?`index_truncated`:`not_retained`:r!=null&&r===i.opener_block_key?`opener`:`silent`}function A(e){return new Set(e.map(e=>e.parent_uuid))}function j(e){let t=new Map;for(let n of e){let e=t.get(n.parent_uuid);e?e.push(n):t.set(n.parent_uuid,[n])}return t}function M(e){return e.kind===`reasoning`?e.landmark_key:e.block_key}var N={tool_error:`error`,plan:`plan`,reasoning:`heading`};function P(e,t){if(!t?.length)return[];let n=j(t),r=[];return e.forEach((e,t)=>{for(let i of n.get(e.uuid)??[])r.push({landmark:i,ownerTurnIndex:t})}),r}var F=class extends Error{constructor(){super(`Conversation indexing is still finishing.`)}},I=class extends Error{reason;constructor(e){let t=m(e);super(t.message),this.name=`ConversationDegraded`,this.reason=t.reason}};function L(e){return typeof e==`number`&&Number.isFinite(e)?e:0}function ee(e){return typeof e==`number`&&Number.isFinite(e)?e:null}function R(e){if(e)return e.source===`codex`||`cached_input`in e||`reasoning_output`in e?{source:`codex`,input:L(e.input),output:L(e.output),cache_creation:0,cache_read:0,cached_input:L(e.cached_input),reasoning_output:L(e.reasoning_output)}:{source:`claude`,input:L(e.input),output:L(e.output),cache_creation:L(e.cache_creation??e.cache_create),cache_read:L(e.cache_read)}}function te(e){let t=2166136261;for(let n=0;n<e.length;n++)t^=e.charCodeAt(n),t=Math.imul(t,16777619);return t>>>0||1}function z(e){if(typeof e!=`string`||e.trim()===``)return null;try{let t=JSON.parse(e);return t&&typeof t==`object`&&!Array.isArray(t)?t:{value:t}}catch{return{raw:e}}}var ne=new Set([`create_branch`,`stage`,`commit`,`push`,`create_pr`]);function B(e){return typeof e==`string`&&e.trim()!==``?e.trim():void 0}function re(e){if(!Array.isArray(e)||e.length===0)return;let t=[];for(let n of e){let e=V(n);if(!e||typeof e.key!=`string`||typeof e.text!=`string`)return;t.push({key:e.key,text:e.text})}return t}function ie(e){let t=V(e.detail?.reasoning);if(t?.schema_version===1){let n=B(t.title),r=B(t.summary),i=B(t.body);if(!n&&!r&&!i)return null;let a=re(t.headings);return{kind:`codex_reasoning`,source:B(t.source)??`codex`,title:n,summary:r,body:i,...a?{headings:a}:{},...e.block_key?{block_key:e.block_key}:{}}}let n=B(e.text);return n?{kind:`codex_reasoning`,source:`codex`,body:n,...e.block_key?{block_key:e.block_key}:{}}:null}function ae(e){if(!Array.isArray(e)||e.length===0)return null;let t=[];for(let n of e){let e=V(n);if(!e||e.schema_version!==1)return null;if(e.type===`git`&&typeof e.action==`string`&&ne.has(e.action)){t.push({type:`git`,action:e.action,...e.action===`create_pr`&&typeof e.draft==`boolean`?{draft:e.draft}:{}});continue}if(e.type===`memory_citation`&&Number.isSafeInteger(e.citation_count)&&Number(e.citation_count)>=0&&Number.isSafeInteger(e.rollout_count)&&Number(e.rollout_count)>=0){t.push({type:`memory_citation`,citation_count:Number(e.citation_count),rollout_count:Number(e.rollout_count)});continue}return null}return t}function oe(e){let t=V(e.detail?.lifecycle);return t?.schema_version!==1||t.event!==`task_started`&&t.event!==`task_complete`?null:{kind:`codex_lifecycle`,event:t.event,...B(t.message)?{message:B(t.message)}:{},...B(t.error)?{error:B(t.error)}:{},...typeof t.duration_ms==`number`&&Number.isFinite(t.duration_ms)?{duration_ms:t.duration_ms}:{},...e.block_key?{payload_key:e.block_key}:{}}}function V(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:null}function se(e){if(!Array.isArray(e))return null;let t=[];for(let n of e){let e=V(n);if(!e)return null;let r={};for(let t of[`path`,`move_path`,`status`])typeof e[t]==`string`&&(r[t]=e[t]);t.push(r)}return t}function ce(e){if(!Array.isArray(e))return null;let t=[];for(let n of e){let e=V(n);if(!e)return null;let r={};for(let t of[`path`,`move_path`,`status`,`unified_diff`,`raw`,`raw_extra`])typeof e[t]==`string`&&(r[t]=e[t]);typeof e.truncated==`boolean`&&(r.truncated=e.truncated),(e.diff_source===`retained`||e.diff_source===`derived`)&&(r.diff_source=e.diff_source),t.push(r)}return t}function H(e){let t=V(e);if(t?.schema_version!==1||t.type!==`terminal_output`||!Array.isArray(t.parts))return;let n=t.parts.map(e=>{let t=V(e);if(!t||t.type!==`text`&&t.type!==`raw`||typeof t.text!=`string`)return null;let n=t.stream===`stdout`||t.stream===`stderr`?t.stream:`output`;return{type:t.type,stream:n,text:t.text}});if(!n.some(e=>e==null))return{schema_version:1,type:`terminal_output`,status:typeof t.status==`string`?t.status:`unknown`,is_error:t.is_error===!0,parts:n,truncated:t.truncated===!0,...typeof t.exit_code==`number`||t.exit_code===null?{exit_code:t.exit_code}:{},...typeof t.wall_time_seconds==`number`||t.wall_time_seconds===null?{wall_time_seconds:t.wall_time_seconds}:{}}}var le=new Set([`completed`,`failed`,`error`,`running`,`unknown`]),U=new Set([`failed`,`error`]);function ue(e){if(e)return{status:le.has(e.status)?e.status:`unknown`,exit_code:typeof e.exit_code==`number`?e.exit_code:null,wall_time_seconds:typeof e.wall_time_seconds==`number`?e.wall_time_seconds:null}}function de(e){if(!Array.isArray(e)||e.length===0)return;let t=[];for(let n of e){let e=V(n);if(!e)return;if(e.kind===`command`){if(typeof e.command!=`string`)return;t.push({kind:`command`,command:e.command,workdir:typeof e.workdir==`string`?e.workdir:null,metadata:V(e.metadata)??{}});continue}if(e.kind===`session`){if(e.scope!==`shell`&&e.scope!==`cell`||e.operation!==`write`&&e.operation!==`poll`)return;t.push({kind:`session`,scope:e.scope,operation:e.operation,ref:typeof e.ref==`string`?e.ref:null,chars:typeof e.chars==`string`?e.chars:null});continue}if(e.kind===`other`&&typeof e.name==`string`&&e.name!==``){t.push({kind:`other`,name:e.name});continue}return}return t}function fe(e){let t=de(e.invocations);if(!(!t||typeof e.complete!=`boolean`||typeof e.truncated!=`boolean`))return{schema_version:1,type:`program`,title:typeof e.title==`string`?e.title:null,complete:e.complete,invocations:t,truncated:e.truncated}}function pe(e){if(!(e.scope!==`shell`&&e.scope!==`cell`||e.operation!==`write`&&e.operation!==`poll`||typeof e.truncated!=`boolean`))return{schema_version:1,type:`session_ref`,scope:e.scope,operation:e.operation,ref:typeof e.ref==`string`?e.ref:null,chars:typeof e.chars==`string`?e.chars:null,truncated:e.truncated}}function me(e){if(typeof e.query==`string`)return{schema_version:1,type:`tool_search`,query:e.query,limit:typeof e.limit==`number`&&Number.isFinite(e.limit)?e.limit:null,...e.truncated===!0?{truncated:!0}:{}}}function he(e){let t=V(e),n=V(t?.sessions);if(!t||!n||typeof t.truncated!=`boolean`)return;let r=Object.create(null);for(let[e,t]of Object.entries(n)){let n=V(t);if(!n||!Number.isSafeInteger(n.ordinal)||n.opener_block_key!==null&&typeof n.opener_block_key!=`string`)return;r[e]={ordinal:n.ordinal,opener_block_key:n.opener_block_key}}return{sessions:r,truncated:t.truncated}}function ge(e){let t=V(e);if(t?.schema_version!==1||typeof t.name!=`string`||t.name===``||!(`input`in t)||typeof t.truncated!=`boolean`)return null;let n=t.span,r=Array.isArray(n)&&n.length===2&&Number.isSafeInteger(n[0])&&Number.isSafeInteger(n[1])&&n[0]>=0&&n[1]>=n[0]?[n[0],n[1]]:null;return{block:{kind:`external_call`,name:t.name,input:t.input,truncated:t.truncated},span:r}}function _e(e){let t=V(e);return!t||typeof t.status!=`string`||typeof t.truncated!=`boolean`||!(`value`in t)?null:{status:t.status,value:t.value,truncated:t.truncated}}function ve(e){if(e.source!==`update_plan`||typeof e.call_status!=`string`||!Array.isArray(e.items))return;let t=e.items.map(e=>{let t=V(e);return t&&typeof t.step==`string`&&typeof t.status==`string`?{step:t.step,status:t.status}:null}),n=e.result===void 0?void 0:_e(e.result);if(!(t.some(e=>e==null)||e.result!==void 0&&!n))return{schema_version:1,type:`plan`,source:`update_plan`,call_status:e.call_status,explanation:typeof e.explanation==`string`?e.explanation:null,items:t,...n?{result:n}:{}}}function ye(e){let t=V(e.completion);if(e.source!==`web_search_call`||typeof e.call_status!=`string`||typeof e.query!=`string`||!V(e.action)||!t||typeof t.status!=`string`||typeof t.query!=`string`||!V(t.action)||!Array.isArray(t.results))return;let n=t.results.map(e=>{let t=V(e);return!t||typeof t.title!=`string`||typeof t.url!=`string`?null:{title:t.title,url:t.url,...typeof t.domain==`string`?{domain:t.domain}:{},...typeof t.snippet==`string`?{snippet:t.snippet}:{},...typeof t.ref_id==`string`?{ref_id:t.ref_id}:{},...typeof t.type==`string`?{type:t.type}:{}}});if(!n.some(e=>e==null))return{schema_version:1,type:`web_search`,source:`web_search_call`,call_status:e.call_status,query:e.query,action:V(e.action),completion:{status:t.status,query:t.query,action:V(t.action),results:n,...typeof t.error==`string`?{error:t.error}:{},...typeof t.event_block_key==`string`?{event_block_key:t.event_block_key}:{}}}}function be(e){let t=V(e.completion),n=V(t?.duration);if(!(e.source!==`function_call`||typeof e.name!=`string`||typeof e.call_status!=`string`||!t||typeof t.status!=`string`||typeof t.server!=`string`||typeof t.tool!=`string`||!V(t.arguments)||!V(t.result)||!n||typeof n.secs!=`number`||!Number.isFinite(n.secs)||typeof n.nanos!=`number`||!Number.isFinite(n.nanos)))return{schema_version:1,type:`mcp`,source:`function_call`,name:e.name,call_status:e.call_status,completion:{status:t.status,server:t.server,tool:t.tool,arguments:V(t.arguments),result:V(t.result),duration:{secs:n.secs,nanos:n.nanos},...typeof t.event_block_key==`string`?{event_block_key:t.event_block_key}:{}}}}var xe=new Set([`spawn_agent`,`wait_agent`,`send_message`,`list_agents`,`followup_task`,`interrupt_agent`]);function Se(e){let t=typeof e.operation==`string`&&xe.has(e.operation)?e.operation:null,n=V(e.arguments),r=e.result===void 0?void 0:_e(e.result),i=e.child_conversation==null?null:V(e.child_conversation);if(!(!t||typeof e.call_status!=`string`||!n||e.result!==void 0&&!r||e.child_conversation!=null&&!i)&&!(i&&typeof i.conversation_key!=`string`))return{schema_version:1,type:`agent`,operation:t,call_status:e.call_status,arguments:n,...r?{result:r}:{},...i?{child_conversation:{conversation_key:i.conversation_key,...typeof i.role==`string`?{role:i.role}:{},...typeof i.nickname==`string`?{nickname:i.nickname}:{}}}:{}}}function W(e){let t=V(e.detail?.card);if(t?.schema_version!==1)return;if(t.type===`terminal`){if(!Array.isArray(t.commands)||t.commands.length===0)return;let n=t.commands.map(e=>{let t=V(e);return!t||typeof t.command!=`string`?null:{command:t.command,workdir:typeof t.workdir==`string`?t.workdir:null,metadata:V(t.metadata)??{}}});return n.some(e=>e==null)?void 0:{schema_version:1,type:`terminal`,status:typeof t.status==`string`?t.status:`unknown`,commands:n,output:H(e.output?.detail?.card),truncated:t.truncated===!0||e.output?.detail?.card!=null&&V(e.output.detail.card)?.truncated===!0}}if(t.type===`plan`)return ve(t);if(t.type===`web_search`)return ye(t);if(t.type===`mcp`)return be(t);if(t.type===`agent`)return Se(t);if(t.type===`program`)return fe(t);if(t.type===`session_ref`)return pe(t);if(t.type===`tool_search`)return me(t);if(t.type!==`patch`)return;let n=se(t.files);if(n==null)return;let r=V(t.completion),i=r?.schema_version===1&&r.type===`patch`?r:t,a=ce(i.files);if(a!=null)return{schema_version:1,type:`patch`,source:typeof t.source==`string`?t.source:`patch_apply_end`,status:typeof i.status==`string`?i.status:`unknown`,files:a,request_files:r?n:void 0,patch:typeof t.patch==`string`?t.patch:void 0,success:typeof i.success==`boolean`?i.success:null,stdout:typeof i.stdout==`string`?i.stdout:null,stderr:typeof i.stderr==`string`?i.stderr:null,has_diff:typeof i.has_diff==`boolean`?i.has_diff:a.some(e=>typeof e.unified_diff==`string`),truncated:t.truncated===!0||i.truncated===!0,event_payload_key:typeof i.event_block_key==`string`?i.event_block_key:void 0}}function Ce(e){let t=e[0],n=t.kind===`command`?t.command:t.kind===`session`?[w(t.operation),S(t.scope,t.ref)].filter(Boolean).join(` `):t.name;return e.length>1?`${n} +${e.length-1} more`:n}function we(e){return[S(e.scope,e.ref),e.chars==null?``:D(e.chars)].filter(Boolean).join(` · `)||e.operation}function G(e){if(e)return e.replace(/^\[((?:\$)[^\]\r\n]+)\]\([^\)\r\n]*\/SKILL\.md\)[ \t]*/,(e,t,n,r)=>n+e.length<r.length?`${t} `:t)}function Te(e,t){let n=[];for(let r of e){if(r.kind===`assistant`||r.kind===`user`||r.kind===`text`){let e=r.kind===`assistant`?ge(r.detail?.external_call):null,t=e?.span!=null&&r.text!=null&&e.span[1]<=r.text.length?e.span:null,i=t?`${r.text.slice(0,t[0])}${r.text.slice(t[1])}`.replace(/[ \t]*\n+$/,``):r.text;i&&n.push({kind:`text`,text:i,...r.block_key?{block_key:r.block_key}:{}}),e&&t&&n.push({...e.block,...r.block_key?{block_key:r.block_key}:{}});let a=ae(r.detail?.markers);a&&n.push({kind:`system_actions`,actions:a,...r.block_key?{payload_key:r.block_key}:{}});continue}if(r.kind===`thinking`){r.text?.trim()&&n.push({kind:`thinking`,text:r.text});continue}if(r.kind===`reasoning`){if(t===`codex`){let e=ie(r);e&&n.push(e)}else r.text?.trim()&&n.push({kind:`thinking`,text:r.text});continue}if(r.kind===`tool_call`){let e=r;if(t===`claude`&&r.detail==null&&typeof e.input_summary==`string`&&typeof e.preview==`string`&&`result`in e){n.push(e);continue}let i=typeof r.detail?.name==`string`?r.detail.name:null,a=typeof r.detail?.args==`string`?r.detail.args:``,o=W(r),s=o?.type===`terminal`?o:null,c=o?.type===`patch`?o:null,l=o?.type===`plan`?o:null,u=o?.type===`web_search`?o:null,d=o?.type===`mcp`?o:null,f=o?.type===`agent`?o:null,p=o?.type===`program`?o:null,m=o?.type===`session_ref`?o:null,h=o?.type===`tool_search`?o:null,g=s?{command:s.commands[0].command,workdir:s.commands[0].workdir}:u?{query:u.query,action:u.action}:d?d.completion.arguments:f?f.arguments:z(a),_=t===`codex`?ue(H(r.output?.detail?.card)):void 0,v=s?.output?.is_error===!0||c?.success===!1||U.has(u?.completion.status??``)||U.has(d?.completion.status??``)||U.has(_?.status??``),y=B(l?.explanation)??B(u?.query)??(d?B(`${d.completion.tool} · ${d.completion.server}`):void 0)??(f?B(f.operation):void 0)??B(h?.query)??B(p?.title)??(p?B(Ce(p.invocations)):void 0)??(m?B(we(m)):void 0),b=l?.result?.value??u?.completion.error??d?.completion.result??f?.result?.value??null,x=typeof b==`string`?b:b==null?null:JSON.stringify(b,null,2);n.push({kind:`tool_call`,name:i,input_summary:s?JSON.stringify({commands:s.commands}):a||r.text||``,input:g,preview:s?.commands[0].command??c?.files.map(e=>e.move_path??e.path).filter(Boolean).join(`, `)??y??(r.text??a).split(`
1
+ import{Ft as e,Rt as t,_t as n,ft as r,ht as i}from"./useKeymap-CW7Up0Ay.js";import{Ft as a}from"./index-CYZ3NLqF.js";var o=t(e(),1),s=class extends Error{status;constructor(e){super(`HTTP ${e}`),this.status=e,this.name=`HttpError`}};function c(e){return e?.name===`AbortError`}async function l(e,t){let n=await fetch(e,t?{signal:t}:void 0);if(!n.ok)throw new s(n.status);return await n.json()}function u(e){let t=e?.data_version;return typeof t==`string`&&t!==``?t:e?.generated_at??``}var d={legacy_bridge_pending:{reason:`legacy_bridge_pending`,message:`Transcripts have not finished moving into the conversation store. Run cctally cache-sync to finish the import.`,retryable:!1},maintenance:{reason:`maintenance`,message:`The conversation store is busy with maintenance. Conversations return once it finishes.`,retryable:!0},schema_behind:{reason:`schema_behind`,message:`The conversation store is behind this version of cctally. Run cctally cache-sync to bring it up to date.`,retryable:!1},schema_ahead:{reason:`schema_ahead`,message:`The conversation store was written by a newer version of cctally. Update cctally to read it.`,retryable:!1}},f={reason:`unavailable`,message:`The conversation store is not available right now.`,retryable:!0};function p(e){if(typeof e!=`object`||!e)return null;let t=e;return t.status===`degraded`?typeof t.degraded_reason==`string`&&t.degraded_reason?t.degraded_reason:f.reason:null}function m(e){return d[e]??{...f,reason:e||f.reason}}function h(e,t,n){n!==void 0&&e.append(t,String(n))}function g(e,t={}){let n=new URLSearchParams;return n.append(`source`,e),h(n,`account`,t.accountKey),h(n,`project_key`,t.projectKey),h(n,`model`,t.model),h(n,`limit`,t.limit),h(n,`cursor`,t.cursor),h(n,`selected`,t.selected),`/api/conversations?${n.toString()}`}function _(e,t){let n=new URLSearchParams({source:e});return h(n,`account`,t),`/api/conversations/facets?${n.toString()}`}function v(e,t){let n=new URLSearchParams;return n.append(`source`,e),h(n,`account`,t.accountKey),n.append(`q`,t.query),h(n,`kind`,t.kind),h(n,`limit`,t.limit),h(n,`cursor`,t.cursor),`/api/conversation/search?${n.toString().replace(/\+/g,`%20`)}`}var y={detail:``,outline:`/outline`,find:`/find`,prompts:`/prompts`,payload:`/payload`,export:`/export`,"anon-map":`/anon-map`,events:`/events`,media:`/media`};function b(e,t,r){let i=n(e);if(i.source===`codex`&&!i.key.startsWith(`v1.`))throw Error(`Codex conversation keys must be qualified`);let a=new URLSearchParams;h(a,`account`,i.account_key);for(let[e,t]of Object.entries(r??{}))t!==void 0&&a.append(e,typeof t==`boolean`?t?`1`:`0`:String(t));let o=a.size?`?${a.toString().replace(/\+/g,`%20`)}`:``;return`/api/conversation/${encodeURIComponent(i.key)}${y[t]}${o}`}function x(e){let t=e.native_card;return t?.type===`session_ref`?t.scope===`shell`&&t.ref!=null?[t.ref]:[]:t?.type===`program`?t.invocations.flatMap(e=>e.kind===`session`&&e.scope===`shell`&&e.ref!=null?[e.ref]:[]):[]}function S(e,t){return t==null?``:e===`shell`?`session ${t}`:`cell ${t}`}function C(e,t){return t==null?``:e===`shell`?`s${t}`:`c${t}`}function w(e){return e===`write`?`wrote to`:`polled`}function T(e){return e===`write`?`wrote`:`poll`}var E=60;function D(e){let t=e.replace(/\s+/g,` `).trim();return t.length>E?`${t.slice(0,E)}…`:t}function O(e){let t=new Set(e.flatMap(e=>x(e)));return t.size===1?[...t][0]:null}function k(e,t,n,r){if(!e||t!==`shell`||n==null)return`silent`;let i=e.sessions[n];return i?.opener_block_key==null?e.truncated?`index_truncated`:`not_retained`:r!=null&&r===i.opener_block_key?`opener`:`silent`}function A(e){return new Set(e.map(e=>e.parent_uuid))}function j(e){let t=new Map;for(let n of e){let e=t.get(n.parent_uuid);e?e.push(n):t.set(n.parent_uuid,[n])}return t}function M(e){return e.kind===`reasoning`?e.landmark_key:e.block_key}var N={tool_error:`error`,plan:`plan`,reasoning:`heading`};function P(e,t){if(!t?.length)return[];let n=j(t),r=[];return e.forEach((e,t)=>{for(let i of n.get(e.uuid)??[])r.push({landmark:i,ownerTurnIndex:t})}),r}var F=class extends Error{constructor(){super(`Conversation indexing is still finishing.`)}},I=class extends Error{reason;constructor(e){let t=m(e);super(t.message),this.name=`ConversationDegraded`,this.reason=t.reason}};function L(e){return typeof e==`number`&&Number.isFinite(e)?e:0}function ee(e){return typeof e==`number`&&Number.isFinite(e)?e:null}function R(e){if(e)return e.source===`codex`||`cached_input`in e||`reasoning_output`in e?{source:`codex`,input:L(e.input),output:L(e.output),cache_creation:0,cache_read:0,cached_input:L(e.cached_input),reasoning_output:L(e.reasoning_output)}:{source:`claude`,input:L(e.input),output:L(e.output),cache_creation:L(e.cache_creation??e.cache_create),cache_read:L(e.cache_read)}}function te(e){let t=2166136261;for(let n=0;n<e.length;n++)t^=e.charCodeAt(n),t=Math.imul(t,16777619);return t>>>0||1}function z(e){if(typeof e!=`string`||e.trim()===``)return null;try{let t=JSON.parse(e);return t&&typeof t==`object`&&!Array.isArray(t)?t:{value:t}}catch{return{raw:e}}}var ne=new Set([`create_branch`,`stage`,`commit`,`push`,`create_pr`]);function B(e){return typeof e==`string`&&e.trim()!==``?e.trim():void 0}function re(e){if(!Array.isArray(e)||e.length===0)return;let t=[];for(let n of e){let e=V(n);if(!e||typeof e.key!=`string`||typeof e.text!=`string`)return;t.push({key:e.key,text:e.text})}return t}function ie(e){let t=V(e.detail?.reasoning);if(t?.schema_version===1){let n=B(t.title),r=B(t.summary),i=B(t.body);if(!n&&!r&&!i)return null;let a=re(t.headings);return{kind:`codex_reasoning`,source:B(t.source)??`codex`,title:n,summary:r,body:i,...a?{headings:a}:{},...e.block_key?{block_key:e.block_key}:{}}}let n=B(e.text);return n?{kind:`codex_reasoning`,source:`codex`,body:n,...e.block_key?{block_key:e.block_key}:{}}:null}function ae(e){if(!Array.isArray(e)||e.length===0)return null;let t=[];for(let n of e){let e=V(n);if(!e||e.schema_version!==1)return null;if(e.type===`git`&&typeof e.action==`string`&&ne.has(e.action)){t.push({type:`git`,action:e.action,...e.action===`create_pr`&&typeof e.draft==`boolean`?{draft:e.draft}:{}});continue}if(e.type===`memory_citation`&&Number.isSafeInteger(e.citation_count)&&Number(e.citation_count)>=0&&Number.isSafeInteger(e.rollout_count)&&Number(e.rollout_count)>=0){t.push({type:`memory_citation`,citation_count:Number(e.citation_count),rollout_count:Number(e.rollout_count)});continue}return null}return t}function oe(e){let t=V(e.detail?.lifecycle);return t?.schema_version!==1||t.event!==`task_started`&&t.event!==`task_complete`?null:{kind:`codex_lifecycle`,event:t.event,...B(t.message)?{message:B(t.message)}:{},...B(t.error)?{error:B(t.error)}:{},...typeof t.duration_ms==`number`&&Number.isFinite(t.duration_ms)?{duration_ms:t.duration_ms}:{},...e.block_key?{payload_key:e.block_key}:{}}}function V(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:null}function se(e){if(!Array.isArray(e))return null;let t=[];for(let n of e){let e=V(n);if(!e)return null;let r={};for(let t of[`path`,`move_path`,`status`])typeof e[t]==`string`&&(r[t]=e[t]);t.push(r)}return t}function ce(e){if(!Array.isArray(e))return null;let t=[];for(let n of e){let e=V(n);if(!e)return null;let r={};for(let t of[`path`,`move_path`,`status`,`unified_diff`,`raw`,`raw_extra`])typeof e[t]==`string`&&(r[t]=e[t]);typeof e.truncated==`boolean`&&(r.truncated=e.truncated),(e.diff_source===`retained`||e.diff_source===`derived`)&&(r.diff_source=e.diff_source),t.push(r)}return t}function H(e){let t=V(e);if(t?.schema_version!==1||t.type!==`terminal_output`||!Array.isArray(t.parts))return;let n=t.parts.map(e=>{let t=V(e);if(!t||t.type!==`text`&&t.type!==`raw`||typeof t.text!=`string`)return null;let n=t.stream===`stdout`||t.stream===`stderr`?t.stream:`output`;return{type:t.type,stream:n,text:t.text}});if(!n.some(e=>e==null))return{schema_version:1,type:`terminal_output`,status:typeof t.status==`string`?t.status:`unknown`,is_error:t.is_error===!0,parts:n,truncated:t.truncated===!0,...typeof t.exit_code==`number`||t.exit_code===null?{exit_code:t.exit_code}:{},...typeof t.wall_time_seconds==`number`||t.wall_time_seconds===null?{wall_time_seconds:t.wall_time_seconds}:{}}}var le=new Set([`completed`,`failed`,`error`,`running`,`unknown`]),U=new Set([`failed`,`error`]);function ue(e){if(e)return{status:le.has(e.status)?e.status:`unknown`,exit_code:typeof e.exit_code==`number`?e.exit_code:null,wall_time_seconds:typeof e.wall_time_seconds==`number`?e.wall_time_seconds:null}}function de(e){if(!Array.isArray(e)||e.length===0)return;let t=[];for(let n of e){let e=V(n);if(!e)return;if(e.kind===`command`){if(typeof e.command!=`string`)return;t.push({kind:`command`,command:e.command,workdir:typeof e.workdir==`string`?e.workdir:null,metadata:V(e.metadata)??{}});continue}if(e.kind===`session`){if(e.scope!==`shell`&&e.scope!==`cell`||e.operation!==`write`&&e.operation!==`poll`)return;t.push({kind:`session`,scope:e.scope,operation:e.operation,ref:typeof e.ref==`string`?e.ref:null,chars:typeof e.chars==`string`?e.chars:null});continue}if(e.kind===`other`&&typeof e.name==`string`&&e.name!==``){t.push({kind:`other`,name:e.name});continue}return}return t}function fe(e){let t=de(e.invocations);if(!(!t||typeof e.complete!=`boolean`||typeof e.truncated!=`boolean`))return{schema_version:1,type:`program`,title:typeof e.title==`string`?e.title:null,complete:e.complete,invocations:t,truncated:e.truncated}}function pe(e){if(!(e.scope!==`shell`&&e.scope!==`cell`||e.operation!==`write`&&e.operation!==`poll`||typeof e.truncated!=`boolean`))return{schema_version:1,type:`session_ref`,scope:e.scope,operation:e.operation,ref:typeof e.ref==`string`?e.ref:null,chars:typeof e.chars==`string`?e.chars:null,truncated:e.truncated}}function me(e){if(typeof e.query==`string`)return{schema_version:1,type:`tool_search`,query:e.query,limit:typeof e.limit==`number`&&Number.isFinite(e.limit)?e.limit:null,...e.truncated===!0?{truncated:!0}:{}}}function he(e){let t=V(e),n=V(t?.sessions);if(!t||!n||typeof t.truncated!=`boolean`)return;let r=Object.create(null);for(let[e,t]of Object.entries(n)){let n=V(t);if(!n||!Number.isSafeInteger(n.ordinal)||n.opener_block_key!==null&&typeof n.opener_block_key!=`string`)return;r[e]={ordinal:n.ordinal,opener_block_key:n.opener_block_key}}return{sessions:r,truncated:t.truncated}}function ge(e){let t=V(e);if(t?.schema_version!==1||typeof t.name!=`string`||t.name===``||!(`input`in t)||typeof t.truncated!=`boolean`)return null;let n=t.span,r=Array.isArray(n)&&n.length===2&&Number.isSafeInteger(n[0])&&Number.isSafeInteger(n[1])&&n[0]>=0&&n[1]>=n[0]?[n[0],n[1]]:null;return{block:{kind:`external_call`,name:t.name,input:t.input,truncated:t.truncated},span:r}}function _e(e){let t=V(e);return!t||typeof t.status!=`string`||typeof t.truncated!=`boolean`||!(`value`in t)?null:{status:t.status,value:t.value,truncated:t.truncated}}function ve(e){if(e.source!==`update_plan`||typeof e.call_status!=`string`||!Array.isArray(e.items))return;let t=e.items.map(e=>{let t=V(e);return t&&typeof t.step==`string`&&typeof t.status==`string`?{step:t.step,status:t.status}:null}),n=e.result===void 0?void 0:_e(e.result);if(!(t.some(e=>e==null)||e.result!==void 0&&!n))return{schema_version:1,type:`plan`,source:`update_plan`,call_status:e.call_status,explanation:typeof e.explanation==`string`?e.explanation:null,items:t,...n?{result:n}:{}}}function ye(e){let t=V(e.completion);if(e.source!==`web_search_call`||typeof e.call_status!=`string`||typeof e.query!=`string`||!V(e.action)||!t||typeof t.status!=`string`||typeof t.query!=`string`||!V(t.action)||!Array.isArray(t.results))return;let n=t.results.map(e=>{let t=V(e);return!t||typeof t.title!=`string`||typeof t.url!=`string`?null:{title:t.title,url:t.url,...typeof t.domain==`string`?{domain:t.domain}:{},...typeof t.snippet==`string`?{snippet:t.snippet}:{},...typeof t.ref_id==`string`?{ref_id:t.ref_id}:{},...typeof t.type==`string`?{type:t.type}:{}}});if(!n.some(e=>e==null))return{schema_version:1,type:`web_search`,source:`web_search_call`,call_status:e.call_status,query:e.query,action:V(e.action),completion:{status:t.status,query:t.query,action:V(t.action),results:n,...typeof t.error==`string`?{error:t.error}:{},...typeof t.event_block_key==`string`?{event_block_key:t.event_block_key}:{}}}}function be(e){let t=V(e.completion),n=V(t?.duration);if(!(e.source!==`function_call`||typeof e.name!=`string`||typeof e.call_status!=`string`||!t||typeof t.status!=`string`||typeof t.server!=`string`||typeof t.tool!=`string`||!V(t.arguments)||!V(t.result)||!n||typeof n.secs!=`number`||!Number.isFinite(n.secs)||typeof n.nanos!=`number`||!Number.isFinite(n.nanos)))return{schema_version:1,type:`mcp`,source:`function_call`,name:e.name,call_status:e.call_status,completion:{status:t.status,server:t.server,tool:t.tool,arguments:V(t.arguments),result:V(t.result),duration:{secs:n.secs,nanos:n.nanos},...typeof t.event_block_key==`string`?{event_block_key:t.event_block_key}:{}}}}var xe=new Set([`spawn_agent`,`wait_agent`,`send_message`,`list_agents`,`followup_task`,`interrupt_agent`]);function Se(e){let t=typeof e.operation==`string`&&xe.has(e.operation)?e.operation:null,n=V(e.arguments),r=e.result===void 0?void 0:_e(e.result),i=e.child_conversation==null?null:V(e.child_conversation);if(!(!t||typeof e.call_status!=`string`||!n||e.result!==void 0&&!r||e.child_conversation!=null&&!i)&&!(i&&typeof i.conversation_key!=`string`))return{schema_version:1,type:`agent`,operation:t,call_status:e.call_status,arguments:n,...r?{result:r}:{},...i?{child_conversation:{conversation_key:i.conversation_key,...typeof i.role==`string`?{role:i.role}:{},...typeof i.nickname==`string`?{nickname:i.nickname}:{}}}:{}}}function W(e){let t=V(e.detail?.card);if(t?.schema_version!==1)return;if(t.type===`terminal`){if(!Array.isArray(t.commands)||t.commands.length===0)return;let n=t.commands.map(e=>{let t=V(e);return!t||typeof t.command!=`string`?null:{command:t.command,workdir:typeof t.workdir==`string`?t.workdir:null,metadata:V(t.metadata)??{}}});return n.some(e=>e==null)?void 0:{schema_version:1,type:`terminal`,status:typeof t.status==`string`?t.status:`unknown`,commands:n,output:H(e.output?.detail?.card),truncated:t.truncated===!0||e.output?.detail?.card!=null&&V(e.output.detail.card)?.truncated===!0}}if(t.type===`plan`)return ve(t);if(t.type===`web_search`)return ye(t);if(t.type===`mcp`)return be(t);if(t.type===`agent`)return Se(t);if(t.type===`program`)return fe(t);if(t.type===`session_ref`)return pe(t);if(t.type===`tool_search`)return me(t);if(t.type!==`patch`)return;let n=se(t.files);if(n==null)return;let r=V(t.completion),i=r?.schema_version===1&&r.type===`patch`?r:t,a=ce(i.files);if(a!=null)return{schema_version:1,type:`patch`,source:typeof t.source==`string`?t.source:`patch_apply_end`,status:typeof i.status==`string`?i.status:`unknown`,files:a,request_files:r?n:void 0,patch:typeof t.patch==`string`?t.patch:void 0,success:typeof i.success==`boolean`?i.success:null,stdout:typeof i.stdout==`string`?i.stdout:null,stderr:typeof i.stderr==`string`?i.stderr:null,has_diff:typeof i.has_diff==`boolean`?i.has_diff:a.some(e=>typeof e.unified_diff==`string`),truncated:t.truncated===!0||i.truncated===!0,event_payload_key:typeof i.event_block_key==`string`?i.event_block_key:void 0}}function Ce(e){let t=e[0],n=t.kind===`command`?t.command:t.kind===`session`?[w(t.operation),S(t.scope,t.ref)].filter(Boolean).join(` `):t.name;return e.length>1?`${n} +${e.length-1} more`:n}function we(e){return[S(e.scope,e.ref),e.chars==null?``:D(e.chars)].filter(Boolean).join(` · `)||e.operation}function G(e){if(e)return e.replace(/^\[((?:\$)[^\]\r\n]+)\]\([^\)\r\n]*\/SKILL\.md\)[ \t]*/,(e,t,n,r)=>n+e.length<r.length?`${t} `:t)}function Te(e,t){let n=[];for(let r of e){if(r.kind===`assistant`||r.kind===`user`||r.kind===`text`){let e=r.kind===`assistant`?ge(r.detail?.external_call):null,t=e?.span!=null&&r.text!=null&&e.span[1]<=r.text.length?e.span:null,i=t?`${r.text.slice(0,t[0])}${r.text.slice(t[1])}`.replace(/[ \t]*\n+$/,``):r.text;i&&n.push({kind:`text`,text:i,...r.block_key?{block_key:r.block_key}:{}}),e&&t&&n.push({...e.block,...r.block_key?{block_key:r.block_key}:{}});let a=ae(r.detail?.markers);a&&n.push({kind:`system_actions`,actions:a,...r.block_key?{payload_key:r.block_key}:{}});continue}if(r.kind===`thinking`){r.text?.trim()&&n.push({kind:`thinking`,text:r.text});continue}if(r.kind===`reasoning`){if(t===`codex`){let e=ie(r);e&&n.push(e)}else r.text?.trim()&&n.push({kind:`thinking`,text:r.text});continue}if(r.kind===`tool_call`){let e=r;if(t===`claude`&&r.detail==null&&typeof e.input_summary==`string`&&typeof e.preview==`string`&&`result`in e){n.push(e);continue}let i=typeof r.detail?.name==`string`?r.detail.name:null,a=typeof r.detail?.args==`string`?r.detail.args:``,o=W(r),s=o?.type===`terminal`?o:null,c=o?.type===`patch`?o:null,l=o?.type===`plan`?o:null,u=o?.type===`web_search`?o:null,d=o?.type===`mcp`?o:null,f=o?.type===`agent`?o:null,p=o?.type===`program`?o:null,m=o?.type===`session_ref`?o:null,h=o?.type===`tool_search`?o:null,g=s?{command:s.commands[0].command,workdir:s.commands[0].workdir}:u?{query:u.query,action:u.action}:d?d.completion.arguments:f?f.arguments:z(a),_=t===`codex`?ue(H(r.output?.detail?.card)):void 0,v=s?.output?.is_error===!0||c?.success===!1||U.has(u?.completion.status??``)||U.has(d?.completion.status??``)||U.has(_?.status??``),y=B(l?.explanation)??B(u?.query)??(d?B(`${d.completion.tool} · ${d.completion.server}`):void 0)??(f?B(f.operation):void 0)??B(h?.query)??B(p?.title)??(p?B(Ce(p.invocations)):void 0)??(m?B(we(m)):void 0),b=l?.result?.value??u?.completion.error??d?.completion.result??f?.result?.value??null,x=typeof b==`string`?b:b==null?null:JSON.stringify(b,null,2);n.push({kind:`tool_call`,name:i,input_summary:s?JSON.stringify({commands:s.commands}):a||r.text||``,input:g,preview:s?.commands[0].command??c?.files.map(e=>e.move_path??e.path).filter(Boolean).join(`, `)??y??(r.text??a).split(`
2
2
  `)[0]??``,tool_use_id:r.block_key??null,...r.block_key?{block_key:r.block_key}:{},payload_capable:r.block_key!=null,payload_kind:`call`,native_card:o,..._?{outcome:_}:{},web_search:u?{query:u.query,links:u.completion.results}:void 0,result:r.output||x!=null?{text:x??r.output?.text??``,truncated:s?.output?.truncated===!0||c?.truncated===!0||l?.result?.truncated===!0||f?.result?.truncated===!0,is_error:v}:null});continue}if(r.kind===`event`){let e=W(r);if(e?.type===`patch`){let t=[e.stdout,e.stderr].filter(e=>typeof e==`string`).join(``);n.push({kind:`tool_call`,name:`patch_apply_end`,input_summary:r.text??``,input:null,preview:e.files.map(e=>e.move_path??e.path).filter(Boolean).join(`, `)||`patch summary`,tool_use_id:r.block_key??null,...r.block_key?{block_key:r.block_key}:{},payload_capable:r.block_key!=null,payload_kind:`event`,native_card:e,result:{text:t,truncated:e.truncated===!0,is_error:e.success===!1||U.has(e.status)}});continue}let t=oe(r);if(t){n.push(t);continue}}if(r.kind===`tool_output`||r.kind===`tool_result`){let e=H(r.detail?.card);n.push({kind:`tool_result`,text:r.text??``,truncated:e?.truncated===!0,is_error:r.detail?.is_error===!0||e?.is_error===!0||U.has(e?.status??``),tool_use_id:r.call_id??r.block_key??null,...r.block_key?{block_key:r.block_key}:{}});continue}r.text?n.push({kind:`text`,text:r.text,...r.block_key?{block_key:r.block_key}:{}}):r.block_key&&n.push({kind:`text`,text:``,block_key:r.block_key})}return n}function Ee(e){let t=e.blocks.find(e=>e.kind===`event`),n=V(t?.detail?.lifecycle);return n?.event===`task_started`||n?.event===`task_complete`?`codex_${n.event}`:typeof t?.detail?.event==`string`?t.detail.event:t?.text?.split(`
3
3
  `)[0]?.trim()||null}function De(e){let t=V(e);if(t?.schema_version!==1||typeof t.state!=`string`||!Array.isArray(t.events))return;let n=t.events.map(e=>{let t=V(e);return t&&typeof t.event==`string`&&t.payload_which===`event`&&typeof t.block_key==`string`?{event:t.event,payload_which:`event`,block_key:t.block_key}:null});if(!n.some(e=>e==null))return{schema_version:1,state:t.state,...V(t.started)?{started:V(t.started)}:{},...V(t.completed)?{completed:V(t.completed)}:{},events:n}}function Oe(e){let t=e.blocks.find(e=>e.kind===`meta`)?.detail,n=e.meta_kind??t?.meta_kind,r=e.meta_label??t?.meta_label,i=typeof r==`string`?r:Ee(e);return{meta_kind:n===`skill`||n===`command`||n===`context`||n===`compaction`||n===`notification`?n:i===`context_compacted`?`compaction`:e.kind===`event`?`notification`:`context`,meta_label:i,meta_sections:Array.isArray(e.meta_sections)?e.meta_sections.filter(e=>typeof e==`string`):void 0,skill_name:typeof e.skill_name==`string`?e.skill_name:null}}function ke(e,t){let n={session_id:e.key,uuid:t.item_key,id:te(t.item_key)},r=Te(t.blocks,e.source),i=t.blocks.filter(e=>e.kind===`user`||e.kind===`assistant`||e.kind===`text`).map(e=>e.text??``).filter(Boolean).join(`
4
4
 
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
6
6
  <link rel="icon" type="image/svg+xml" href="/static/favicon.svg" />
7
7
  <title>cctally dashboard</title>
8
- <script type="module" crossorigin src="/static/assets/index-BXDOzSng.js"></script>
8
+ <script type="module" crossorigin src="/static/assets/index-CYZ3NLqF.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/static/assets/useKeymap-CW7Up0Ay.js">
10
10
  <link rel="stylesheet" crossorigin href="/static/assets/index-BKITk1CT.css">
11
11
  </head>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cctally",
3
- "version": "1.115.0",
3
+ "version": "1.116.0",
4
4
  "description": "Claude Code usage tracker and local dashboard for Pro/Max subscription limits - weekly cost-per-percent trend, quota forecasts, threshold alerts. ccusage-compatible.",
5
5
  "homepage": "https://github.com/omrikais/cctally",
6
6
  "repository": {
@@ -43,6 +43,7 @@
43
43
  "bin/_cctally_journal_repair.py",
44
44
  "bin/_cctally_milestone_history.py",
45
45
  "bin/_cctally_milestones.py",
46
+ "bin/_cctally_oauth_samples.py",
46
47
  "bin/_cctally_parser.py",
47
48
  "bin/_cctally_percent_breakdown.py",
48
49
  "bin/_cctally_pricing_check.py",
@@ -67,7 +68,6 @@
67
68
  "bin/_cctally_tui.py",
68
69
  "bin/_cctally_update.py",
69
70
  "bin/_cctally_weekrefs.py",
70
- "bin/_lib_merge_gate.py",
71
71
  "bin/_lib_quarantine.py",
72
72
  "bin/_lib_account_binding.py",
73
73
  "bin/_lib_account_protocol.py",
@@ -137,11 +137,13 @@
137
137
  "bin/_lib_log.py",
138
138
  "bin/_lib_meter_rate_change.py",
139
139
  "bin/_lib_milestone_history.py",
140
+ "bin/_lib_oauth_samples.py",
140
141
  "bin/_lib_outcome_quarantine.py",
141
142
  "bin/_lib_perf.py",
142
143
  "bin/_lib_pricing.py",
143
144
  "bin/_lib_pricing_check.py",
144
145
  "bin/_lib_pricing_debug.py",
146
+ "bin/_lib_provider_activity.py",
145
147
  "bin/_lib_quota.py",
146
148
  "bin/_lib_quota_alert_axes.py",
147
149
  "bin/_lib_quota_calibration.py",
@@ -150,6 +152,7 @@
150
152
  "bin/_lib_quota_model.py",
151
153
  "bin/_lib_rate_change_delivery.py",
152
154
  "bin/_lib_readme_refresh.py",
155
+ "bin/_lib_rebuild_progress.py",
153
156
  "bin/_lib_reclaim_planner.py",
154
157
  "bin/_lib_record.py",
155
158
  "bin/_lib_rederive.py",
@@ -165,6 +168,7 @@
165
168
  "bin/_lib_source_identity.py",
166
169
  "bin/_lib_source_retry.py",
167
170
  "bin/_lib_sqlite_close.py",
171
+ "bin/_lib_stale_proof.py",
168
172
  "bin/_lib_stats_damage.py",
169
173
  "bin/_lib_stats_publish.py",
170
174
  "bin/_lib_stats_wal.py",
@@ -175,6 +179,7 @@
175
179
  "bin/_lib_transcript_access.py",
176
180
  "bin/_lib_view_models.py",
177
181
  "bin/_lib_wal_checkpoint.py",
182
+ "bin/_lib_worker_launches.py",
178
183
  "bin/_lib_write_budget.py",
179
184
  "bin/_lib_write_io.py",
180
185
  "bin/cctally",
@@ -1,452 +0,0 @@
1
- """Conservative impact selection for merge certification (stdlib only).
2
-
3
- This is a reviewed component policy, not proof of every possible dependency.
4
- Unknown paths and shared/infrastructure changes require the full estate. The
5
- scheduled full run and the release run remain the cross-component backstop.
6
- """
7
- from __future__ import annotations
8
-
9
- import argparse
10
- import hashlib
11
- import importlib.util
12
- import json
13
- import os
14
- from pathlib import Path, PurePosixPath
15
- import signal
16
- import subprocess
17
- import sys
18
-
19
- GATE_ID = 'cctally-test-remote/merge-focused@1'
20
- MAX_SECONDS = 300
21
- # All of these are leaf presentation components. Their entire frontend estate
22
- # runs, including their consumers, instead of relying on a TS import heuristic.
23
- PRESENTATION_FILES = frozenset(
24
- 'dashboard/web/src/components/' + name + '.tsx'
25
- for name in ('ZoneTag', 'ModelLegend', 'SortableHeader', 'HelpOverlay',
26
- 'AlertsEmptyGauge', 'SessionsControls', 'BasketChip', 'Toast')
27
- )
28
- SMOKE_FILES = ('tests/test_cli_smoke.py', 'tests/test_lib_json_envelope.py')
29
- PRESENTATION_PYTEST = ('tests/test_dashboard_handler_static.py',)
30
- # The reviewed memory publication set: both topic stores and the topic metadata.
31
- # A private test pins it to the publication engine's own definition. Its
32
- # configuration is NOT memory, so a change to it is ordinary task work.
33
- MEMORY_PUBLICATION_SET = ('.claude-memory/**', '.agentmem/codex-memory/**', '.agentmem/topics.json')
34
- MEMORY_CONFIGURATION = '.agentmem/config.json'
35
- # Every test module that reads the memory corpus, beside the smoke files and
36
- # the Doc lint harness: together they certify a memory-only candidate.
37
- MEMORY_PYTEST = ('tests/test_cctally_memory.py', 'tests/test_agent_workflows.py',
38
- 'tests/test_session_workflow_texts.py')
39
- # The capture publishes regular files only (a link is refused), so a memory
40
- # path that is anything else on either side is not a memory publication.
41
- REGULAR_MODES = ('100644', '100755')
42
- # The instruction-text class (#894): agent-instruction prose whose every reader
43
- # is one of INSTRUCTIONS_PYTEST. Markdown at any depth under these trees,
44
- # nested CLAUDE.md/AGENTS.md included.
45
- INSTRUCTION_TREES = ('.agent-workflows/skills/', '.claude/skills/', '.agents/skills/',
46
- '.agent-workflows/contracts/', 'docs/superpowers/')
47
- INSTRUCTION_NAMES = ('CLAUDE.md', 'AGENTS.md')
48
- # Every nested instruction file outside the trees. A new one is a structural
49
- # change to the instruction chain: its readers depend on where it lands, so it
50
- # selects the full estate until a reviewed policy change lists it here.
51
- NESTED_INSTRUCTION_FILES = ('bin/AGENTS.md', 'dashboard/AGENTS.md')
52
- # The generator inputs of the root AGENTS.md (its configuration is not one).
53
- INSTRUCTION_INPUTS = ('.agentmem/codex.md', '.agentmem/manifest.json')
54
- # Every test module that reads, validates or scans an instruction path,
55
- # beside the smoke files and the Doc lint harness.
56
- INSTRUCTIONS_PYTEST = ('tests/test_agent_workflows.py', 'tests/test_session_workflow_texts.py',
57
- 'tests/test_cctally_memory.py', 'tests/test_session_issues.py',
58
- 'tests/test_session_provenance.py', 'tests/test_linux_matrix_gate.py',
59
- 'tests/test_release_internals.py', 'tests/test_quota_budget_error_harness.py',
60
- 'tests/test_session_policy.py', 'tests/test_lib_share.py',
61
- 'tests/test_dashboard_source_kernel.py', 'tests/test_share_privacy_detector.py',
62
- 'tests/test_fixture_cache.py')
63
- # An instruction path is eligible only as a non-executable regular file.
64
- INSTRUCTION_MODES = ('100644',)
65
- # The two session execution plans are documentation: their only readers are
66
- # people and the Doc lint harness, so a plan refresh takes the documentation
67
- # focus. Exactly these two paths; any other docs/ Markdown is unclassified.
68
- EXECUTION_PLAN_PATHS = ('docs/cctally-claude-execution-plan.md', 'docs/cctally-execution-plan.md')
69
-
70
-
71
- def _git(repo, *args):
72
- proc = subprocess.run(['git', '--no-optional-locks', '-C', str(repo), *args],
73
- capture_output=True)
74
- if proc.returncode:
75
- raise ValueError('git revision/diff failed: ' + proc.stderr.decode(errors='replace').strip())
76
- return proc.stdout
77
-
78
-
79
- def _changed_names(data):
80
- """--name-only -z lists both endpoints when rename detection is disabled."""
81
- return [p.decode('utf-8', errors='strict') for p in data.split(b'\0') if p]
82
-
83
-
84
- def basis(repo, base_rev, head='HEAD', *, working=True):
85
- if not base_rev or base_rev.startswith('-'):
86
- raise ValueError('base revision must be nonempty and must not be an option')
87
- base = _git(repo, 'merge-base', base_rev, head).decode().strip()
88
- head_oid = _git(repo, 'rev-parse', '--verify', head + '^{commit}').decode().strip()
89
- committed = set(_changed_names(_git(repo, 'diff', '--no-renames', '--name-only', '-z', base, head_oid)))
90
- dirty = set()
91
- if working:
92
- dirty.update(_changed_names(_git(repo, 'diff', '--no-renames', '--name-only', '-z', head_oid)))
93
- dirty.update(_changed_names(_git(repo, 'ls-files', '--others', '--exclude-standard', '-z')))
94
- if _git(repo, 'ls-files', '-u'):
95
- raise ValueError('the index has unmerged entries')
96
- return {'baseOid': base, 'headOid': head_oid,
97
- 'committedPaths': len(committed), 'worktreePaths': len(dirty),
98
- 'paths': sorted(committed | dirty)}
99
-
100
-
101
- def memory_publication_path(path):
102
- """Whether `path` is in the memory publication set (the engine's glob semantics)."""
103
- path = path.strip('/')
104
- for pattern in MEMORY_PUBLICATION_SET:
105
- if pattern.endswith('/**'):
106
- prefix = pattern[:-3]
107
- if path == prefix or path.startswith(prefix + '/'):
108
- return True
109
- elif path == pattern:
110
- return True
111
- return False
112
-
113
-
114
- def _tree_modes(repo, rev, paths):
115
- """{path: git mode} of the entries `paths` name in `rev` (absent paths are omitted)."""
116
- out = _git(repo, '--literal-pathspecs', 'ls-tree', '-z', '--full-tree', rev, '--', *paths)
117
- modes = {}
118
- for record in out.split(b'\0'):
119
- if record:
120
- meta, name = record.split(b'\t', 1)
121
- modes[name.decode('utf-8', errors='strict')] = meta.split()[0].decode()
122
- return modes
123
-
124
-
125
- def irregular_memory_paths(repo, base, head_oid, paths, *, working=True):
126
- """The memory paths that are not a regular file (or absent) at the base, at the head,
127
- or (with `working`) in the working tree: the file types the publication set does not define."""
128
- irregular = set()
129
- for rev in (base, head_oid):
130
- irregular.update(name for name, mode in _tree_modes(repo, rev, paths).items()
131
- if mode not in REGULAR_MODES)
132
- if working:
133
- for path in paths:
134
- target = Path(repo) / path
135
- if target.is_symlink() or (target.exists() and not target.is_file()):
136
- irregular.add(path)
137
- return sorted(irregular & set(paths))
138
-
139
-
140
- def _blob_prefixes(repo, rev, paths):
141
- """{path: its first two bytes} for the blobs `paths` name in `rev`, in one git call."""
142
- if not paths:
143
- return {}
144
- request = b''.join(f'{rev}:{path}\n'.encode('utf-8') for path in paths)
145
- proc = subprocess.run(['git', '--no-optional-locks', '-C', str(repo), 'cat-file', '--batch'],
146
- input=request, capture_output=True)
147
- if proc.returncode:
148
- raise ValueError('git cat-file failed: ' + proc.stderr.decode(errors='replace').strip())
149
- out, offset, prefixes = proc.stdout, 0, {}
150
- for path in paths:
151
- end = out.index(b'\n', offset)
152
- header = out[offset:end].split()
153
- if len(header) != 3 or header[1] != b'blob':
154
- raise ValueError('git cat-file returned no blob for ' + path)
155
- size = int(header[2])
156
- prefixes[path] = out[end + 1:end + 1 + min(size, 2)]
157
- offset = end + 1 + size + 1
158
- return prefixes
159
-
160
-
161
- def ineligible_instruction_paths(repo, base, head_oid, paths, *, working=True):
162
- """The instruction paths that are not a non-executable regular file without a
163
- `#!` first line at the base, at the head, or (with `working`) on disk. Absence
164
- on any side is eligible. With `working=False` only the two commits are read."""
165
- paths = sorted(p for p in paths if _sane(p) and _instruction_class(p) == 'instruction')
166
- if not paths:
167
- return []
168
- ineligible = set()
169
- for rev in (base, head_oid):
170
- modes = _tree_modes(repo, rev, paths)
171
- ineligible.update(name for name, mode in modes.items() if mode not in INSTRUCTION_MODES)
172
- regular = sorted(name for name, mode in modes.items() if mode in INSTRUCTION_MODES)
173
- ineligible.update(name for name, prefix in _blob_prefixes(repo, rev, regular).items()
174
- if prefix == b'#!')
175
- if working:
176
- for path in paths:
177
- target = Path(repo) / path
178
- if target.is_symlink():
179
- ineligible.add(path)
180
- elif target.exists():
181
- if not target.is_file() or target.stat().st_mode & 0o111:
182
- ineligible.add(path)
183
- else:
184
- with target.open('rb') as handle:
185
- if handle.read(2) == b'#!':
186
- ineligible.add(path)
187
- return sorted(ineligible & set(paths))
188
-
189
-
190
- def _memory_only(paths, irregular):
191
- """A memory-only candidate: every path in the publication set, each a regular file."""
192
- return (irregular is not None and bool(paths) and not irregular
193
- and all(memory_publication_path(p) and _sane(p) for p in paths))
194
-
195
-
196
- def _sane(path):
197
- p = PurePosixPath(path)
198
- return not (p.is_absolute() or '..' in p.parts or any(c.isspace() for c in path))
199
-
200
-
201
- def policy_digest(repo):
202
- return 'sha256:' + hashlib.sha256(
203
- (Path(repo) / 'bin/_lib_merge_gate.py').read_bytes()).hexdigest()
204
-
205
-
206
- def _document(path):
207
- return path in ('README.md', 'CHANGELOG.md') or path in EXECUTION_PLAN_PATHS or (
208
- path.startswith('docs/commands/') and path.endswith('.md'))
209
-
210
-
211
- def _frontend_test(path):
212
- return path.startswith('dashboard/web/src/') and path.endswith(('.test.ts', '.test.tsx'))
213
-
214
-
215
- def _instruction_class(path):
216
- """'instruction' for an instruction path, a full-selection reason for an
217
- instruction-file name at an unreviewed location, or None for any other path."""
218
- if path.endswith('.md') and path.startswith(INSTRUCTION_TREES):
219
- return 'instruction'
220
- if PurePosixPath(path).name in INSTRUCTION_NAMES:
221
- if path in INSTRUCTION_NAMES or path in NESTED_INSTRUCTION_FILES:
222
- return 'instruction'
223
- return 'unreviewed nested instruction file: ' + path
224
- if path in INSTRUCTION_INPUTS:
225
- return 'instruction'
226
- return None
227
-
228
-
229
- def select(repo, paths, *, irregular=None, instruction_evidence=None):
230
- """The reviewed selection of `paths`.
231
-
232
- `irregular` is the list of memory paths that are not regular files
233
- (`irregular_memory_paths`); only a caller that computed it can have a
234
- candidate selected as memory-only. Any other candidate is selected over its
235
- whole diff, where a memory path is unclassified.
236
-
237
- `instruction_evidence` is the list of instruction paths that are not
238
- non-executable regular files (`ineligible_instruction_paths`); only a caller
239
- that computed it can have an instruction path selected focused.
240
- """
241
- repo = Path(repo)
242
- manifest = json.loads((repo / 'tests/authoritative-test-manifest.json').read_text())
243
- private = (repo / '.mirror-allowlist').exists()
244
- names = [r['name'] for r in manifest['harnesses']
245
- if private or r.get('visibility', 'public') == 'public']
246
- if not names or len(names) != len(set(names)):
247
- raise ValueError('invalid harness manifest')
248
- paths = sorted(set(paths))
249
- reasons, components = [], set()
250
- memory = _memory_only(paths, irregular)
251
- if memory:
252
- components.add('memory')
253
- for path in ([] if memory else paths):
254
- p = PurePosixPath(path)
255
- if path in (irregular or ()):
256
- reasons.append('memory path that is not a regular file: ' + path)
257
- elif p.is_absolute() or '..' in p.parts or any(c.isspace() for c in path):
258
- reasons.append('unclassified path: ' + path)
259
- elif '__pycache__' in p.parts:
260
- # Terminal: the skill comparison never reads cache content, so no
261
- # class may admit it (the memory-only shortcut is decided above).
262
- reasons.append('runtime cache path: ' + path)
263
- elif (instruction := _instruction_class(path)) is not None:
264
- if instruction != 'instruction':
265
- reasons.append(instruction)
266
- elif instruction_evidence is None:
267
- reasons.append('instruction path without file evidence: ' + path)
268
- elif path in instruction_evidence:
269
- reasons.append('instruction path that is not a non-executable regular file: ' + path)
270
- else:
271
- components.add('instructions')
272
- elif _document(path):
273
- components.add('documentation')
274
- elif path in PRESENTATION_FILES or _frontend_test(path):
275
- components.add('presentation')
276
- elif path.startswith('dashboard/static/'):
277
- components.add('presentation')
278
- elif path in PRESENTATION_PYTEST:
279
- components.add('presentation')
280
- else:
281
- reasons.append('shared, high-risk, or unclassified path: ' + path)
282
- if 'instructions' in components and 'presentation' in components:
283
- reasons.append('instruction text and presentation are not certified together')
284
- harnesses = {'doc-lint'}
285
- files = set(SMOKE_FILES)
286
- if 'presentation' in components:
287
- harnesses.add('frontend')
288
- files.update(PRESENTATION_PYTEST)
289
- if 'memory' in components:
290
- files.update(MEMORY_PYTEST)
291
- if 'instructions' in components:
292
- files.update(INSTRUCTIONS_PYTEST)
293
- if not harnesses <= set(names):
294
- reasons.append('required merge harness absent from manifest')
295
- if any(not (repo / p).is_file() for p in files):
296
- reasons.append('required merge pytest file absent')
297
- full = bool(reasons)
298
- return {
299
- 'mode': 'full' if full else 'merge-focused',
300
- 'pytest': 'full' if full else 'selected',
301
- 'selectedHarnesses': [n for n in names if full or n in harnesses],
302
- 'omittedHarnesses': [n for n in names if not full and n not in harnesses],
303
- 'selectedPytestFiles': [] if full else sorted(files),
304
- 'components': sorted(components), 'reasons': reasons,
305
- 'policyDigest': policy_digest(repo),
306
- 'maxWallSeconds': MAX_SECONDS,
307
- }
308
-
309
-
310
- def plan(repo, base_rev, head='HEAD', *, working=True):
311
- b = basis(repo, base_rev, head, working=working)
312
- irregular = None
313
- if b['paths'] and all(memory_publication_path(p) for p in b['paths']):
314
- irregular = irregular_memory_paths(repo, b['baseOid'], b['headOid'], b['paths'], working=working)
315
- evidence = None
316
- if any(_sane(p) and _instruction_class(p) == 'instruction' for p in b['paths']):
317
- evidence = ineligible_instruction_paths(repo, b['baseOid'], b['headOid'], b['paths'],
318
- working=working)
319
- result = select(repo, b['paths'], irregular=irregular, instruction_evidence=evidence)
320
- result['mergeBasis'] = b
321
- return result
322
-
323
-
324
- def filter_legs(plan_record, directory, quarantined=()):
325
- """Narrow both expected-node legs to selected files; retain serial ownership.
326
-
327
- bin/cctally-test-all applies tests/quarantine.json to the legs first, so a
328
- selected file whose every node is quarantined has none left. Such a file
329
- (one that ``quarantined``, the list's node ids, names) contributes no
330
- targets; any other selected file without a recorded node refuses."""
331
- directory = Path(directory)
332
- selected = set(plan_record['selectedPytestFiles'])
333
- found = set()
334
- for name in ('pytest', 'benchmark'):
335
- path = directory / (name + '.txt')
336
- nodes = [n for n in path.read_text().splitlines() if n.split('::')[0] in selected]
337
- found.update(n.split('::')[0] for n in nodes)
338
- path.write_text(''.join(n + '\n' for n in nodes))
339
- absent = selected - found - {node.split('::')[0] for node in quarantined}
340
- if absent:
341
- raise ValueError('selected files absent from recorded pytest estate: ' + ', '.join(sorted(absent)))
342
-
343
-
344
- def quarantine_ids(repo):
345
- """The pytest node ids tests/quarantine.json lists; none when the tree carries no list.
346
-
347
- Parsed by the shared bin/_lib_quarantine.py; harness cases are not pytest
348
- nodes and are left to their harness. bin/cctally-test-all validated the
349
- list at admission, before this runs."""
350
- sys.path.insert(0, str(Path(__file__).resolve().parent))
351
- import _lib_quarantine
352
- return _lib_quarantine.pytest_ids(_lib_quarantine.load(repo))
353
-
354
-
355
- def supervise(command, seconds):
356
- """Bound the complete gate, including foreground admission subprocesses.
357
-
358
- A fresh POSIX session contains the aggregator's separate pool/pytest
359
- process groups. Terminating that session also reaches children when bash
360
- is waiting on an admission command and cannot yet run its signal trap.
361
- The caller writes the ordinary contract's timeout verdict after teardown.
362
- """
363
- process = subprocess.Popen(command, start_new_session=True)
364
-
365
- def members():
366
- listing = subprocess.check_output(['ps', '-A', '-o', 'pid='], text=True)
367
- result = []
368
- for token in listing.split():
369
- pid = int(token)
370
- try:
371
- if os.getsid(pid) == process.pid:
372
- result.append(pid)
373
- except (ProcessLookupError, PermissionError):
374
- pass
375
- return result
376
-
377
- def terminate():
378
- for sig in (signal.SIGTERM, signal.SIGKILL):
379
- for pid in members():
380
- try:
381
- os.kill(pid, sig)
382
- except ProcessLookupError:
383
- pass
384
- if sig == signal.SIGTERM:
385
- try:
386
- process.wait(timeout=2)
387
- except subprocess.TimeoutExpired:
388
- pass
389
- process.wait()
390
-
391
- def interrupted(signum, _frame):
392
- terminate()
393
- raise SystemExit(128 + signum)
394
-
395
- old = {sig: signal.signal(sig, interrupted) for sig in (signal.SIGTERM, signal.SIGINT)}
396
- try:
397
- try:
398
- return process.wait(timeout=max(0, seconds))
399
- except subprocess.TimeoutExpired:
400
- terminate()
401
- return 124
402
- finally:
403
- for sig, handler in old.items():
404
- signal.signal(sig, handler)
405
-
406
-
407
- def main(argv=None):
408
- parser = argparse.ArgumentParser(description=__doc__)
409
- parser.add_argument('--repo', default=str(Path(__file__).resolve().parents[1]))
410
- parser.add_argument('--base')
411
- parser.add_argument('--required-mode', action='store_true')
412
- parser.add_argument('--shell', action='store_true')
413
- parser.add_argument('--filter-legs')
414
- parser.add_argument('--deadline', nargs=argparse.REMAINDER,
415
- help=argparse.SUPPRESS)
416
- args = parser.parse_args(argv)
417
- if args.deadline is not None:
418
- if len(args.deadline) < 2:
419
- parser.error('deadline requires seconds and a command')
420
- return supervise(args.deadline[1:], int(args.deadline[0]))
421
- if not args.base:
422
- parser.error('--base is required')
423
- try:
424
- result = plan(args.repo, args.base)
425
- if args.required_mode:
426
- # `<mode> <reason>`: the wrapper decides on the mode alone; the
427
- # reason names the focused components for whoever reads the log.
428
- if result['mode'] == 'full':
429
- reason = 'reviewed-selection'
430
- else:
431
- reason = '+'.join(result['components']) or 'none'
432
- print(f"{result['mode']} {reason}")
433
- elif args.filter_legs:
434
- filter_legs(result, args.filter_legs, quarantined=quarantine_ids(args.repo))
435
- elif args.shell:
436
- print('mode\t' + result['mode'])
437
- print('harnesses\t' + ' '.join(result['selectedHarnesses']))
438
- print('omitted\t' + ' '.join(result['omittedHarnesses']))
439
- print('pytest\t' + result['pytest'])
440
- print('files\t' + ' '.join(result['selectedPytestFiles']))
441
- print('seconds\t' + str(result['maxWallSeconds']))
442
- print('record\t' + json.dumps(result, sort_keys=True, separators=(',', ':')))
443
- else:
444
- print(json.dumps(result, sort_keys=True, indent=2))
445
- except (ValueError, OSError, KeyError, UnicodeError) as exc:
446
- print('merge-gate: ' + str(exc), file=sys.stderr)
447
- return 2
448
- return 0
449
-
450
-
451
- if __name__ == '__main__':
452
- raise SystemExit(main())
@@ -1 +0,0 @@
1
- import{Ft as e,Rt as t,a as n,b as r,c as i,f as a,t as o,x as s}from"./useKeymap-CW7Up0Ay.js";import{dt as c,jt as l,o as u,s as d,ut as f}from"./index-BXDOzSng.js";var p=t(e(),1);function m(){let[e,t]=(0,p.useState)(null),[n,r]=(0,p.useState)(!1),[i,a]=(0,p.useState)(null);return{report:e,loading:n,error:i,refresh:(0,p.useCallback)(async()=>{r(!0),a(null);try{let e=await fetch(`/api/doctor`);if(!e.ok)throw Error(`HTTP ${e.status}`);t(await e.json())}catch(e){a(e instanceof Error?e.message:String(e))}finally{r(!1)}},[])}}var h=n(),g={ok:`✓`,warn:`⚠`,fail:`✗`},_=/(--[A-Za-z0-9][A-Za-z0-9-]*)/g;function v({text:e}){return(0,h.jsx)(h.Fragment,{children:e.split(_).map((e,t)=>e.startsWith(`--`)?(0,h.jsx)(`span`,{className:`doctor-modal__flag`,children:e},`${e}-${t}`):e)})}function y(){let e=(0,p.useSyncExternalStore)(r,()=>a().doctorModalOpen),{report:t,loading:n,error:l,refresh:g}=m(),_=()=>{i({type:`CLOSE_DOCTOR_MODAL`})};o((0,p.useMemo)(()=>[{key:`Escape`,scope:`modal`,action:_,when:()=>a().doctorModalOpen}],[])),(0,p.useEffect)(()=>{e&&g()},[e,g]),(0,p.useEffect)(()=>{if(!t)return;let e=a().doctor,n=e?Date.parse(e.generated_at):NaN,r=Date.parse(t.generated_at);e&&Number.isFinite(n)&&Number.isFinite(r)&&r<=n||i({type:`SET_DOCTOR_AGGREGATE`,doctor:{severity:t.overall.severity,counts:t.overall.counts,generated_at:t.generated_at,fingerprint:`client-reconcile`}})},[t]);let v=(0,p.useRef)(null);return c(v,{active:e,trapEnabled:(0,p.useSyncExternalStore)(r,()=>s(a())===`doctor`),initialFocus:`container`}),f(e),e?(0,h.jsxs)(`div`,{className:`update-modal-root`,onClick:_,children:[(0,h.jsx)(`div`,{className:`modal-backdrop`}),(0,h.jsxs)(`div`,{ref:v,className:`modal-card doctor-modal-card`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":`doctor-modal-title`,tabIndex:-1,onClick:e=>e.stopPropagation(),children:[(0,h.jsx)(u,{title:`Doctor`,titleId:`doctor-modal-title`,headerExtras:(0,h.jsxs)(`div`,{className:`doctor-modal__header-actions`,children:[(0,h.jsx)(`button`,{type:`button`,className:`doctor-modal__refresh`,onClick:()=>{g()},disabled:n,"aria-label":`Refresh doctor report`,children:n?`refreshing…`:`↻ refresh`}),(0,h.jsx)(d,{onClose:_})]})}),(0,h.jsxs)(`div`,{className:`modal-body`,children:[n&&!t&&(0,h.jsx)(`p`,{children:`Loading…`}),l&&(0,h.jsxs)(`p`,{className:`doctor-modal__error`,children:[`Error loading report: `,l]}),t&&(0,h.jsx)(b,{report:t})]})]})]}):null}function b({report:e}){let{counts:t}=e.overall;return(0,h.jsxs)(h.Fragment,{children:[(0,h.jsxs)(`p`,{className:`doctor-modal__summary`,children:[t.ok,` OK · `,t.warn,` WARN · `,t.fail,` FAIL`]}),e.categories.map(e=>(0,h.jsx)(x,{cat:e,defaultOpen:e.severity!==`ok`},e.id))]})}function x({cat:e,defaultOpen:t}){let[n,r]=(0,p.useState)(t);return(0,h.jsxs)(`section`,{className:`doctor-modal__category doctor-modal__category--${e.severity}`,children:[(0,h.jsxs)(`button`,{type:`button`,className:`doctor-modal__category-header`,onClick:()=>r(e=>!e),"aria-expanded":n,children:[(0,h.jsx)(`span`,{className:`doctor-modal__category-caret`,"aria-hidden":`true`,children:n?`▾`:`▸`}),(0,h.jsx)(`span`,{className:`doctor-modal__glyph`,"aria-hidden":`true`,children:g[e.severity]}),(0,h.jsx)(`span`,{children:e.title})]}),n&&e.checks.map(e=>(0,h.jsx)(S,{c:e},e.id))]})}function S({c:e}){let[t,n]=(0,p.useState)(!1),r=e.details&&Object.keys(e.details).length>0,i=e.id===`data.latest_snapshot_age`&&typeof e.details?.latest_snapshot_age_s==`number`?l(e.details.latest_snapshot_age_s):e.summary;return(0,h.jsxs)(`div`,{className:`doctor-modal__check doctor-modal__check--${e.severity}`,children:[(0,h.jsxs)(`p`,{children:[(0,h.jsx)(`span`,{className:`doctor-modal__glyph`,"aria-label":e.severity,children:g[e.severity]}),` `,(0,h.jsx)(`strong`,{children:e.title}),`: `,i]}),e.remediation&&(0,h.jsxs)(`p`,{className:`doctor-modal__remediation`,children:[`→ `,(0,h.jsx)(v,{text:e.remediation})]}),e.severity!==`ok`&&!e.remediation&&(0,h.jsxs)(`p`,{className:`doctor-modal__remediation`,children:[`→ Run `,(0,h.jsx)(`code`,{children:`cctally doctor`}),` for the full report`]}),r&&(0,h.jsxs)(h.Fragment,{children:[(0,h.jsxs)(`button`,{type:`button`,className:`doctor-modal__details-toggle`,onClick:()=>n(e=>!e),"aria-expanded":t,children:[t?`▼`:`▶`,` details`]}),t&&(0,h.jsx)(`pre`,{className:`doctor-modal__details`,children:JSON.stringify(e.details,null,2)})]})]})}export{y as DoctorModal};