@timurtekb/tekjobs 0.30.0 → 0.31.1
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/CHANGELOG.md +11 -0
- package/README.md +6 -3
- package/app/dist/assets/{index-DIgDstHD.js → index-Dnu8dxG5.js} +1 -1
- package/app/dist/index.html +1 -1
- package/app/server/cover-letter.mjs +25 -5
- package/cli.mjs +71 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
Every release, newest first. Written by semantic-release from the commit messages.
|
|
4
4
|
|
|
5
|
+
## <small>0.31.1 (2026-10-07)</small>
|
|
6
|
+
|
|
7
|
+
* fix(mail): a recruiter's "401(k)" no longer reads as a signed-out CLI ([8610854](https://github.com/Timurtek/tekjobs/commit/8610854))
|
|
8
|
+
* chore(changelog): one entry for 0.31.0, not the one a failed run left behind ([538df22](https://github.com/Timurtek/tekjobs/commit/538df22))
|
|
9
|
+
|
|
10
|
+
## 0.31.0 (2026-10-07)
|
|
11
|
+
|
|
12
|
+
* fix(cli): servers stay up until you stop them; tekjobs up, down and ps ([4cb10b6](https://github.com/Timurtek/tekjobs/commit/4cb10b6))
|
|
13
|
+
* feat(cli): tekjobs serve opens the app and leaves when the app is closed ([91a584d](https://github.com/Timurtek/tekjobs/commit/91a584d))
|
|
14
|
+
* docs(site): a square cut of the showreel ([26a4f3c](https://github.com/Timurtek/tekjobs/commit/26a4f3c))
|
|
15
|
+
|
|
5
16
|
## 0.30.0 (2026-09-27)
|
|
6
17
|
|
|
7
18
|
* feat(site): a 45-second showreel, on the landing and in the README ([ac1aa62](https://github.com/Timurtek/tekjobs/commit/ac1aa62))
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ A local career memory for you and your AI. TekJobs scans hundreds of public comp
|
|
|
14
14
|
|
|
15
15
|
[](https://tekjobs.timurtek.com/#showreel)
|
|
16
16
|
|
|
17
|
-
*What it does, in forty-five seconds. [Watch the showreel](https://tekjobs.timurtek.com/#showreel) ([mp4](https://tekjobs.timurtek.com/showreel/tekjobs-showreel.mp4), [vertical
|
|
17
|
+
*What it does, in forty-five seconds. [Watch the showreel](https://tekjobs.timurtek.com/#showreel) ([mp4](https://tekjobs.timurtek.com/showreel/tekjobs-showreel.mp4), [vertical](https://tekjobs.timurtek.com/showreel/tekjobs-showreel-vertical.mp4) and [square](https://tekjobs.timurtek.com/showreel/tekjobs-showreel-square.mp4) cuts). For one real, unedited run on the fictional sample resume (install, interview, first scan, first Today), [watch the 57-second demo](https://tekjobs.timurtek.com/#demo).*
|
|
18
18
|
|
|
19
19
|
## Why it exists
|
|
20
20
|
|
|
@@ -63,7 +63,7 @@ It does not fit if you want a hosted service with nothing to install (TekJobs is
|
|
|
63
63
|
4. Run the app, and schedule the mornings.
|
|
64
64
|
|
|
65
65
|
```
|
|
66
|
-
tekjobs
|
|
66
|
+
tekjobs up # the app on http://127.0.0.1:8787, detached: it stays up until `tekjobs down`
|
|
67
67
|
tekjobs schedule # the scan and the read-only mail pass, daily at 07:30 (--time to change it)
|
|
68
68
|
```
|
|
69
69
|
|
|
@@ -170,7 +170,10 @@ tekjobs add <url> [<url>...] [--dry] add postings you found yourself
|
|
|
170
170
|
tekjobs mail [--days N] the read-only mail pass
|
|
171
171
|
tekjobs rescore [--full] [--dry] what existing notes score under the current criteria
|
|
172
172
|
tekjobs schedule [--time HH:MM] [--print] the morning task, for Windows, macOS or Linux
|
|
173
|
-
tekjobs
|
|
173
|
+
tekjobs up [--dev] [--port N] start the API (and with --dev, Vite) detached; they stay up until `down`
|
|
174
|
+
tekjobs down stop what `up` started
|
|
175
|
+
tekjobs ps what `up` has running
|
|
176
|
+
tekjobs serve the app + API on http://127.0.0.1:8787, in this terminal
|
|
174
177
|
tekjobs mcp the MCP server on stdio
|
|
175
178
|
tekjobs --version
|
|
176
179
|
```
|
|
@@ -57,7 +57,7 @@ Defaulting to \`null\`.`}md(Ad,`getInvalidValueError`);var jd=xd,Md=Cd;(0,b.forw
|
|
|
57
57
|
`)});continue}let a=/^(#{1,6})\s+(.*)$/.exec(e);if(a){n.push({kind:`heading`,level:a[1].length,children:ug(a[2])}),r++;continue}if(/^(-{3,}|\*{3,}|_{3,})\s*$/.test(e)){n.push({kind:`rule`}),r++;continue}if(sg(e)&&r+1<t.length&&cg(t[r+1])){let i=og(e).map(ug);r+=2;let a=[];for(;r<t.length&&sg(t[r]);)a.push(og(t[r++]).map(ug));n.push({kind:`table`,header:i,rows:a});continue}if(/^>\s?/.test(e)){let e=[];for(;r<t.length&&/^>\s?/.test(t[r]);)e.push(t[r++].replace(/^>\s?/,``));n.push({kind:`quote`,children:ug(e.join(` `))});continue}let o=/^\s*([-*+]|\d+[.)])\s+/.exec(e);if(o){let e=/\d/.test(o[1]),i=[];for(;r<t.length;){let e=/^\s*([-*+]|\d+[.)])\s+(.*)$/.exec(t[r]);if(!e)break;let n=e[2];for(r++;r<t.length&&/^\s{2,}\S/.test(t[r])&&!/^\s*([-*+]|\d+[.)])\s+/.test(t[r]);)n+=` `+t[r++].trim();i.push(ug(n))}n.push({kind:`list`,ordered:e,items:i});continue}let s=[];for(;r<t.length&&t[r].trim()!==``&&!/^```/.test(t[r])&&!/^(#{1,6})\s/.test(t[r])&&!/^\s*([-*+]|\d+[.)])\s+/.test(t[r])&&!/^>\s?/.test(t[r])&&!(sg(t[r])&&r+1<t.length&&cg(t[r+1]));)s.push(t[r++].trim());n.push({kind:`paragraph`,children:ug(s.join(` `))})}return n}function ug(e){let t=[],n=e,r=e=>{let n=t[t.length-1];e.kind===`text`&&n?.kind===`text`?n.text+=e.text:t.push(e)};for(;n.length;){let e=/^`([^`]+)`/.exec(n);if(e){r({kind:`code`,text:e[1]}),n=n.slice(e[0].length);continue}let t=/^\[([^\]]+)\]\((https?:\/\/[^\s)]+|\/[^\s)]*|#[^\s)]*)\)/.exec(n);if(t){r({kind:`link`,href:t[2],children:ug(t[1])}),n=n.slice(t[0].length);continue}let i=/^(\*\*|__)(.+?)\1/.exec(n);if(i){r({kind:`strong`,children:ug(i[2])}),n=n.slice(i[0].length);continue}let a=/^(\*|_)([^*_]+?)\1/.exec(n);if(a){r({kind:`em`,children:ug(a[2])}),n=n.slice(a[0].length);continue}let o=n.slice(1).search(/[`*_[]/),s=o===-1?n.length:o+1;r({kind:`text`,text:n.slice(0,s)}),n=n.slice(s)}return t}var dg=(0,b.forwardRef)(function({text:e,streaming:t=!1,className:n,...r},i){let a=lg(e);return(0,x.jsxs)(`div`,{ref:i,className:R(`z-markdown`,n),"data-streaming":t||void 0,...r,children:[a.map((e,n)=>(0,x.jsx)(fg,{block:e,last:n===a.length-1,streaming:t},n)),t&&a.length===0&&(0,x.jsx)(`span`,{className:`z-markdown__cursor`,"aria-hidden":`true`})]})});function fg({block:e,last:t,streaming:n}){let r=t&&n?(0,x.jsx)(`span`,{className:`z-markdown__cursor`,"aria-hidden":`true`}):null;switch(e.kind){case`paragraph`:return(0,x.jsxs)(`p`,{children:[(0,x.jsx)(pg,{nodes:e.children}),r]});case`heading`:{let t=`h${e.level}`;return(0,x.jsxs)(t,{children:[(0,x.jsx)(pg,{nodes:e.children}),r]})}case`list`:{let t=e.ordered?`ol`:`ul`;return(0,x.jsx)(t,{children:e.items.map((t,n)=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(pg,{nodes:t}),n===e.items.length-1?r:null]},n))})}case`code`:return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(ag,{code:e.code,language:e.language||void 0}),r]});case`quote`:return(0,x.jsxs)(`blockquote`,{children:[(0,x.jsx)(pg,{nodes:e.children}),r]});case`table`:return(0,x.jsxs)(Y,{density:`sm`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsx)(Y.Row,{children:e.header.map((e,t)=>(0,x.jsx)(Y.HeadCell,{children:(0,x.jsx)(pg,{nodes:e})},t))})}),(0,x.jsx)(Y.Body,{children:e.rows.map((e,t)=>(0,x.jsx)(Y.Row,{children:e.map((e,t)=>(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(pg,{nodes:e})},t))},t))})]});case`rule`:return(0,x.jsx)(`hr`,{})}}function pg({nodes:e}){return e.map((e,t)=>{switch(e.kind){case`text`:return e.text;case`code`:return(0,x.jsx)(`code`,{children:e.text},t);case`strong`:return(0,x.jsx)(`strong`,{children:(0,x.jsx)(pg,{nodes:e.children})},t);case`em`:return(0,x.jsx)(`em`,{children:(0,x.jsx)(pg,{nodes:e.children})},t);case`link`:return(0,x.jsx)(`a`,{href:e.href,target:e.href.startsWith(`http`)?`_blank`:void 0,rel:e.href.startsWith(`http`)?`noreferrer`:void 0,children:(0,x.jsx)(pg,{nodes:e.children})},t)}})}var mg=Object.defineProperty,hg=(e,t)=>mg(e,`name`,{value:t,configurable:!0}),gg=`Tabs`,[_g,vg]=T(gg,[rc]),yg=rc(),[bg,xg]=_g(gg),Sg=b.forwardRef(hg(function(e,t){let{__scopeTabs:n,value:r,onValueChange:i,defaultValue:a,orientation:o=`horizontal`,dir:s,activationMode:c=`automatic`,...l}=e,u=G(s),[d,f]=kt({prop:r,onChange:i,defaultProp:a??``,caller:gg});return(0,x.jsx)(bg,{scope:n,baseId:bt(),value:d,onValueChange:f,orientation:o,dir:u,activationMode:c,children:(0,x.jsx)(L.div,{dir:u,"data-orientation":o,...l,ref:t})})},`Tabs`)),Cg=`TabsList`,wg=b.forwardRef(hg(function(e,t){let{__scopeTabs:n,loop:r=!0,...i}=e,a=xg(Cg,n),o=yg(n);return(0,x.jsx)(hc,{asChild:!0,...o,orientation:a.orientation,dir:a.dir,loop:r,children:(0,x.jsx)(L.div,{role:`tablist`,"aria-orientation":a.orientation,...i,ref:t})})},`TabsList`)),Tg=`TabsTrigger`,Eg=b.forwardRef(hg(function(e,t){let{__scopeTabs:n,value:r,disabled:i=!1,...a}=e,o=xg(Tg,n),s=yg(n),c=kg(o.baseId,r),l=Ag(o.baseId,r),u=r===o.value;return(0,x.jsx)(gc,{asChild:!0,...s,focusable:!i,active:u,children:(0,x.jsx)(L.button,{type:`button`,role:`tab`,"aria-selected":u,"aria-controls":l,"data-state":u?`active`:`inactive`,"data-disabled":i?``:void 0,disabled:i,id:c,...a,ref:t,onMouseDown:U(e.onMouseDown,e=>{!i&&e.button===0&&e.ctrlKey===!1?o.onValueChange(r):e.preventDefault()}),onKeyDown:U(e.onKeyDown,e=>{i||e.target!==e.currentTarget||[` `,`Enter`].includes(e.key)&&o.onValueChange(r)}),onFocus:U(e.onFocus,()=>{let e=o.activationMode!==`manual`;!u&&!i&&e&&o.onValueChange(r)})})})},`TabsTrigger`)),Dg=`TabsContent`,Og=b.forwardRef(hg(function(e,t){let{__scopeTabs:n,value:r,forceMount:i,children:a,...o}=e,s=xg(Dg,n),c=kg(s.baseId,r),l=Ag(s.baseId,r),u=r===s.value,d=b.useRef(u);return b.useEffect(()=>{let e=requestAnimationFrame(()=>d.current=!1);return()=>cancelAnimationFrame(e)},[]),(0,x.jsx)(bn,{present:i||u,children:({present:n})=>(0,x.jsx)(L.div,{"data-state":u?`active`:`inactive`,"data-orientation":s.orientation,role:`tabpanel`,"aria-labelledby":c,hidden:!n,id:l,tabIndex:0,...o,ref:t,style:{...e.style,animationDuration:d.current?`0s`:void 0},children:n&&a})})},`TabsContent`));function kg(e,t){return`${e}-trigger-${t}`}hg(kg,`makeTriggerId`);function Ag(e,t){return`${e}-content-${t}`}hg(Ag,`makeContentId`);var jg=Sg,Mg=wg,Ng=Eg,Pg=Og,Fg=(0,b.forwardRef)(function({variant:e=`line`,size:t=`md`,className:n,...r},i){return(0,x.jsx)(jg,{ref:i,className:R(`z-tabs`,n),"data-variant":e,"data-size":t,...r})}),Ig=(0,b.forwardRef)(function({className:e,...t},n){return(0,x.jsx)(Mg,{ref:n,className:R(`z-tabs__list`,e),...t})}),Lg=(0,b.forwardRef)(function({className:e,...t},n){return(0,x.jsx)(Ng,{ref:n,className:R(`z-tabs__trigger z-focusable`,e),...t})}),Rg=(0,b.forwardRef)(function({className:e,...t},n){return(0,x.jsx)(Pg,{ref:n,className:R(`z-tabs__content z-focusable`,e),...t})}),Z=Object.assign(Fg,{List:Ig,Trigger:Lg,Content:Rg}),zg=(0,b.forwardRef)(function({variant:e=`text`,width:t,height:n,lines:r=1,className:i,style:a,...o},s){return e===`text`&&r>1?(0,x.jsx)(`span`,{ref:s,className:R(`z-skeleton-lines`,i),"aria-hidden":`true`,style:a,...o,children:Array.from({length:r},(e,n)=>(0,x.jsx)(`span`,{className:`z-skeleton`,"data-variant":`text`,style:{width:n===r-1?`60%`:t}},n))}):(0,x.jsx)(`span`,{ref:s,className:R(`z-skeleton`,i),"data-variant":e,"aria-hidden":`true`,style:{width:t,height:n,...a},...o})}),Bg=(0,b.forwardRef)(function({label:e=`Thinking`,showLabel:t=!1,size:n=`md`,className:r,...i},a){return(0,x.jsxs)(`span`,{ref:a,className:R(`z-loader`,r),"data-size":n,role:`status`,"aria-label":e,...i,children:[(0,x.jsxs)(`span`,{className:`z-loader__dots`,"aria-hidden":`true`,children:[(0,x.jsx)(`span`,{}),(0,x.jsx)(`span`,{}),(0,x.jsx)(`span`,{})]}),t&&(0,x.jsx)(`span`,{className:`z-loader__label`,children:e})]})}),Vg=(0,b.forwardRef)(function({title:e,description:t,icon:n,action:r,size:i=`md`,tone:a=`neutral`,className:o,...s},c){return(0,x.jsxs)(`div`,{ref:c,className:R(`z-empty`,o),"data-size":i,"data-tone":a,...s,children:[n&&(0,x.jsx)(`span`,{className:`z-empty__icon`,"aria-hidden":`true`,children:n}),(0,x.jsx)(`p`,{className:`z-empty__title`,children:e}),t&&(0,x.jsx)(`p`,{className:`z-empty__description`,children:t}),r&&(0,x.jsx)(`div`,{className:`z-empty__action`,children:r})]})});function Hg({columns:e,cards:t,cardId:n,cardColumn:r,renderCard:i,cardLabel:a,onMove:o,density:s=`md`,label:c,className:l}){let[u,d]=(0,b.useState)(null),[f,p]=(0,b.useState)(null),[m,h]=(0,b.useState)(``),g=(0,b.useId)(),_=(0,b.useRef)(new Map),v=(0,b.useCallback)(e=>t.filter(t=>r(t)===e),[t,r]),y=(0,b.useCallback)((e,t,r,i)=>{(t!==r||v(t).findIndex(t=>n(t)===e)!==i)&&o?.({cardId:e,from:t,to:r,index:i})},[v,n,o]);(0,b.useEffect)(()=>{u&&_.current.get(u.id)?.focus()},[u,t]);let S=(e,t)=>{u&&(y(u.id,u.column,e,t),d(null),p(null))},C=(t,i,o,s)=>{if(t.target!==t.currentTarget)return;let c=n(i),l=t.key;if(l===` `||l===`Enter`){if(t.preventDefault(),!u)d({id:c,column:r(i),index:s}),h(`${a(i)} lifted. Use the arrow keys to move it, Enter to drop, Escape to cancel.`);else{let t=f??{column:u.column,index:u.index},n=e.find(e=>e.id===t.column);y(u.id,u.column,t.column,t.index),h(`${a(i)} moved to ${typeof n?.title==`string`?n.title:t.column}, position ${t.index+1}.`),d(null),p(null)}return}if(l===`Escape`&&u){t.preventDefault(),h(`${a(i)} put back.`),d(null),p(null);return}if(!u)return;let m=f??{column:u.column,index:u.index},g=e.findIndex(e=>e.id===m.column);if(l===`ArrowLeft`||l===`ArrowRight`){t.preventDefault();let r=e[g+(l===`ArrowRight`?1:-1)];if(!r)return;let i=v(r.id).filter(e=>n(e)!==u.id).length,a=Math.min(m.index,i);p({column:r.id,index:a}),h(`Over ${typeof r.title==`string`?r.title:r.id}, position ${a+1}.`);return}if(l===`ArrowUp`||l===`ArrowDown`){t.preventDefault();let e=v(m.column).filter(e=>n(e)!==u.id).length,r=Math.max(0,Math.min(e,m.index+(l===`ArrowDown`?1:-1)));p({column:m.column,index:r}),h(`Position ${r+1}.`)}};return(0,x.jsxs)(`div`,{className:R(`z-kanban`,l),"data-density":s,role:`group`,"aria-label":c,children:[(0,x.jsx)(`p`,{className:`z-sr-only`,role:`status`,"aria-live":`polite`,children:m}),e.map((e,t)=>{let r=v(e.id),o=f?.column===e.id,s=e.limit!==void 0&&r.length>e.limit;return(0,x.jsxs)(`section`,{className:`z-kanban__column`,"data-over":o||void 0,"aria-labelledby":`${g}-${e.id}`,onDragOver:t=>{u&&(t.preventDefault(),p({column:e.id,index:r.filter(e=>n(e)!==u.id).length}))},onDrop:t=>{t.preventDefault(),S(e.id,f?.column===e.id?f.index:r.length)},children:[(0,x.jsxs)(`header`,{className:`z-kanban__head`,children:[(0,x.jsx)(`h3`,{className:`z-kanban__title`,id:`${g}-${e.id}`,children:e.title}),(0,x.jsx)(z,{size:`sm`,tone:s?`warning`:`neutral`,variant:`outline`,children:e.limit===void 0?r.length:`${r.length}/${e.limit}`})]}),(0,x.jsxs)(`ul`,{className:`z-kanban__list`,children:[r.map((r,s)=>{let c=n(r),l=u?.id===c;return(0,x.jsx)(`li`,{className:`z-kanban__slot`,"data-drop":o&&f?.index===s?``:void 0,children:(0,x.jsx)(`article`,{ref:e=>{e?_.current.set(c,e):_.current.delete(c)},className:`z-kanban__card z-focusable`,tabIndex:0,draggable:!0,"data-lifted":l||void 0,"aria-roledescription":`Draggable card`,"aria-label":a(r),"aria-grabbed":l||void 0,onKeyDown:e=>C(e,r,t,s),onDragStart:()=>d({id:c,column:e.id,index:s}),onDragEnd:()=>{d(null),p(null)},children:i(r)})},c)}),r.length===0&&(0,x.jsx)(`li`,{className:`z-kanban__slot`,"data-drop":o?``:void 0,children:e.empty??(0,x.jsx)(Vg,{size:`sm`,title:`Nothing here`})})]})]},e.id)})]})}function Ug(e,t){return`${e}-option-${t}`}function Wg(e){let{options:t,label:n,description:r,error:i,placeholder:a,size:o=`md`,disabled:s,emptyMessage:c=`No matches`,className:l,id:u}=e,d=e.multiple===!0,f=(0,b.useId)(),p=u??f,m=`${p}-list`,[h,g]=(0,b.useState)(!1),[_,v]=(0,b.useState)(``),[y,S]=(0,b.useState)(0),C=(0,b.useRef)(null),w=(0,b.useRef)(null),T=(0,b.useRef)(null),E=(0,b.useMemo)(()=>{if(d)return e.value??[];let t=e.value;return t?[t]:[]},[d,e]),D=(0,b.useMemo)(()=>new Map(t.map(e=>[e.value,e])),[t]),O=(0,b.useMemo)(()=>{let e=_.trim().toLowerCase();return e?t.filter(t=>t.label.toLowerCase().includes(e)||(t.hint??``).toLowerCase().includes(e)):t},[t,_,d]);(0,b.useEffect)(()=>S(0),[_,h]),(0,b.useEffect)(()=>{if(!h)return;let e=e=>{T.current?.contains(e.target)||g(!1)};return document.addEventListener(`pointerdown`,e),()=>document.removeEventListener(`pointerdown`,e)},[h]),(0,b.useEffect)(()=>{h&&w.current?.querySelector(`[data-active="true"]`)?.scrollIntoView({block:`nearest`})},[y,h]);let k=t=>{if(!t.disabled){if(d){let n=E.includes(t.value)?E.filter(e=>e!==t.value):[...E,t.value];e.onValueChange?.(n),v(``),C.current?.focus();return}e.onValueChange?.(t.value),v(``),g(!1)}},A=t=>{d&&(e.onValueChange?.(E.filter(e=>e!==t)),C.current?.focus())},j=e=>{let t=e.key;if(t===`ArrowDown`||t===`ArrowUp`){if(e.preventDefault(),!h){g(!0);return}let n=t===`ArrowDown`?1:-1;for(let e=1;e<=O.length;e++){let t=(y+n*e+O.length*e)%O.length;if(!O[t]?.disabled){S(t);return}}return}if(t===`Enter`&&h){let t=O[y];t&&(e.preventDefault(),k(t));return}if(t===`Escape`){h&&(e.preventDefault(),g(!1));return}t===`Backspace`&&d&&_===``&&E.length&&A(E[E.length-1])},ee=(0,b.useMemo)(()=>{let e=[];for(let t of O){let n=e[e.length-1];n&&n.name===t.group?n.options.push(t):e.push({name:t.group,options:[t]})}return e},[O]),M=-1,N=[r?`${p}-description`:null,i?`${p}-error`:null].filter(Boolean).join(` `)||void 0;return(0,x.jsxs)(`div`,{ref:T,className:R(`z-combobox`,l),"data-size":o,"data-invalid":i?``:void 0,"data-disabled":s||void 0,children:[(0,x.jsx)(`label`,{className:`z-combobox__label`,htmlFor:p,children:n}),(0,x.jsxs)(`div`,{className:`z-combobox__control`,children:[d&&E.map(e=>(0,x.jsxs)(z,{size:`sm`,tone:`neutral`,variant:`soft`,className:`z-combobox__chip`,children:[D.get(e)?.label??e,(0,x.jsx)(`button`,{type:`button`,className:`z-combobox__remove z-focusable`,"aria-label":`Remove ${D.get(e)?.label??e}`,onClick:()=>A(e),disabled:s,children:(0,x.jsx)(H.Close,{size:12})})]},e)),(0,x.jsx)(`input`,{ref:C,id:p,className:`z-combobox__input z-focusable`,role:`combobox`,type:`text`,autoComplete:`off`,"aria-expanded":h,"aria-controls":m,"aria-autocomplete":`list`,"aria-activedescendant":h&&O[y]?Ug(p,y):void 0,"aria-describedby":N,"aria-invalid":i?!0:void 0,disabled:s,placeholder:d||!E.length?a:D.get(E[0])?.label,value:_,onChange:e=>{v(e.target.value),g(!0)},onFocus:()=>g(!0),onKeyDown:j}),(0,x.jsx)(`span`,{className:`z-combobox__chevron`,"aria-hidden":`true`,children:(0,x.jsx)(H.ChevronDown,{size:16})})]}),h&&(0,x.jsxs)(`ul`,{ref:w,className:`z-combobox__list`,id:m,role:`listbox`,"aria-label":typeof n==`string`?n:void 0,"aria-multiselectable":d||void 0,children:[ee.map((e,t)=>(0,x.jsxs)(`li`,{className:`z-combobox__group`,role:`presentation`,children:[e.name&&(0,x.jsx)(`p`,{className:`z-combobox__group-name`,children:e.name}),(0,x.jsx)(`ul`,{role:`presentation`,children:e.options.map(e=>{M+=1;let t=M,n=E.includes(e.value);return(0,x.jsxs)(`li`,{id:Ug(p,t),"data-value":e.value,className:`z-combobox__option`,role:`option`,"aria-selected":n,"aria-disabled":e.disabled||void 0,"data-active":t===y,"data-selected":n||void 0,onPointerDown:t=>{t.preventDefault(),k(e)},onPointerEnter:()=>S(t),children:[(0,x.jsx)(`span`,{className:`z-combobox__option-label`,children:e.label}),e.hint&&(0,x.jsx)(`span`,{className:`z-combobox__option-hint`,children:e.hint}),n&&(0,x.jsx)(`span`,{className:`z-combobox__tick`,"aria-hidden":`true`,children:(0,x.jsx)(H.Check,{size:14})})]},e.value)})})]},e.name??`g${t}`)),O.length===0&&(0,x.jsx)(`li`,{className:`z-combobox__empty`,role:`presentation`,children:c})]}),r&&!i&&(0,x.jsx)(`p`,{className:`z-combobox__description`,id:`${p}-description`,children:r}),i&&(0,x.jsx)(`p`,{className:`z-combobox__error`,id:`${p}-error`,children:i})]})}var Gg=[`new`,`reviewing`,`applying`,`ready`,`applied`,`interviewing`,`offer`,`rejected`,`passed`],Kg=[`wrong role shape`,`weak evidence match`,`compensation`,`location or authorisation`,`too managerial`,`too visual`,`too engineering`,`stale or duplicate`,`company`],qg=[`recruiter`,`hiring-manager`,`interviewer`,`referral`,`other`];async function Q(e,t){let n=await fetch(e,{headers:{"content-type":`application/json`},...t}),r=await n.json().catch(()=>({}));if(!n.ok)throw Error(r.error||`${n.status} ${n.statusText}`);return r}var $={summary:()=>Q(`/api/summary`),jobs:e=>{let t=new URLSearchParams;for(let[n,r]of Object.entries(e))r!==void 0&&r!==``&&r!==null&&t.set(n,String(r));return Q(`/api/jobs?${t}`)},facets:e=>{let t=new URLSearchParams;for(let[n,r]of Object.entries(e))r!==void 0&&r!==``&&r!==null&&t.set(n,String(r));return Q(`/api/jobs/facets?${t}`)},job:e=>Q(`/api/jobs/${encodeURIComponent(e)}`),attachPosting:(e,t,n=!1)=>Q(`/api/jobs/${encodeURIComponent(e)}/attach`,{method:`POST`,body:JSON.stringify({url:t,linkOnly:n})}),settings:()=>Q(`/api/settings`),saveSettings:e=>Q(`/api/settings`,{method:`PUT`,body:JSON.stringify(e)}),resumes:()=>Q(`/api/resumes`),useResume:e=>Q(`/api/resumes/use`,{method:`POST`,body:JSON.stringify({name:e})}),openResume:e=>Q(`/api/resumes/open`,{method:`POST`,body:JSON.stringify({name:e})}),revealJob:e=>Q(`/api/jobs/${encodeURIComponent(e)}/reveal`,{method:`POST`}),importLinks:e=>Q(`/api/jobs/import`,{method:`POST`,body:JSON.stringify({urls:e})}),today:(e=7)=>Q(`/api/today?cap=${e}`),setStatus:(e,t,n)=>Q(`/api/jobs/${encodeURIComponent(e)}`,{method:`PATCH`,body:JSON.stringify({status:t,reason:n})}),addNote:(e,t)=>Q(`/api/jobs/${encodeURIComponent(e)}`,{method:`PATCH`,body:JSON.stringify({note:t})}),packet:e=>Q(`/api/jobs/${encodeURIComponent(e)}/packet`),coverLetter:e=>Q(`/api/jobs/${encodeURIComponent(e)}/cover-letter`),writeCoverLetter:(e,t)=>Q(`/api/jobs/${encodeURIComponent(e)}/cover-letter`,{method:`POST`,body:JSON.stringify(t)}),tailoredResume:e=>Q(`/api/jobs/${encodeURIComponent(e)}/resume`),writeTailoredResume:(e,t)=>Q(`/api/jobs/${encodeURIComponent(e)}/resume`,{method:`POST`,body:JSON.stringify(t)}),saveTailoredResume:(e,t)=>Q(`/api/jobs/${encodeURIComponent(e)}/resume`,{method:`PUT`,body:JSON.stringify({text:t})}),resumePrintUrl:e=>`/api/jobs/${encodeURIComponent(e)}/resume.html`,saveCoverLetter:(e,t)=>Q(`/api/jobs/${encodeURIComponent(e)}/cover-letter`,{method:`PUT`,body:JSON.stringify({text:t})}),saveApplication:(e,t,n)=>Q(`/api/jobs/${encodeURIComponent(e)}`,{method:`PATCH`,body:JSON.stringify({application:{field:t,value:n}})}),runs:()=>Q(`/api/runs`),scan:()=>Q(`/api/scan`),startScan:(e=!1,t,n=!1)=>Q(`/api/scan`,{method:`POST`,body:JSON.stringify({dry:e,criteria:t||``,retryFailed:n})}),criteria:()=>Q(`/api/criteria`),saveCriteria:e=>Q(`/api/criteria`,{method:`PUT`,body:JSON.stringify({raw:e})}),outcomes:()=>Q(`/api/outcomes`),views:()=>Q(`/api/views`),defaultViews:()=>Q(`/api/views/defaults`),saveViews:e=>Q(`/api/views`,{method:`PUT`,body:JSON.stringify({views:e})}),mail:()=>Q(`/api/mail`),mailCheck:e=>Q(`/api/mail/check`,{method:`POST`,body:JSON.stringify({sinceDays:e})}),mailConfirm:(e,t)=>Q(`/api/mail/${encodeURIComponent(e)}/confirm`,{method:`POST`,body:JSON.stringify({noteId:t})}),mailConfirmSafe:()=>Q(`/api/mail/confirm-safe`,{method:`POST`}),mailDismiss:e=>Q(`/api/mail/${encodeURIComponent(e)}/dismiss`,{method:`POST`}),previewCriteria:e=>Q(`/api/criteria/preview`,{method:`POST`,body:JSON.stringify({raw:e})}),rescoreNotes:(e=!1)=>Q(`/api/rescore`,{method:`POST`,body:JSON.stringify({dry:e})}),criteriaPresets:()=>Q(`/api/criteria/presets`),criteriaPreset:e=>Q(`/api/criteria/presets/${encodeURIComponent(e)}`),saveCriteriaPreset:(e,t)=>Q(`/api/criteria/presets/${encodeURIComponent(e)}`,{method:`PUT`,body:JSON.stringify({raw:t})}),deleteCriteriaPreset:e=>Q(`/api/criteria/presets/${encodeURIComponent(e)}`,{method:`DELETE`}),activateCriteriaPreset:e=>Q(`/api/criteria/presets/${encodeURIComponent(e)}/activate`,{method:`POST`}),profileNotes:()=>Q(`/api/profile`),profileSummary:()=>Q(`/api/profile/summary`),saveProfileNote:(e,t)=>Q(`/api/profile`,{method:`PUT`,body:JSON.stringify({note:e,markdown:t})}),snippets:()=>Q(`/api/snippets`),saveSnippets:e=>Q(`/api/snippets`,{method:`PUT`,body:JSON.stringify({items:e})}),people:()=>Q(`/api/people`),person:e=>Q(`/api/people/${encodeURIComponent(e)}`),addPerson:e=>Q(`/api/people`,{method:`POST`,body:JSON.stringify(e)}),attachPerson:(e,t,n,r)=>Q(`/api/people/${encodeURIComponent(e)}/attach`,{method:`POST`,body:JSON.stringify({jobId:t,role:n,context:r})}),logContact:(e,t,n)=>Q(`/api/people/${encodeURIComponent(e)}/log`,{method:`POST`,body:JSON.stringify({text:t,date:n})}),jobPeople:e=>Q(`/api/jobs/${encodeURIComponent(e)}/people`),jobConnections:e=>Q(`/api/jobs/${encodeURIComponent(e)}/connections`),linkedinStatus:()=>Q(`/api/linkedin`),linkedinPreview:(e,t,n)=>Q(`/api/linkedin/preview`,{method:`POST`,body:JSON.stringify({source:e,since:t,everyone:n})}),linkedinImport:(e,t={})=>Q(`/api/linkedin/import`,{method:`POST`,body:JSON.stringify({source:e,...t})}),companies:()=>Q(`/api/companies`),addCompany:e=>Q(`/api/companies`,{method:`POST`,body:JSON.stringify(e)}),feeds:()=>Q(`/api/feeds`),onboarding:()=>Q(`/api/onboarding`),initProfile:()=>Q(`/api/onboarding/init`,{method:`POST`,body:`{}`}),importResume:e=>Q(`/api/onboarding/resume`,{method:`POST`,body:JSON.stringify({path:e})})},Jg=e=>`$${Math.round(e/1e3)}k`,Yg=e=>e.replace(/\s*[•·].*$/,``).replace(/\s+/g,` `).trim(),Xg=e=>{if(!e)return``;let t=Math.floor((Date.now()-new Date(e).getTime())/864e5);return Number.isFinite(t)?t<=0?`today`:`${t}d ago`:``},Zg={floor:`Floor`,stretch:`Stretch`,below:`Below`,unknown:`Not stated`},Qg={floor:`success`,stretch:`warning`,below:`neutral`,unknown:`neutral`},$g={new:`neutral`,reviewing:`primary`,applying:`primary`,ready:`warning`,applied:`primary`,interviewing:`warning`,offer:`success`,rejected:`danger`,passed:`neutral`};function e_(e){let[t,n]=(0,b.useState)(()=>typeof window<`u`&&window.matchMedia(e).matches);return(0,b.useEffect)(()=>{let t=window.matchMedia(e),r=()=>n(t.matches);return r(),t.addEventListener(`change`,r),()=>t.removeEventListener(`change`,r)},[e]),t}var t_={name:`TekJobs`,logo:`/brand/tekjobs-avatar-192.png`};function n_({href:e=`/`}){return(0,x.jsxs)(`a`,{className:`brand-mark`,href:e,"aria-label":t_.name,children:[t_.logo&&(0,x.jsx)(`img`,{className:`brand-mark__logo`,src:t_.logo,alt:``}),(0,x.jsxs)(`span`,{"aria-hidden":`true`,children:[`Tek`,(0,x.jsx)(`span`,{className:`brand-mark__accent`,children:`Jobs`})]})]})}function r_(){let[e,t]=(0,b.useState)(!1),[n,r]=(0,b.useState)(null),[i,a]=(0,b.useState)(``),[o,s]=(0,b.useState)(null),[c,l]=(0,b.useState)(!1),u=(0,b.useRef)(null),d=()=>$.snippets().then(r).catch(e=>X({title:`Could not load the copy panel`,description:e.message,tone:`danger`}));(0,b.useEffect)(()=>{e&&!n&&d()},[e]),(0,b.useEffect)(()=>{e?setTimeout(()=>u.current?.focus(),30):a(``)},[e]);let f=(0,b.useMemo)(()=>{let e=i.trim().toLowerCase(),t=(n?.items??[]).filter(t=>t.value&&(!e||`${t.group} ${t.label} ${t.value}`.toLowerCase().includes(e))),r=new Map;for(let e of t){let t=e.group||`Other`;r.has(t)||r.set(t,[]),r.get(t).push(e)}return[...r.entries()]},[n,i]),p=async e=>{try{await navigator.clipboard.writeText(e.value),s(e.label),setTimeout(()=>s(t=>t===e.label?null:t),1600)}catch(e){X({title:`Could not copy`,description:e.message,tone:`danger`})}},m=f[0]?.[1][0];return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(fd,{open:e,onOpenChange:t,size:`lg`,children:[(0,x.jsx)(Bh,{content:`Copy panel`,children:(0,x.jsx)(fd.Trigger,{asChild:!0,children:(0,x.jsx)(B,{variant:`ghost`,size:`sm`,"aria-label":`Copy panel`,leadingIcon:(0,x.jsx)(H.Copy,{})})})}),(0,x.jsx)(fd.Content,{align:`end`,showArrow:!1,children:(0,x.jsxs)(`div`,{className:`copy`,children:[(0,x.jsx)(`form`,{className:`copy__search`,onSubmit:e=>{e.preventDefault(),m&&p(m)},children:(0,x.jsx)(Zp,{ref:u,size:`sm`,"aria-label":`Find a snippet`,placeholder:`Find, then Enter copies the first`,leadingIcon:(0,x.jsx)(H.Search,{}),value:i,onChange:e=>a(e.target.value)})}),n?f.length===0?(0,x.jsx)(`p`,{className:`muted copy__empty`,children:n.items.length===0?`Nothing here yet. Customize adds lines.`:i?`Nothing matches.`:`Every snippet is empty. Customize fills them in.`}):(0,x.jsx)(`div`,{className:`copy__groups`,children:f.map(([e,t])=>(0,x.jsxs)(`div`,{className:`copy__group`,children:[(0,x.jsx)(`div`,{className:`microlabel`,children:e}),t.map(t=>(0,x.jsx)(B,{asChild:!0,variant:`ghost`,tone:`neutral`,size:`sm`,align:`start`,className:`copy__row`,children:(0,x.jsxs)(`button`,{type:`button`,onClick:()=>p(t),title:t.value,children:[(0,x.jsx)(`span`,{className:`copy__label`,children:t.label}),(0,x.jsxs)(`span`,{className:`copy__value num`,children:[o===t.label?`Copied`:t.value.split(`
|
|
58
58
|
`)[0],t.value.includes(`
|
|
59
59
|
`)&&o!==t.label?` …`:``]})]})},`${e}:${t.label}`))]},e))}):(0,x.jsx)(zg,{lines:4}),(0,x.jsxs)(`div`,{className:`copy__foot`,children:[(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,leadingIcon:(0,x.jsx)(H.Edit,{}),onClick:()=>{t(!1),l(!0)},children:`Customize`}),n&&!n.exists&&(0,x.jsx)(`span`,{className:`muted`,children:`Read from your profile until you save once.`})]})]})})]}),c&&n&&(0,x.jsx)(i_,{initial:n.items,path:n.path,onClose:()=>l(!1),onSaved:e=>{r(e),l(!1)}})]})}function i_({initial:e,path:t,onClose:n,onSaved:r}){let[i,a]=(0,b.useState)(e.length?e:[{group:``,label:``,value:``}]),[o,s]=(0,b.useState)(!1),c=(e,t)=>a(n=>n.map((n,r)=>r===e?{...n,...t}:n)),l=(e,t)=>a(n=>{let r=e+t;if(r<0||r>=n.length)return n;let i=[...n];return[i[e],i[r]]=[i[r],i[e]],i}),u=e=>a(t=>t.filter((t,n)=>n!==e));return(0,x.jsx)(Sp,{open:!0,onOpenChange:e=>!e&&n(),side:`right`,size:`md`,children:(0,x.jsx)(Sp.Content,{children:(0,x.jsxs)(`div`,{className:`detail`,children:[(0,x.jsx)(Sp.Title,{children:`Customize the copy panel`}),(0,x.jsxs)(Sp.Description,{children:[`Label is the button, group is its heading, value is what lands on the clipboard. Lines with no label are dropped. Saved to `,(0,x.jsx)(`code`,{className:`mono`,children:t.split(/[\\/]/).slice(-2).join(`/`)}),`, so Obsidian works too.`]}),(0,x.jsx)(`div`,{className:`copy__rows`,children:i.map((e,t)=>(0,x.jsxs)(`div`,{className:`copy__edit`,children:[(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(Zp,{size:`sm`,label:`Label`,value:e.label,onChange:e=>c(t,{label:e.target.value})}),(0,x.jsx)(Zp,{size:`sm`,label:`Group`,value:e.group,onChange:e=>c(t,{group:e.target.value})})]}),(0,x.jsx)(Xp,{label:`Value`,rows:e.value.includes(`
|
|
60
|
-
`)?4:1,value:e.value,onChange:e=>c(t,{value:e.target.value})}),(0,x.jsxs)(`div`,{className:`copy__edit-actions`,children:[(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,"aria-label":`Move up`,leadingIcon:(0,x.jsx)(H.ArrowUp,{}),disabled:t===0,onClick:()=>l(t,-1)}),(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,"aria-label":`Move down`,leadingIcon:(0,x.jsx)(H.ArrowDown,{}),disabled:t===i.length-1,onClick:()=>l(t,1)}),(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`danger`,"aria-label":`Remove`,leadingIcon:(0,x.jsx)(H.Trash,{}),onClick:()=>u(t)})]})]},t))}),(0,x.jsxs)(`div`,{className:`form__actions`,children:[(0,x.jsx)(B,{size:`sm`,variant:`soft`,tone:`neutral`,leadingIcon:(0,x.jsx)(H.Plus,{}),onClick:()=>a(e=>[...e,{group:e[e.length-1]?.group??``,label:``,value:``}]),children:`Add a line`}),(0,x.jsx)(`span`,{className:`toolbar__spacer`}),(0,x.jsx)(B,{size:`sm`,variant:`ghost`,onClick:n,children:`Cancel`}),(0,x.jsx)(B,{size:`sm`,tone:`primary`,loading:o,onClick:async()=>{s(!0);try{let e=await $.saveSnippets(i);X({title:`Copy panel saved`,description:`Profile/Snippets.md`,tone:`success`}),r(e)}catch(e){X({title:`Not saved`,description:e.message,tone:`danger`})}s(!1)},children:`Save`})]})]})})})}var a_=[{page:`onboarding`,label:`Get started`,icon:H.Sparkles},{page:`today`,label:`Today`,icon:H.Star},{page:`overview`,label:`Overview`,icon:H.Home},{page:`jobs`,label:`Jobs`,icon:H.Inbox},{page:`pipeline`,label:`Pipeline`,icon:H.Layers},{page:`mail`,label:`Mail`,icon:H.Mail},{page:`people`,label:`People`,icon:H.Users},{page:`companies`,label:`Sources`,icon:H.Globe},{page:`criteria`,label:`Criteria`,icon:H.Filter},{page:`profile`,label:`Profile`,icon:H.User},{page:`runs`,label:`Runs`,icon:H.Refresh},{page:`agent`,label:`Agent access`,icon:H.Terminal},{page:`settings`,label:`Settings`,icon:H.Settings}],o_={onboarding:`Get started`,today:`Today`,overview:`Overview`,jobs:`Jobs`,pipeline:`Pipeline`,mail:`Mail`,people:`People`,companies:`Sources`,criteria:`Criteria`,profile:`Profile`,runs:`Runs`,agent:`Agent access`,settings:`Settings`},s_=[{title:`Work`,pages:[`today`,`jobs`,`pipeline`,`mail`,`people`]},{title:`Insights`,pages:[`overview`]},{title:`Setup`,pages:[`profile`,`criteria`,`companies`]},{title:`System`,pages:[`runs`,`agent`,`settings`,`onboarding`]}];function c_({page:e,onNavigate:t,onSearch:n,theme:r,onToggleTheme:i,onboarded:a=!0,counts:o={},lastScan:s=``,children:c}){let[l,u]=(0,b.useState)(!1),d=e_(`(max-width: 40rem)`),[f,p]=(0,b.useState)(``),[m,h]=(0,b.useState)(()=>{try{return localStorage.getItem(`tekjobs.sidebar`)===`collapsed`}catch{return!1}}),g=()=>h(e=>{try{localStorage.setItem(`tekjobs.sidebar`,e?`open`:`collapsed`)}catch{}return!e}),_=e=>{t(e),u(!1)};return(0,x.jsxs)(`div`,{className:`shell${m?` shell--collapsed`:``}${d?` shell--strip`:``}`,children:[(0,x.jsx)(`aside`,{className:`sidebar`,"aria-label":`Primary`,children:(0,x.jsx)(l_,{page:e,onNavigate:_,onboarded:a,counts:o,lastScan:s,collapsed:m||d,onToggleCollapsed:d?void 0:g,tipSide:d?`bottom`:`right`})}),(0,x.jsxs)(`div`,{className:`main`,children:[(0,x.jsxs)(`header`,{className:`topbar`,children:[(0,x.jsxs)(Sp,{open:l,onOpenChange:u,side:`left`,size:`sm`,children:[(0,x.jsx)(Sp.Trigger,{asChild:!0,children:(0,x.jsx)(B,{className:`topbar__menu`,variant:`ghost`,size:`sm`,"aria-label":`Open navigation`,leadingIcon:(0,x.jsx)(H.Menu,{})})}),(0,x.jsxs)(Sp.Content,{children:[(0,x.jsx)(Sp.Title,{children:`Navigation`}),(0,x.jsx)(`div`,{className:`sidebar sidebar--sheet`,children:(0,x.jsx)(l_,{page:e,onNavigate:_,onboarded:a,counts:o,lastScan:s,collapsed:!1})})]})]}),(0,x.jsx)(`h1`,{className:`topbar__title`,children:o_[e]}),(0,x.jsx)(`form`,{className:`topbar__search`,onSubmit:e=>{e.preventDefault(),n(f.trim())},children:(0,x.jsx)(Zp,{size:`sm`,placeholder:`Search company or role`,"aria-label":`Search jobs`,leadingIcon:(0,x.jsx)(H.Search,{}),trailingIcon:(0,x.jsx)(`span`,{className:`num`,children:`⌘K`}),value:f,onChange:e=>p(e.target.value)})}),(0,x.jsxs)(`div`,{className:`topbar__actions`,children:[(0,x.jsx)(r_,{}),(0,x.jsx)(Bh,{content:r===`light`?`Switch to dark`:`Switch to light`,children:(0,x.jsx)(B,{variant:`ghost`,size:`sm`,onClick:i,"aria-label":`Toggle theme`,leadingIcon:r===`light`?(0,x.jsx)(H.Moon,{}):(0,x.jsx)(H.Sun,{})})})]})]}),c]})]})}function l_({page:e,onNavigate:t,onboarded:n,counts:r,lastScan:i,collapsed:a,onToggleCollapsed:o,tipSide:s=`right`}){let c=new Map(a_.map(e=>[e.page,e])),l=n?s_:[{title:`Start`,pages:[`onboarding`]},...s_.map(e=>({...e,pages:e.pages.filter(e=>e!==`onboarding`)}))];return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`brand`,children:[(0,x.jsx)(n_,{}),o&&(0,x.jsx)(Bh,{content:a?`Expand the sidebar`:`Collapse the sidebar`,children:(0,x.jsx)(B,{className:`sidebar__collapse`,variant:`ghost`,size:`sm`,tone:`neutral`,"aria-label":a?`Expand the sidebar`:`Collapse the sidebar`,leadingIcon:a?(0,x.jsx)(H.ChevronRight,{}):(0,x.jsx)(H.ChevronLeft,{}),onClick:o})})]}),(0,x.jsx)(`nav`,{className:`nav`,"aria-label":`Pages`,children:l.map(n=>(0,x.jsxs)(`div`,{className:`nav__group`,children:[!a&&(0,x.jsx)(`div`,{className:`nav__group-title`,children:n.title}),n.pages.map(e=>c.get(e)).filter(e=>!!e).map(n=>{let i=(0,x.jsx)(B,{className:`nav__item`,align:`start`,variant:e===n.page?`soft`:`ghost`,tone:e===n.page?`primary`:`neutral`,size:`sm`,leadingIcon:(0,x.jsx)(n.icon,{}),trailingIcon:!a&&r[n.page]!=null?(0,x.jsx)(`span`,{className:`nav__count`,children:r[n.page]}):void 0,"aria-current":e===n.page?`page`:void 0,"aria-label":a?n.label:void 0,onClick:()=>t(n.page),children:a?null:n.label},n.page);return a?(0,x.jsx)(Bh,{content:r[n.page]==null?n.label:`${n.label} · ${r[n.page]}`,side:s,children:i},n.page):i})]},n.title))}),!a&&(0,x.jsx)(`div`,{className:`sidebar__foot`,children:(0,x.jsxs)(`div`,{children:[`Notes are the record.`,i&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`br`,{}),(0,x.jsx)(`span`,{className:`num`,children:i})]}),(0,x.jsx)(`br`,{}),(0,x.jsxs)(`span`,{className:`num`,children:[`v`,`0.
|
|
60
|
+
`)?4:1,value:e.value,onChange:e=>c(t,{value:e.target.value})}),(0,x.jsxs)(`div`,{className:`copy__edit-actions`,children:[(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,"aria-label":`Move up`,leadingIcon:(0,x.jsx)(H.ArrowUp,{}),disabled:t===0,onClick:()=>l(t,-1)}),(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,"aria-label":`Move down`,leadingIcon:(0,x.jsx)(H.ArrowDown,{}),disabled:t===i.length-1,onClick:()=>l(t,1)}),(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`danger`,"aria-label":`Remove`,leadingIcon:(0,x.jsx)(H.Trash,{}),onClick:()=>u(t)})]})]},t))}),(0,x.jsxs)(`div`,{className:`form__actions`,children:[(0,x.jsx)(B,{size:`sm`,variant:`soft`,tone:`neutral`,leadingIcon:(0,x.jsx)(H.Plus,{}),onClick:()=>a(e=>[...e,{group:e[e.length-1]?.group??``,label:``,value:``}]),children:`Add a line`}),(0,x.jsx)(`span`,{className:`toolbar__spacer`}),(0,x.jsx)(B,{size:`sm`,variant:`ghost`,onClick:n,children:`Cancel`}),(0,x.jsx)(B,{size:`sm`,tone:`primary`,loading:o,onClick:async()=>{s(!0);try{let e=await $.saveSnippets(i);X({title:`Copy panel saved`,description:`Profile/Snippets.md`,tone:`success`}),r(e)}catch(e){X({title:`Not saved`,description:e.message,tone:`danger`})}s(!1)},children:`Save`})]})]})})})}var a_=[{page:`onboarding`,label:`Get started`,icon:H.Sparkles},{page:`today`,label:`Today`,icon:H.Star},{page:`overview`,label:`Overview`,icon:H.Home},{page:`jobs`,label:`Jobs`,icon:H.Inbox},{page:`pipeline`,label:`Pipeline`,icon:H.Layers},{page:`mail`,label:`Mail`,icon:H.Mail},{page:`people`,label:`People`,icon:H.Users},{page:`companies`,label:`Sources`,icon:H.Globe},{page:`criteria`,label:`Criteria`,icon:H.Filter},{page:`profile`,label:`Profile`,icon:H.User},{page:`runs`,label:`Runs`,icon:H.Refresh},{page:`agent`,label:`Agent access`,icon:H.Terminal},{page:`settings`,label:`Settings`,icon:H.Settings}],o_={onboarding:`Get started`,today:`Today`,overview:`Overview`,jobs:`Jobs`,pipeline:`Pipeline`,mail:`Mail`,people:`People`,companies:`Sources`,criteria:`Criteria`,profile:`Profile`,runs:`Runs`,agent:`Agent access`,settings:`Settings`},s_=[{title:`Work`,pages:[`today`,`jobs`,`pipeline`,`mail`,`people`]},{title:`Insights`,pages:[`overview`]},{title:`Setup`,pages:[`profile`,`criteria`,`companies`]},{title:`System`,pages:[`runs`,`agent`,`settings`,`onboarding`]}];function c_({page:e,onNavigate:t,onSearch:n,theme:r,onToggleTheme:i,onboarded:a=!0,counts:o={},lastScan:s=``,children:c}){let[l,u]=(0,b.useState)(!1),d=e_(`(max-width: 40rem)`),[f,p]=(0,b.useState)(``),[m,h]=(0,b.useState)(()=>{try{return localStorage.getItem(`tekjobs.sidebar`)===`collapsed`}catch{return!1}}),g=()=>h(e=>{try{localStorage.setItem(`tekjobs.sidebar`,e?`open`:`collapsed`)}catch{}return!e}),_=e=>{t(e),u(!1)};return(0,x.jsxs)(`div`,{className:`shell${m?` shell--collapsed`:``}${d?` shell--strip`:``}`,children:[(0,x.jsx)(`aside`,{className:`sidebar`,"aria-label":`Primary`,children:(0,x.jsx)(l_,{page:e,onNavigate:_,onboarded:a,counts:o,lastScan:s,collapsed:m||d,onToggleCollapsed:d?void 0:g,tipSide:d?`bottom`:`right`})}),(0,x.jsxs)(`div`,{className:`main`,children:[(0,x.jsxs)(`header`,{className:`topbar`,children:[(0,x.jsxs)(Sp,{open:l,onOpenChange:u,side:`left`,size:`sm`,children:[(0,x.jsx)(Sp.Trigger,{asChild:!0,children:(0,x.jsx)(B,{className:`topbar__menu`,variant:`ghost`,size:`sm`,"aria-label":`Open navigation`,leadingIcon:(0,x.jsx)(H.Menu,{})})}),(0,x.jsxs)(Sp.Content,{children:[(0,x.jsx)(Sp.Title,{children:`Navigation`}),(0,x.jsx)(`div`,{className:`sidebar sidebar--sheet`,children:(0,x.jsx)(l_,{page:e,onNavigate:_,onboarded:a,counts:o,lastScan:s,collapsed:!1})})]})]}),(0,x.jsx)(`h1`,{className:`topbar__title`,children:o_[e]}),(0,x.jsx)(`form`,{className:`topbar__search`,onSubmit:e=>{e.preventDefault(),n(f.trim())},children:(0,x.jsx)(Zp,{size:`sm`,placeholder:`Search company or role`,"aria-label":`Search jobs`,leadingIcon:(0,x.jsx)(H.Search,{}),trailingIcon:(0,x.jsx)(`span`,{className:`num`,children:`⌘K`}),value:f,onChange:e=>p(e.target.value)})}),(0,x.jsxs)(`div`,{className:`topbar__actions`,children:[(0,x.jsx)(r_,{}),(0,x.jsx)(Bh,{content:r===`light`?`Switch to dark`:`Switch to light`,children:(0,x.jsx)(B,{variant:`ghost`,size:`sm`,onClick:i,"aria-label":`Toggle theme`,leadingIcon:r===`light`?(0,x.jsx)(H.Moon,{}):(0,x.jsx)(H.Sun,{})})})]})]}),c]})]})}function l_({page:e,onNavigate:t,onboarded:n,counts:r,lastScan:i,collapsed:a,onToggleCollapsed:o,tipSide:s=`right`}){let c=new Map(a_.map(e=>[e.page,e])),l=n?s_:[{title:`Start`,pages:[`onboarding`]},...s_.map(e=>({...e,pages:e.pages.filter(e=>e!==`onboarding`)}))];return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`brand`,children:[(0,x.jsx)(n_,{}),o&&(0,x.jsx)(Bh,{content:a?`Expand the sidebar`:`Collapse the sidebar`,children:(0,x.jsx)(B,{className:`sidebar__collapse`,variant:`ghost`,size:`sm`,tone:`neutral`,"aria-label":a?`Expand the sidebar`:`Collapse the sidebar`,leadingIcon:a?(0,x.jsx)(H.ChevronRight,{}):(0,x.jsx)(H.ChevronLeft,{}),onClick:o})})]}),(0,x.jsx)(`nav`,{className:`nav`,"aria-label":`Pages`,children:l.map(n=>(0,x.jsxs)(`div`,{className:`nav__group`,children:[!a&&(0,x.jsx)(`div`,{className:`nav__group-title`,children:n.title}),n.pages.map(e=>c.get(e)).filter(e=>!!e).map(n=>{let i=(0,x.jsx)(B,{className:`nav__item`,align:`start`,variant:e===n.page?`soft`:`ghost`,tone:e===n.page?`primary`:`neutral`,size:`sm`,leadingIcon:(0,x.jsx)(n.icon,{}),trailingIcon:!a&&r[n.page]!=null?(0,x.jsx)(`span`,{className:`nav__count`,children:r[n.page]}):void 0,"aria-current":e===n.page?`page`:void 0,"aria-label":a?n.label:void 0,onClick:()=>t(n.page),children:a?null:n.label},n.page);return a?(0,x.jsx)(Bh,{content:r[n.page]==null?n.label:`${n.label} · ${r[n.page]}`,side:s,children:i},n.page):i})]},n.title))}),!a&&(0,x.jsx)(`div`,{className:`sidebar__foot`,children:(0,x.jsxs)(`div`,{children:[`Notes are the record.`,i&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`br`,{}),(0,x.jsx)(`span`,{className:`num`,children:i})]}),(0,x.jsx)(`br`,{}),(0,x.jsxs)(`span`,{className:`num`,children:[`v`,`0.31.0`]}),(0,x.jsx)(`br`,{}),(0,x.jsx)(`a`,{className:`sidebar__legal`,href:`https://tekjobs.timurtek.com/legal/terms`,target:`_blank`,rel:`noreferrer`,children:`Terms`}),` · `,(0,x.jsx)(`a`,{className:`sidebar__legal`,href:`https://tekjobs.timurtek.com/legal/privacy`,target:`_blank`,rel:`noreferrer`,children:`Privacy`})]})})]})}var u_=`{
|
|
61
61
|
"mcpServers": {
|
|
62
62
|
"tekjobs": {
|
|
63
63
|
"command": "node",
|
package/app/dist/index.html
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<link rel="icon" href="/brand/tekjobs-avatar-192.png" type="image/png" sizes="192x192" />
|
|
9
9
|
<link rel="apple-touch-icon" href="/brand/tekjobs-avatar-192.png" />
|
|
10
10
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@500;600&family=Hanken+Grotesk:wght@400;500;600&family=Azeret+Mono:wght@400;500&display=swap" data-zengin="fonts" />
|
|
11
|
-
<script type="module" crossorigin src="/assets/index-
|
|
11
|
+
<script type="module" crossorigin src="/assets/index-Dnu8dxG5.js"></script>
|
|
12
12
|
<link rel="stylesheet" crossorigin href="/assets/index-CbvdnTFY.css">
|
|
13
13
|
</head>
|
|
14
14
|
<body>
|
|
@@ -214,17 +214,37 @@ export function runLLM(prompt, { timeoutMs = 240000, extraArgs = [] } = {}) {
|
|
|
214
214
|
child.on('error', (e) => { clearTimeout(timer); reject(new Error(`Could not start "${command}": ${e.message}`)); });
|
|
215
215
|
child.on('close', (code) => {
|
|
216
216
|
clearTimeout(timer);
|
|
217
|
-
const
|
|
218
|
-
if (
|
|
219
|
-
if (/failed to authenticate|oauth|not logged in|please log in|login required|unauthorized|401/i.test(all)) return reject(Object.assign(new Error(`${command} is signed out. Open a terminal, run "${command}", sign in, then try again. (The desktop app's login is separate from the terminal's.)`), { kind: 'auth' }));
|
|
220
|
-
if (/requires a newer version|please upgrade/i.test(all)) return reject(Object.assign(new Error(`${command} is out of date and its model refused the request. Update it (npm i -g, or its own updater), then try again.`), { kind: 'outdated' }));
|
|
221
|
-
if (code !== 0 && !out.trim()) return reject(new Error(`${command} exited with code ${code}: ${err.trim().split('\n').slice(-2).join(' ') || 'no output'}`));
|
|
217
|
+
const failure = classifyRun({ code, out, err, command });
|
|
218
|
+
if (failure) return reject(failure);
|
|
222
219
|
resolve(out.replace(/^```[a-z]*\n|\n```\s*$/g, '').trim());
|
|
223
220
|
});
|
|
224
221
|
child.stdin.write(prompt); child.stdin.end();
|
|
225
222
|
});
|
|
226
223
|
}
|
|
227
224
|
|
|
225
|
+
/**
|
|
226
|
+
* What a finished CLI run means: null when it answered, otherwise an Error with a `kind` (missing, auth,
|
|
227
|
+
* outdated, failed) and the CLI's last words. A run that exited 0 with output answered, whatever words the
|
|
228
|
+
* answer contains: the earlier version read "401" and "OAuth" anywhere in the output as a sign-out, and a
|
|
229
|
+
* recruiter's "401(k) match" turned a healthy morning mail check into "claude is signed out".
|
|
230
|
+
*/
|
|
231
|
+
export function classifyRun({ code, out = '', err = '', command = 'claude' }) {
|
|
232
|
+
const tail = err.trim().split('\n').slice(-3).join(' ').slice(0, 300);
|
|
233
|
+
if (/not recognized as an internal|command not found|ENOENT|is not recognized/i.test(err) && !out.trim()) {
|
|
234
|
+
return Object.assign(new Error(`"${command}" is not installed or not on PATH. Install Claude Code, or set another CLI under "llm" in ${CONFIG_FILE}.`), { kind: 'missing' });
|
|
235
|
+
}
|
|
236
|
+
if (code === 0 && out.trim()) return null;
|
|
237
|
+
const signedOut = /not logged in|please run \/login|run `?\/login|failed to authenticate|authentication[_ ]error|invalid[_ ]api[_ ]key|token (has )?expired|(^|\W)unauthorized(\W|$)|\b(http|status|error)\s*:?\s*401\b/i;
|
|
238
|
+
if (signedOut.test(err) || (!out.trim() && signedOut.test(out))) {
|
|
239
|
+
return Object.assign(new Error(`${command} is signed out. Open a terminal, run "${command}", sign in, then try again. (The desktop app's login is separate from the terminal's.) It said: ${tail || 'nothing'}`), { kind: 'auth' });
|
|
240
|
+
}
|
|
241
|
+
if (/requires a newer version|please upgrade/i.test(`${out}\n${err}`)) {
|
|
242
|
+
return Object.assign(new Error(`${command} is out of date and its model refused the request. Update it (npm i -g, or its own updater), then try again.`), { kind: 'outdated' });
|
|
243
|
+
}
|
|
244
|
+
if (!out.trim()) return Object.assign(new Error(`${command} exited with code ${code}: ${tail || 'no output'}`), { kind: 'failed' });
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
|
|
228
248
|
const drafts = new Map(); // id → { running, startedAt, finishedAt, error, errorKind }
|
|
229
249
|
export function state(id) {
|
|
230
250
|
const d = drafts.get(id) || { running: false, startedAt: null, finishedAt: null, error: '', errorKind: '' };
|
package/cli.mjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// tekjobs CLI: init a profile folder, import a resume, check onboarding, scan, serve, mcp.
|
|
3
3
|
import fs from 'node:fs';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
+
import os from 'node:os';
|
|
5
6
|
import { spawn, spawnSync } from 'node:child_process';
|
|
6
7
|
import { fileURLToPath } from 'node:url';
|
|
7
8
|
|
|
@@ -37,7 +38,10 @@ const HELP = `tekjobs — a local job-search machine
|
|
|
37
38
|
tekjobs import linkedin <zip|folder> your LinkedIn data export into the search: who you know at each
|
|
38
39
|
company, and the recruiters who wrote
|
|
39
40
|
[--since YYYY-MM-DD] [--everyone] [--no-people] [--preview] [--dry]
|
|
40
|
-
tekjobs
|
|
41
|
+
tekjobs up [--dev] [--port N] start the API (and with --dev, Vite) detached: they stay up until \`down\`
|
|
42
|
+
tekjobs down stop what \`up\` started
|
|
43
|
+
tekjobs ps what \`up\` has running
|
|
44
|
+
tekjobs serve the app + API on http://127.0.0.1:8787, in this terminal
|
|
41
45
|
tekjobs mcp the MCP server on stdio (Claude Code, Codex, Cursor, Claude Desktop)
|
|
42
46
|
|
|
43
47
|
The profile folder is resolved from TEKJOBS_PROFILE, then ~/.tekjobs/config.json, then ~/.tekjobs/profile.
|
|
@@ -167,6 +171,9 @@ async function main() {
|
|
|
167
171
|
if (!s.dry) console.log(` Index: ${s.indexPath}. Job notes now show who you know at each company.`);
|
|
168
172
|
return;
|
|
169
173
|
}
|
|
174
|
+
if (cmd === 'up') return up();
|
|
175
|
+
if (cmd === 'down') return down();
|
|
176
|
+
if (cmd === 'ps') return ps();
|
|
170
177
|
if (cmd === 'serve') return run(process.execPath, [path.join(ROOT, 'app', 'server', 'index.mjs')]);
|
|
171
178
|
if (cmd === 'mcp') return run(process.execPath, [path.join(ROOT, 'app', 'server', 'mcp.mjs')]);
|
|
172
179
|
console.error(`unknown command "${cmd}"\n`); console.log(HELP); process.exit(1);
|
|
@@ -177,6 +184,69 @@ function printStatus(s) {
|
|
|
177
184
|
console.log(s.complete ? '\nAll set. The daily scan takes it from here.' : '\nNext: the first unchecked line above.');
|
|
178
185
|
}
|
|
179
186
|
function run(bin, args) { const p = spawn(bin, args, { stdio: 'inherit', env: process.env }); p.on('close', (c) => process.exit(c ?? 0)); }
|
|
187
|
+
|
|
188
|
+
// ---- up / down / ps: the servers, started once, detached from this terminal, left running until `down` ----
|
|
189
|
+
// A server started in a terminal dies with the tab, and one started by an editor's preview dies with the session;
|
|
190
|
+
// both meant starting them again every morning. These start the API (and with --dev, Vite) as detached processes
|
|
191
|
+
// with their output in ~/.tekjobs/run/*.log and their pids in servers.json, and nothing stops them but `down`.
|
|
192
|
+
const RUN_DIR = path.join(os.homedir(), '.tekjobs', 'run');
|
|
193
|
+
const RUN_FILE = path.join(RUN_DIR, 'servers.json');
|
|
194
|
+
const alive = (pid) => { if (!pid) return false; try { process.kill(pid, 0); return true; } catch (e) { return e.code === 'EPERM'; } };
|
|
195
|
+
const readRun = () => { try { return JSON.parse(fs.readFileSync(RUN_FILE, 'utf8')); } catch { return {}; } };
|
|
196
|
+
const writeRun = (o) => { fs.mkdirSync(RUN_DIR, { recursive: true }); fs.writeFileSync(RUN_FILE, JSON.stringify(o, null, 2)); };
|
|
197
|
+
function startDetached(name, bin, args, env, cwd) {
|
|
198
|
+
fs.mkdirSync(RUN_DIR, { recursive: true });
|
|
199
|
+
const log = path.join(RUN_DIR, `${name}.log`);
|
|
200
|
+
const fd = fs.openSync(log, 'a');
|
|
201
|
+
fs.writeSync(fd, `\n===== ${new Date().toISOString()} start =====\n`);
|
|
202
|
+
const p = spawn(bin, args, { cwd, env: { ...process.env, ...env }, detached: true, stdio: ['ignore', fd, fd], windowsHide: true });
|
|
203
|
+
fs.closeSync(fd);
|
|
204
|
+
p.unref();
|
|
205
|
+
return { pid: p.pid, log, started: new Date().toISOString() };
|
|
206
|
+
}
|
|
207
|
+
function killTree(pid) {
|
|
208
|
+
if (process.platform === 'win32') { spawnSync('taskkill', ['/T', '/F', '/PID', String(pid)], { stdio: 'ignore' }); return; }
|
|
209
|
+
try { process.kill(-pid, 'SIGTERM'); } catch { try { process.kill(pid, 'SIGTERM'); } catch { /* already gone */ } }
|
|
210
|
+
}
|
|
211
|
+
async function up() {
|
|
212
|
+
const port = Number(opt('--port') || process.env.PORT || 8787);
|
|
213
|
+
const vitePort = Number(opt('--vite-port') || 5173);
|
|
214
|
+
const dev = rest.includes('--dev');
|
|
215
|
+
const state = readRun();
|
|
216
|
+
const next = { ...state };
|
|
217
|
+
if (state.api && alive(state.api.pid)) console.log(`API already up: pid ${state.api.pid}, http://127.0.0.1:${state.api.port}`);
|
|
218
|
+
else {
|
|
219
|
+
next.api = { ...startDetached('api', process.execPath, [path.join(ROOT, 'app', 'server', 'index.mjs')], { PORT: String(port) }, ROOT), port };
|
|
220
|
+
console.log(`API up: pid ${next.api.pid}, http://127.0.0.1:${port} (log: ${next.api.log})`);
|
|
221
|
+
}
|
|
222
|
+
if (dev) {
|
|
223
|
+
if (state.vite && alive(state.vite.pid)) console.log(`Vite already up: pid ${state.vite.pid}, http://localhost:${state.vite.port}`);
|
|
224
|
+
else {
|
|
225
|
+
const viteArgs = ['run', 'dev', '--', '--port', String(vitePort), '--strictPort'];
|
|
226
|
+
const [bin, args] = process.platform === 'win32' ? ['cmd', ['/c', 'npm', ...viteArgs]] : ['npm', viteArgs];
|
|
227
|
+
next.vite = { ...startDetached('vite', bin, args, {}, path.join(ROOT, 'app')), port: vitePort };
|
|
228
|
+
console.log(`Vite up: pid ${next.vite.pid}, http://localhost:${vitePort} (log: ${next.vite.log})`);
|
|
229
|
+
}
|
|
230
|
+
} else if (state.vite && !alive(state.vite.pid)) delete next.vite;
|
|
231
|
+
writeRun(next);
|
|
232
|
+
for (let i = 0; i < 40; i++) { try { if ((await fetch(`http://127.0.0.1:${port}/api/summary`)).ok) break; } catch { /* not yet */ } await new Promise((r) => setTimeout(r, 250)); }
|
|
233
|
+
console.log('They stay up until `tekjobs down`; closing this terminal does not stop them. `tekjobs ps` shows them.');
|
|
234
|
+
}
|
|
235
|
+
function down() {
|
|
236
|
+
const state = readRun();
|
|
237
|
+
let n = 0;
|
|
238
|
+
for (const [name, s] of Object.entries(state)) {
|
|
239
|
+
if (s?.pid && alive(s.pid)) { killTree(s.pid); n++; console.log(`${name} stopped (pid ${s.pid})`); }
|
|
240
|
+
}
|
|
241
|
+
try { fs.unlinkSync(RUN_FILE); } catch { /* nothing recorded */ }
|
|
242
|
+
if (!n) console.log('Nothing was up.');
|
|
243
|
+
}
|
|
244
|
+
function ps() {
|
|
245
|
+
const rows = Object.entries(readRun());
|
|
246
|
+
if (!rows.length) return console.log('Nothing up. `tekjobs up` starts the API; `tekjobs up --dev` the API and Vite.');
|
|
247
|
+
for (const [name, s] of rows) console.log(`${name.padEnd(5)} ${alive(s.pid) ? 'up ' : 'gone'} pid ${String(s.pid).padEnd(6)} http://127.0.0.1:${s.port} since ${s.started} log: ${s.log}`);
|
|
248
|
+
}
|
|
249
|
+
|
|
180
250
|
main().catch((e) => { console.error(e.message); process.exit(1); });
|
|
181
251
|
|
|
182
252
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timurtekb/tekjobs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.1",
|
|
4
4
|
"description": "A local-first job-search machine: watches hundreds of company job boards, scores every posting against your profile, and files matches into a folder of markdown notes you own. Bring your own LLM through MCP.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|