quirl-cli 0.1.11 → 0.1.13

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 (2) hide show
  1. package/dist/quirl.mjs +8 -6
  2. package/package.json +1 -1
package/dist/quirl.mjs CHANGED
@@ -211,7 +211,7 @@ if(!Array.isArray(r))throw Error(`ajv implementation error`);let a=n.name(`valid
211
211
  - Resources hold more than endpoints and tables: deployments (Cloud Run, Lambda), variables (names only, never values), scheduled jobs, domains, database functions, events (webhooks), roles and AI models. See one with get_resource. Record what the code doesn't show with add_contract, correct with update_contract, drop with remove_contract, and connect them with links (a job calls an endpoint, a deployment uses a variable, a role protects a table).
212
212
  - A repo is named after its git remote. To give it another name, set "repoName" in its .quirl/project.json (in a folder of repos, { "path", "name" } in "repos") and run quirl sync; everything linked to it stays. remove_repo takes a repo out of the project, only when the person asks.
213
213
  - If the project has no capabilities yet, offer to read the codebase and draft them with propose_capability.
214
- - If the project briefing isn't already in your context, call quirl_context first.`}),r={p_project:e.project},i=()=>({tool:n.server.getClientVersion()?.name??`mcp`,model:process.env.QUIRL_AGENT_MODEL}),a=e=>async t=>{try{return Kb(await e(t))}catch(e){if(e instanceof Ur)return{...Kb(e.message),isError:!0};throw e}};n.registerTool(`quirl_context`,{title:`Project briefing`,description:`The project briefing: always-loaded docs in full, glossary, capabilities, your open tasks and the list of other docs. Usually already loaded at session start.`,inputSchema:{}},a(async()=>zb(await t.context(e.project)))),n.registerTool(`search_docs`,{title:`Search docs`,description:`Full-text search across the project's docs (README, ADRs, guides, runbooks). Returns matching sections with their content. Use for anything not in the briefing.`,inputSchema:{query:B().describe(`Words to search for, e.g. 'refund approval limits'`),limit:V().int().min(1).max(20).optional()}},a(({query:e,limit:n})=>t.call(`search_docs`,{...r,p_query:e,p_limit:n??6}))),n.registerTool(`read_doc`,{title:`Read a doc`,description:`Read one doc in full, by id, title or source path. source says where it lives: 'quirl' for docs written in Quirl (editable with edit_doc), otherwise the repo or folder it's synced from.`,inputSchema:{doc:B().describe(`Doc id, title or path, e.g. 'docs/adr/004-queues.md'`)}},a(({doc:e})=>t.call(`read_doc`,{...r,p_doc:e})));let o=[`product`,`guideline`,`architecture`,`decision`,`how_to`,`reference`];n.registerTool(`create_doc`,{title:`Write a new doc`,description:`Write a doc in Quirl itself: a PRD, spec or product note with no file behind it. Docs about code that tests or builds rely on belong in their repo, where sync picks them up. Use product for PRDs and specs. Never include secret values.`,inputSchema:{title:B(),body:B().describe(`Markdown. Headings (##, ###) split it into sections edit_doc can change one at a time.`),type:W(o).optional().describe(`Defaults to reference`)}},a(({title:e,body:n,type:a})=>t.call(`create_doc`,{...r,p_title:e,p_body:n,p_type:a??`reference`,p_agent:i()}))),n.registerTool(`edit_doc`,{title:`Edit a doc written in Quirl`,description:`Change one section of a doc written in Quirl, or the whole doc, without rewriting the rest. A section is named by its heading, or by its path when a heading repeats ('Billing > Refunds'). replace swaps the section's text (keeping its heading, unless the new text starts with one); append adds to the end of it. Without a section, replace rewrites the doc and append adds to its end. Docs synced from a repo or folder are changed there instead. The edit fails if the doc changed since it was read, rather than overwriting that change.`,inputSchema:{doc:B().describe(`Doc id or title`),section:B().optional().describe(`Heading text or path, e.g. 'Scope' or 'Billing > Refunds'`),content:B().describe(`Markdown`),mode:W([`replace`,`append`]).optional().describe(`Defaults to replace`),title:B().optional().describe(`A new title for the doc`),type:W(o).optional()}},a(async({doc:e,section:n,content:a,mode:o,title:s,type:c})=>{let l=await t.call(`read_doc`,{...r,p_doc:e});if(!l.editable)throw new Ur(`"${l.title}" comes from ${l.source}. Change it there; sync brings it into Quirl.`);let u;try{u=Gb(l.body,n,a,o??`replace`)}catch(e){throw new Ur(e.message)}return{...await t.call(`update_doc`,{...r,p_doc:l.id,p_title:s??null,p_body:u,p_type:c??null,p_expected_hash:l.contentHash,p_agent:i()}),edited:n??`the whole doc`,sections:Hb(u)}})),n.registerTool(`doc_history`,{title:`A doc's history`,description:`Who changed a doc and when, newest first, with lines added and removed. Pass a version to see what it changed (a diff against the version before), or full to get that version's whole text, e.g. to bring back wording with edit_doc.`,inputSchema:{doc:B().describe(`Doc id or title`),version:V().int().optional(),full:em().optional().describe(`With version: its whole text instead of the diff`)}},a(async({doc:e,version:n,full:i})=>{let a=await t.call(`doc_history`,{...r,p_doc:e,p_limit:n?200:21}),o=a.versions,s=e=>o.find(t=>t.version===e-1);if(n){let e=o.find(e=>e.version===n);if(!e)throw new Ur(`"${a.title}" has no version ${n}; the latest is ${o[0]?.version??0}.`);if(i)return{version:n,title:e.title,body:e.body};let t=s(n);return{version:n,author:e.author??`unknown`,at:e.createdAt,...t&&t.title!==e.title?{renamed:`${t.title} → ${e.title}`}:{},diff:t?Ib(t.body,e.body)||`(no text changes)`:`(first version)`}}return{title:a.title,source:a.source,versions:o.slice(0,20).map(e=>{let t=s(e.version);return{version:e.version,author:e.author??`unknown`,at:e.createdAt,change:t?Pb(Nb(t.body,e.body)):`first version`}})}})),n.registerTool(`archive_doc`,{title:`Archive a doc written in Quirl`,description:`Remove a doc written in Quirl that's no longer true or was a mistake. It's archived and stays in history. Docs synced from a repo or folder are deleted there instead.`,inputSchema:{doc:B().describe(`Doc id or title`),reason:B().optional().describe(`Why, for history`)}},a(({doc:e,reason:n})=>t.call(`archive_doc`,{...r,p_doc:e,p_reason:n??null,p_agent:i()}))),n.registerTool(`lookup`,{title:`Look up a term, capability or contract`,description:`Find glossary terms, capabilities, features and API/table contracts matching a name. Use it to check what a word means here, or the request/response shape of an endpoint or table.`,inputSchema:{query:B().describe(`A term, capability, endpoint or table name, e.g. 'Visit' or 'POST /login'`)}},a(({query:e})=>t.call(`lookup`,{...r,p_query:e})));let s=(e,t,r,i)=>{n.registerTool(e,r,i),n.registerTool(t,{...r,description:`Old name for ${e}; use ${e}. ${r.description}`},i)};s(`list_tasks`,`list_cards`,{title:`List tasks`,description:`List tasks on the board. Defaults to your own tasks that aren't done.`,inputSchema:{onlyMine:em().optional(),includeDone:em().optional()}},a(({onlyMine:e,includeDone:n})=>t.call(`list_cards`,{...r,p_only_mine:e??!0,p_include_done:n??!1})));let c=`Markdown: short paragraphs, and lists for steps or parts, not one long block.`,l=`Kind of work: e.g. Frontend, Backend, Database, Design, DevOps, Testing, Docs, Research. Only tags from the task set are accepted (see tagSets in quirl_context); propose a new value with propose_term (kind tag, tagSet task_work).`,u=B().describe(`Task number, e.g. 'K-104' or '104'`),d=B().optional().describe(`Who does it: "me", a member's email or name (only people on the project), or "none"`);return s(`get_task`,`get_card`,{title:`Get a task`,description:`A task with its feature, docs, dependencies and evidence.`,inputSchema:{task:u.optional(),card:u.optional()}},a(({task:e,card:n})=>t.call(`get_card`,{...r,p_card:e??n}))),s(`create_task`,`create_card`,{title:`Create a task`,description:`Add a task to the board (status: todo). Use it for work you discover that should be tracked. Put it under the feature it serves.`,inputSchema:{title:B(),description:B().optional().describe(`What to do and why. ${c}`),type:W([`feature_work`,`bug`,`chore`,`research`]).optional(),feature:B().optional().describe(`Feature name or id (e.g. F-4) this task belongs to`),tags:H(B()).optional().describe(l),assignee:d.describe(`Who does it: "me" (the default), a member's email or name, or "none"`)}},a(async({title:e,description:n,type:a,feature:o,tags:s,assignee:c})=>{let l=await t.call(`create_card`,{...r,p_title:e,p_description:n??``,p_type:a??`feature_work`,p_feature:o??null,p_agent:i()});return(s?.length||c)&&await t.call(`update_card`,{...r,p_card:l,p_patch:{...s?.length?{tags:s}:{},...c?{assignee:c}:{}},p_agent:i()}),l})),s(`update_task`,`update_card`,{title:`Update a task`,description:`Move a task, mark it blocked (with a reason) or unblocked, assign it, put it under a feature, set its tags, rewrite its title or description, and attach evidence: a branch, commit or pull request. Repos are referenced by name.`,inputSchema:{task:u.optional(),card:u.optional(),assignee:d,status:W([`backlog`,`todo`,`in_progress`,`review`,`done`]).optional(),feature:B().optional().describe(`Feature name or id (e.g. F-4) to put the task under; an empty string takes it off its feature`),title:B().optional(),description:B().optional().describe(`Replaces the description. ${c}`),tags:H(B()).optional().describe(`${l} Replaces the current tags.`),blocked:em().optional(),blockedReason:B().optional(),addBranch:U({repo:B(),name:B()}).optional(),addCommit:U({repo:B(),sha:B(),message:B().optional()}).optional(),addPullRequest:U({repo:B(),number:V().int(),url:B(),state:W([`open`,`merged`,`closed`]).optional()}).optional()}},a(({task:e,card:n,...a})=>t.call(`update_card`,{...r,p_card:e??n,p_patch:a,p_agent:i()}))),n.registerTool(`archive_task`,{title:`Archive a task`,description:`Remove a task that shouldn't be there: a duplicate or a mistake. It's archived and stays in history, and its feature's status is worked out without it. For work that's finished, move it to done instead.`,inputSchema:{task:u,reason:B().optional().describe(`Why, for history`)}},a(({task:e,reason:n})=>t.call(`archive_card`,{...r,p_card:e,p_reason:n??null,p_agent:i()}))),n.registerTool(`propose_term`,{title:`Propose a glossary term`,description:`Suggest a new glossary term. It shows up for approval; it isn't used until a person approves it.`,inputSchema:{term:B(),plain:B().describe(`What it means, for someone non-technical`),technical:B().describe(`What it means in the code`),kind:W([`concept`,`tag`,`name`]).optional(),tagSet:B().optional().describe(`Required for kind 'tag': the set the value belongs to, e.g. feature_change, task_work, capability_audience, capability_kind (see tagSets in quirl_context)`),reason:B().optional()}},a(({term:e,plain:n,technical:a,kind:o,tagSet:s,reason:c})=>t.call(`propose_term`,{...r,p_term:e,p_plain:n,p_technical:a,p_kind:o??`concept`,p_tag_set:s??null,p_reason:c??null,p_agent:i()}))),n.registerTool(`propose_term_retire`,{title:`Retire a glossary term`,description:`Propose retiring a glossary term or tag that's no longer used or was a mistake. With replaceWith, the term stays as one not to say (agents are told the replacement); without it, it's removed. Either way it comes off every capability, task and feature that used it. A person approves it. Built-in tag values can't be retired.`,inputSchema:{term:B().describe(`The term or tag to retire`),replaceWith:B().optional().describe(`An approved term to say instead, if there is one`),reason:B().optional()}},a(({term:e,replaceWith:n,reason:a})=>t.call(`propose_term_retire`,{...r,p_term:e,p_replace_with:n??null,p_reason:a??null,p_agent:i()}))),n.registerTool(`list_flags`,{title:`List flags`,description:`Flags are messages people send about a section of the project: a capability, feature, task, doc or glossary term. Lists open (waiting for an admin) and approved (to act on) flags, or only those with the given status.`,inputSchema:{status:W([`open`,`approved`,`removed`,`done`]).optional()}},a(({status:e})=>t.call(`list_flags`,{...r,p_status:e??null}))),n.registerTool(`decide_flag`,{title:`Approve or remove a flag`,description:`Admins only. Approve a flag so agents act on it at the start of their sessions, or remove it. An approved flag can still be removed. Only do this when the person you work for asks you to.`,inputSchema:{flag:B().describe(`The flag's id, from the briefing or list_flags`),decision:W([`approve`,`remove`])}},a(({flag:e,decision:n})=>t.call(`decide_flag`,{...r,p_flag:e,p_approve:n===`approve`,p_agent:i()}))),n.registerTool(`resolve_flag`,{title:`Mark a flag done`,description:`Mark an approved flag done once you've handled it, so it leaves the briefing. Say briefly what you did.`,inputSchema:{flag:B().describe(`The flag's id, from the briefing or list_flags`),note:B().optional().describe(`What was done, e.g. 'Updated C-12 to mention SMS'`)}},a(({flag:e,note:n})=>t.call(`resolve_flag`,{...r,p_flag:e,p_note:n??null,p_agent:i()}))),n.registerTool(`set_capability_icon`,{title:`Set a capability's icon`,description:`Give a capability an icon that fits what it does; it's shown on the capability's card. Use the same icon a related feature has when one fits both.`,inputSchema:{capability:B().describe(`Capability name or id (e.g. C-12)`),icon:W(Lb)}},a(({capability:e,icon:n})=>t.call(`set_capability_icon`,{...r,p_capability:e,p_icon:n,p_agent:i()}))),n.registerTool(`add_resource`,{title:`Add or fill in a resource`,description:"Record a service the project runs on that `quirl sync` can't see from the code: a hosted database another team runs, a SaaS named only in docs or the console, a staging copy. Sync already finds most things from env templates, docker-compose and client packages, so check Stack first (lookup) and don't add what it found. A resource with the same provider and environment is filled in rather than duplicated: the fields you give are set, and repos and capabilities are added to its links. Never pass URLs with credentials, keys or other secret values.",inputSchema:{name:B().describe(`What the team calls it, e.g. "Postgres", "Stripe"`),type:W(qb),provider:B().optional().describe(`Who runs it, e.g. "Google Cloud SQL", "Stripe". Resources are matched on this. Defaults to the name.`),description:B().optional().describe(`One plain sentence on what the project uses it for`),technical:B().optional().describe(`Technical notes for developers: setup, access, limits`),environment:B().optional().describe(`Defaults to "production"; e.g. "staging"`),repos:H(B()).optional().describe(`Repos that use it, by name`),capabilities:H(B()).optional().describe(`Capabilities that run on it, by name or id (e.g. C-12)`),account:B().optional().describe(`The cloud project, account or team it lives in, e.g. GCP project "domainarium-staging". Sync files deployments, jobs and secrets by it. Never a key.`)}},a(e=>t.call(`add_resource`,{...r,p_name:e.name,p_type:e.type,p_provider:e.provider??null,p_description:e.description??null,p_technical:e.technical??null,p_environment:e.environment??null,p_repos:e.repos??null,p_capabilities:e.capabilities??null,p_account:e.account??null,p_agent:i()}))),n.registerTool(`list_resources`,{title:`List the project's resources`,description:`Every resource on Stack: name, type, provider, environment, whether sync found it or someone added it, the repos that use it, the capabilities that run on it, and the tables and endpoints filed under it (per repo, with a few names). Tables in the wrong database or endpoints under the wrong API: fix with move_contracts.`,inputSchema:{}},a(()=>t.call(`list_resources`,r))),n.registerTool(`update_resource`,{title:`Change a resource`,description:`Correct a resource: rename it, relabel its environment (a scanned one that's really the local docker database becomes 'local'), or change its type, provider, descriptions or links. Only the fields you pass change. repos and capabilities replace its links; use add_resource to add to them. Sync keeps updating a relabelled resource instead of adding it again. Never pass secret values.`,inputSchema:{...Qb,name:B().optional(),type:W(qb).optional(),provider:B().optional(),environment:B().optional().describe(`e.g. "production", "staging", "dev", "local"`),description:B().optional().describe(`One plain sentence on what the project uses it for`),technical:B().optional().describe(`Notes for developers`),repos:H(B()).optional().describe(`Replaces the repos that use it`),capabilities:H(B()).optional().describe(`Replaces the capabilities that run on it (names or C-12)`),account:B().optional().describe(`The cloud project, account or team it lives in, e.g. GCP project "domainarium-staging". Sync files deployments, jobs and secrets by it. Never a key. Empty clears it.`)}},a(e=>t.call(`update_resource`,{...r,p_resource:e.resource,p_in_environment:e.inEnvironment??null,p_name:e.name??null,p_type:e.type??null,p_provider:e.provider??null,p_environment:e.environment??null,p_description:e.description??null,p_technical:e.technical??null,p_repos:e.repos??null,p_capabilities:e.capabilities??null,p_account:e.account??null,p_agent:i()}))),n.registerTool(`remove_resource`,{title:`Remove a wrong resource`,description:`Remove a resource that isn't one: a false match from sync, a duplicate, something no longer used. It's archived, stays in history, and sync won't add it again. A resource holding endpoints or tables from sync can't be removed; relabel it instead.`,inputSchema:{...Qb,reason:B().optional().describe(`Why it's wrong, for history`)}},a(e=>t.call(`remove_resource`,{...r,p_resource:e.resource,p_in_environment:e.inEnvironment??null,p_reason:e.reason??null,p_agent:i()}))),n.registerTool(`get_resource`,{title:`Get a resource and what it holds`,description:`One resource with everything it holds: endpoints, tables, functions, deployments, variables (names only), jobs, domains, events, roles, models. Each with its fields (spec), whether sync found it or someone added it, and its links (what it runs, calls, uses or protects, and what points at it). Use before adding or changing what a resource holds.`,inputSchema:Qb},a(e=>t.call(`get_resource`,{...r,p_resource:e.resource,p_in_environment:e.inEnvironment??null}))),n.registerTool(`add_contract`,{title:`Add something a resource holds`,description:`Record what the code doesn't show: a Cloud Scheduler job set up in the console, the variables Secret Manager holds (names, never values), a Cloud Run service, the roles the product has, the AI models it calls, a webhook it receives, a domain. Sync finds endpoints and tables from OpenAPI files and migrations, so check get_resource first. What you add stays until someone removes it; if sync later finds the same thing in code, it takes it over. Never pass secret values, keys or URLs with credentials.\n\n${Xb}`,inputSchema:{...Qb,kind:W(Jb),name:B().optional().describe(`e.g. "nightly-invoices", "STRIPE_SECRET_KEY", "admin", "claude-opus-5-5". Endpoints default to "METHOD /path".`),description:B().optional().describe(`One plain sentence: what it is or does`),spec:_m(B(),im()).optional().describe(`The kind's fields; see the list above`),repo:B().optional().describe(`The repo it belongs to, if any`),links:Zb.optional()}},a(e=>t.call(`add_contract`,{...r,p_resource:e.resource,p_in_environment:e.inEnvironment??null,p_kind:e.kind,p_name:e.name??null,p_description:e.description??null,p_spec:e.spec??null,p_repo:e.repo??null,p_links:e.links??null,p_agent:i()}))),n.registerTool(`update_contract`,{title:`Change something a resource holds`,description:`Correct or fill in a contract: its description, its fields, its links. spec is merged: given fields are set, a field set to null is removed. links, when given, replace the links people added (sync's stay). On something sync found (an endpoint from OpenAPI, a table from migrations) only the description and links change here; the rest follows the code. To file it under another resource, use move_contracts.\n\n${Xb}`,inputSchema:{contract:B().describe(`kind:name ("job:nightly-invoices", "endpoint:GET /domains"), a unique name, or its id (from get_resource)`),resource:B().optional().describe(`Its resource, when the name is in several`),inEnvironment:B().optional(),name:B().optional(),description:B().optional(),spec:_m(B(),im()).optional(),links:Zb.optional()}},a(e=>t.call(`update_contract`,{...r,p_contract:e.contract,p_resource:e.resource??null,p_in_environment:e.inEnvironment??null,p_name:e.name??null,p_description:e.description??null,p_spec:e.spec??null,p_links:e.links??null,p_agent:i()}))),n.registerTool(`remove_contract`,{title:`Remove something added to a resource`,description:`Remove a contract someone added that's wrong or gone: a deleted job, a retired variable. It's archived and stays in history. What sync found from code can't be removed here: change the code, or move it with move_contracts if it's filed in the wrong place.`,inputSchema:{contract:B().describe(`kind:name ("variable:OLD_KEY"), a unique name, or its id`),resource:B().optional(),inEnvironment:B().optional(),reason:B().optional().describe(`Why, for history`)}},a(e=>t.call(`remove_contract`,{...r,p_contract:e.contract,p_resource:e.resource??null,p_in_environment:e.inEnvironment??null,p_reason:e.reason??null,p_agent:i()}))),n.registerTool(`move_contracts`,{title:`Move what sync filed to another resource`,description:`Correct where sync filed a repo's tables (which database), endpoints (which API), deployments (which Cloud Run project), jobs, variables, functions, roles or models. Without names, all of the repo's ones of that kind move and later syncs put new ones there too. With names, only those move and sync leaves them there. list_resources shows what's filed where. For deployments in the wrong environment, setting the resource's account (update_resource) also fixes later syncs.`,inputSchema:{repo:B().describe(`The repo they come from: name, URL or id`),kind:W([...Jb,`tables`,`endpoints`]),to:B().describe(`The resource they belong to: name, provider or id`),toEnvironment:B().optional().describe(`Its environment, when it exists in several`),names:H(B()).optional().describe(`Only these, e.g. ["bookings"] or ["GET /bookings"]; leave out to move all`)}},a(e=>t.call(`move_contracts`,{...r,p_repo:e.repo,p_kind:e.kind,p_to:e.to,p_in_environment:e.toEnvironment??null,p_names:e.names??null,p_agent:i()}))),n.registerTool(`remove_repo`,{title:`Remove a repo`,description:"Remove a repo from the project, for admins: one that's retired, or was imported by mistake. Its dependencies, endpoints, tables and synced docs are archived with it, and it's unlinked from capabilities, tasks and resources. Sync skips it from then on; running `quirl init` in it adds it back. Only on the person's request: confirm with them first. To rename a repo instead, set its name in .quirl/project.json and sync.",inputSchema:{repo:B().describe(`The repo's name, URL or id`),reason:B().optional().describe(`Why it's removed, for history`)}},a(e=>t.call(`remove_repo`,{...r,p_repo:e.repo,p_reason:e.reason??null,p_agent:i()}))),n.registerTool(`list_features`,{title:`List features`,description:`List the project's features with their status, the capability each changes (or createsCapability when it has none), and task counts. Shipped ones are left out unless includeShipped. Check here before requesting a feature.`,inputSchema:{includeShipped:em().optional()}},a(({includeShipped:e})=>t.call(`list_features`,{...r,p_include_shipped:e??!1}))),n.registerTool(`get_feature`,{title:`Get a feature`,description:`A feature with its description, status, the capability it changes (and what that capability does) and its tasks.`,inputSchema:{feature:B().describe(`Feature name or id (e.g. F-4)`)}},a(({feature:e})=>t.call(`get_feature`,{...r,p_feature:e}))),n.registerTool(`request_feature`,{title:`Request a feature`,description:`Request a feature: a change to the product that stakeholders follow on the Features page, usually made of several tasks. Check list_features first so you don't request one twice. It shows as requested straight away and a person accepts or declines it. Put tasks under it with create_task or update_task.`,inputSchema:{name:B().describe(`Short name, e.g. 'Repeat appointments'`),description:B().describe(`What changes for the user, in plain words. Markdown: short paragraphs, and lists for parts`),capability:B().optional().describe(`Capability name or id (e.g. C-12) it changes. Leave it out when the feature creates a new capability`),tags:H(B()).optional().describe(`Kind of change: e.g. New, Improvement, Visual, Fix, Performance, Security, Removal, Internal (the feature_change set in quirl_context)`),reason:B().optional().describe(`Why it's worth doing`),icon:W(Lb).optional().describe(`An icon that fits the feature, shown on its card`)}},a(async({name:e,description:n,capability:a,tags:o,reason:s,icon:c})=>{let l=await t.call(`request_feature`,{...r,p_name:e,p_description:n,p_capability:a??null,p_tags:o??null,p_reason:s??null,p_agent:i()});return c&&l===`requested`&&await t.call(`set_feature_icon`,{...r,p_feature:e,p_icon:c,p_agent:i()}),l})),n.registerTool(`set_feature_icon`,{title:`Set a feature's icon`,description:`Give a feature an icon that fits what it does; it's shown on the feature's card. list_features shows which features have none.`,inputSchema:{feature:B().describe(`Feature name or id (e.g. F-4)`),icon:W(Lb)}},a(({feature:e,icon:n})=>t.call(`set_feature_icon`,{...r,p_feature:e,p_icon:n,p_agent:i()}))),n.registerTool(`update_feature`,{title:`Correct a feature`,description:`Fix a feature's name, description or the capability it changes, e.g. after requesting it with the wrong one. Only the fields you pass change; it shows in the feature's history. Tags: tag_feature; icon: set_feature_icon.`,inputSchema:{feature:B().describe(`Feature name or id (e.g. F-4)`),name:B().optional(),description:B().optional().describe(`What changes for the user, in plain words. Markdown: short paragraphs, and lists for parts`),capability:B().optional().describe(`The capability it changes (name or C-12), or "none" when it creates a new one`)}},a(({feature:e,name:n,description:a,capability:o})=>t.call(`update_feature`,{...r,p_feature:e,p_name:n??null,p_description:a??null,p_capability:o??null,p_agent:i()}))),n.registerTool(`withdraw_feature`,{title:`Withdraw a feature`,description:`Remove a feature that shouldn't be there: a duplicate, a mistake, or an idea dropped before any work. It's archived and stays in history. One that shipped can't be withdrawn; move or archive its tasks first (update_task, archive_task).`,inputSchema:{feature:B().describe(`Feature name or id (e.g. F-4)`),reason:B().optional().describe(`Why, for history`)}},a(({feature:e,reason:n})=>t.call(`withdraw_feature`,{...r,p_feature:e,p_reason:n??null,p_agent:i()}))),n.registerTool(`tag_feature`,{title:`Tag a feature`,description:`Set a feature's kind-of-change tags (replaces the current ones). Only values from the feature_change tag set are accepted.`,inputSchema:{feature:B().describe(`Feature name or id (e.g. F-4)`),tags:H(B()).describe(`Kind of change: e.g. New, Improvement, Visual, Fix, Performance, Security, Removal, Internal`)}},a(({feature:e,tags:n})=>t.call(`tag_feature`,{...r,p_feature:e,p_tags:n,p_agent:i()}))),n.registerTool(`list_capabilities`,{title:`List the capabilities`,description:`Every capability as data: id (C-12), name, status, icon, the capability it's part of, what it does, what it relies on, its tags and the features changing it. Retired ones only with includeRetired.`,inputSchema:{includeRetired:em().optional()}},a(({includeRetired:e})=>t.call(`list_capabilities`,{...r,p_include_retired:e??!1}))),n.registerTool(`propose_capability`,{title:`Propose a capability`,description:"Draft a capability: one thing the product does today, described for a non-technical reader. Use it when the project has none yet (for example right after `quirl init`), when you find one that's missing, or when a feature that creates a new capability ships (pass it in features). Never for something not built yet: request a feature instead. A person approves it before it shows up.",inputSchema:{name:B().describe(`Short name, e.g. 'Online booking'`),whatItDoes:B().describe(`One or two plain sentences, no jargon`),technical:B().optional().describe(`Where it lives in the code and how it works. Markdown: short paragraphs, and lists for parts, not one long block`),features:H(B()).optional().describe(`Feature names or ids (e.g. F-4) that create or change this capability; they're linked to it once it's approved`),reason:B().optional()}},a(({name:e,whatItDoes:n,technical:a,features:o,reason:s})=>t.call(`propose_capability`,{...r,p_name:e,p_what_it_does:n,p_technical:a??``,p_features:o??null,p_reason:s??null,p_agent:i()}))),n.registerTool(`propose_capability_archive`,{title:`Propose archiving a capability`,description:`Suggest retiring a capability that no longer describes what the product does, or that was drafted for something not built yet. Unshipped features linked to it will create a new capability when they ship. A person approves it.`,inputSchema:{capability:B().describe(`Capability name or id (e.g. C-12)`),reason:B().describe(`Why it should go`)}},a(({capability:e,reason:n})=>t.call(`propose_capability_archive`,{...r,p_capability:e,p_reason:n,p_agent:i()}))),n.registerTool(`propose_capability_update`,{title:`Propose a capability correction`,description:`Suggest a corrected name or description for a capability when the code no longer matches it. A person approves it.`,inputSchema:{capability:B().describe(`Capability name or id (e.g. C-12)`),field:W([`name`,`what_it_does`,`technical_description`]),after:B().describe(`The new name, or the corrected text. Markdown: short paragraphs, and lists for parts, not one long block`),reason:B().optional()}},a(({capability:e,field:n,after:a,reason:o})=>t.call(`propose_capability_update`,{...r,p_capability:e,p_field:n,p_after:a,p_reason:o??null,p_agent:i()}))),n.registerTool(`propose_capability_details`,{title:`Propose how a capability works and its connections`,description:`Suggest a capability's 'How it works' steps, its tags (glossary terms of kind 'tag'), the capability it's part of, and its connections: capabilities it relies on, repos, resources it runs on, glossary terms and docs. Each part you pass replaces that part when a person approves it; parts you leave out are kept. Names are matched to existing, approved items. What it relies on draws the arrows on the Home map, so link the steps a user goes through (e.g. invoicing relies on booking).`,inputSchema:{capability:B().describe(`Capability name or id (e.g. C-12)`),howItWorks:H(B()).optional().describe(`3 to 5 plain-language steps, as the user experiences it`),reliesOn:H(U({capability:B().describe(`Capability name or id (e.g. C-12)`),label:B().describe(`How it relies on it, read before the name, e.g. 'extends'`)})).optional(),parent:B().optional().describe(`The capability this one is part of (name or id, e.g. C-2), or 'none' to make it top-level. Parts are listed under their parent instead of on their own`),repos:H(B()).optional().describe(`Repo names`),resources:H(B()).optional().describe(`Resource names it runs on`),terms:H(B()).optional().describe(`Glossary terms`),docs:H(B()).optional().describe(`Doc titles, or <repo>/<path> (e.g. quirl/AGENTS.md) when titles repeat`),tags:H(B()).optional().describe(`Who it's for (Customer, Admin, Developer, Agent) and its kind (Interface, Integration, Data, Automation, Infrastructure, Access and security, AI): the capability tag sets in quirl_context`),reason:B().optional()}},a(({capability:e,howItWorks:n,reliesOn:a,parent:o,repos:s,resources:c,terms:l,docs:u,tags:d,reason:f})=>t.call(`propose_capability_details`,{...r,p_capability:e,p_how_it_works:n??null,p_relies_on:a??null,p_parent:o??null,p_repos:s??null,p_resources:c??null,p_terms:l??null,p_docs:u??null,p_tags:d??null,p_reason:f??null,p_agent:i()}))),n}async function ex(e){await $b(e).connect(new Mb)}const tx=`0.1.11`,nx=process.env.QUIRL_SERVER===`local`?{apiUrl:`http://127.0.0.1:54321`,publishableKey:`sb_publishable_ACJWlzQHlZjBrEguHvfOxg_3BJgxAaH`,appUrl:`http://localhost:5173`}:{apiUrl:`https://dugevhzlzrdtasuibdzr.supabase.co`,publishableKey:`sb_publishable_45P7GyyZoJsN0AO3wfmqNA_CXbx1iCW`,appUrl:`https://app.quirl.io`};function rx(){return{apiUrl:process.env.QUIRL_API_URL??nx.apiUrl,publishableKey:process.env.QUIRL_PUBLISHABLE_KEY??nx.publishableKey,appUrl:process.env.QUIRL_APP_URL??nx.appUrl}}const ix=()=>x(process.env.XDG_CONFIG_HOME??x(h(),`.config`),`quirl`),ax=()=>x(ix(),`credentials.json`);async function ox(){try{return JSON.parse(await u(ax(),`utf8`))}catch{return{}}}async function sx(){return process.env.QUIRL_KEY?{apiUrl:rx().apiUrl,key:process.env.QUIRL_KEY,email:``}:(await ox())[rx().apiUrl]??null}async function cx(e){let t=await ox();t[e.apiUrl]=e,await l(ix(),{recursive:!0,mode:448}),await m(ax(),`${JSON.stringify(t,null,` `)}\n`,{mode:384}),await s(ax(),384)}async function lx(){let e=await ox();delete e[rx().apiUrl],Object.keys(e).length?await m(ax(),`${JSON.stringify(e,null,` `)}\n`,{mode:384}):await f(ax(),{force:!0})}async function ux(){let e=rx();return{apiUrl:e.apiUrl,publishableKey:e.publishableKey,key:(await sx())?.key??``}}function dx(e){return(e.repos??[]).map(e=>typeof e==`string`?{path:e}:e)}function fx(e=process.cwd()){try{return a(`git`,[`rev-parse`,`--show-toplevel`],{cwd:e,stdio:[`ignore`,`pipe`,`ignore`]}).toString().trim()}catch{return e}}const px=e=>x(e,`.quirl`,`project.json`);async function mx(e=process.cwd()){let t=e;for(;;)try{return{root:t,link:JSON.parse(await u(px(t),`utf8`))}}catch{let e=y(t);if(e===t)return null;t=e}}async function hx(e,t){await l(x(e,`.quirl`),{recursive:!0}),await m(px(e),`${JSON.stringify(t,null,` `)}\n`)}function gx(e){let t=``;for(let n=0;n<e.length;n++){let r=e[n];r===`*`?e[n+1]===`*`?(t+=e[n+2]===`/`?`(?:.*/)?`:`.*`,n+=e[n+2]===`/`?2:1):t+=`[^/]*`:t+=r===`?`?`[^/]`:r.replace(/[.+^${}()|[\]\\]/g,`\\$&`)}return RegExp(`^${t}$`)}function _x(e){let t=[];for(let n of e.split(/\r?\n/)){let e=n.replace(/\s+$/,``);if(!e||e.startsWith(`#`))continue;let r=e.startsWith(`!`);r&&(e=e.slice(1));let i=e.endsWith(`/`);i&&(e=e.slice(0,-1));let a=e.includes(`/`);e=e.replace(/^\//,``);let o=gx(e).source.slice(1,-1);t.push({regex:RegExp(a?`^${o}$`:`^(?:.*/)?${o}$`),negate:r,dirOnly:i})}return t}function vx(e,t){if(!e.length)return!1;let n=t.split(`/`);for(let t=1;t<=n.length;t++){let r=n.slice(0,t).join(`/`),i=t<n.length,a=!1;for(let t of e)(!t.dirOnly||i)&&t.regex.test(r)&&(a=!t.negate);if(a)return!0}return!1}async function yx(e){try{return _x(await u(_.join(e,`.quirlignore`),`utf8`))}catch{return[]}}function bx(e,t){return new Promise(n=>{if(!t.length)return n(/* @__PURE__ */ new Set);i(`git`,[`check-ignore`,`--stdin`,`-z`],{cwd:e,maxBuffer:268435456,timeout:6e4},(e,t)=>n(new Set(String(t??``).split(`\0`).filter(Boolean)))).stdin?.end(`${t.join(`\0`)}\0`)})}const xx=n(i),Sx=/* @__PURE__ */ new Set([`.git`,`node_modules`,`dist`,`build`,`.next`,`vendor`,`.venv`,`venv`,`__pycache__`,`coverage`,`.turbo`,`.svelte-kit`,`.nuxt`,`.output`,`.cache`,`.vercel`,`.pnpm-store`,`fixtures`,`test-fixtures`,`__fixtures__`,`testdata`]),Cx=1048576,wx=2e5;async function Tx(e){let t=[],n=await yx(e),r=(await Dx(e,t)).filter(e=>!vx(n,e.path)),i=await bx(e,r.map(e=>e.path)),a=r.filter(e=>!i.has(e.path)),o=new Map(a.map(e=>[e.path,e]));return{root:e,files:a,warnings:t,file:e=>o.get(e),async readText(e,n=Cx){if(e.size>n)return t.push(`${e.path}: skipped, ${Px(e.size)} is over the ${Px(n)} limit`),null;try{return await u(e.absolutePath,`utf8`)}catch(n){return t.push(`${e.path}: could not be read (${Mx(n)})`),null}}}}async function Ex(e,t){let n=[],r=await yx(e),{stdout:i}=await xx(`git`,[`ls-tree`,`-r`,`-l`,`-z`,`--full-tree`,t],{cwd:e,maxBuffer:268435456,timeout:6e4}),a=[];for(let e of i.split(`\0`)){let t=e.indexOf(` `);if(t===-1)continue;let[i,o,s,c]=e.slice(0,t).trim().split(/\s+/),l=e.slice(t+1);if(o===`blob`&&i!==`120000`&&s&&!l.split(`/`).some(e=>Sx.has(e))&&!vx(r,l)){if(a.length>=wx){n.push(`Stopped after ${wx} files; the rest of the tree was not scanned`);break}a.push({path:l,absolutePath:s,size:Number(c)||0})}}Ox(a);let o=new Map(a.map(e=>[e.path,e]));return{root:e,files:a,warnings:n,file:e=>o.get(e),async readText(t,r=Cx){if(t.size>r)return n.push(`${t.path}: skipped, ${Px(t.size)} is over the ${Px(r)} limit`),null;try{let{stdout:n}=await xx(`git`,[`cat-file`,`blob`,t.absolutePath],{cwd:e,maxBuffer:r+1024,timeout:3e4});return n}catch(e){return n.push(`${t.path}: could not be read (${Mx(e)})`),null}}}}async function Dx(e,t){let n=[],r=[``];for(;r.length>0;){let i=r.pop(),a;try{a=await d(_.join(e,i),{withFileTypes:!0})}catch(e){t.push(`${i||`.`}: folder could not be read (${Mx(e)})`);continue}for(let o of a){let a=i?`${i}/${o.name}`:o.name;if(o.isSymbolicLink())continue;if(o.isDirectory()){!Sx.has(o.name)&&!C(_.join(e,a,`.git`))&&r.push(a);continue}if(!o.isFile())continue;if(n.length>=wx)return t.push(`Stopped after ${wx} files; the rest of the tree was not scanned`),Ox(n);let s=_.join(e,a);try{let e=await c(s);n.push({path:a,absolutePath:s,size:e.size})}catch(e){t.push(`${a}: could not be read (${Mx(e)})`)}}}return Ox(n)}function Ox(e){return e.sort((e,t)=>e.path<t.path?-1:+(e.path>t.path))}function kx(e){let t=e.lastIndexOf(`/`);return t===-1?e:e.slice(t+1)}function Ax(e){let t=e.lastIndexOf(`/`);return t===-1?``:e.slice(0,t)}function jx(e,t){return e?`${e}/${t}`:t}function Mx(e){return Kr(e instanceof Error?e.message:String(e))}function Z(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Nx(e){return typeof e==`string`?e:void 0}function Px(e){return e>=1048576?`${(e/1048576).toFixed(1)} MB`:`${Math.ceil(e/1024)} KB`}async function Fx({hook:e=!1}={}){let t=await mx();if(!t){if(e)return;throw Error("This folder isn't linked to a Quirl project. Run `quirl init`.")}try{let n=await new Wr(await ux()).context(t.link.projectId);process.stdout.write(`${zb(n,e?9500:void 0)}\n`)}catch(n){if(!e)throw n;process.stdout.write(`Quirl project "${t.link.name}": couldn't load the briefing (${Mx(n)}). The quirl MCP tools may still work.\n`)}}const Ix=process.stdout.isTTY&&!process.env.NO_COLOR,Lx=e=>t=>Ix?`\x1b[${e}m${t}\x1b[0m`:t,Rx=Lx(1),Q=Lx(2),zx=Lx(32),Bx=Lx(31),Vx=Lx(36),Hx=e=>console.log(`${zx(`✓`)} ${e}`),Ux=e=>console.log(` ${e}`),Wx=(e,t)=>console.log(`\n${e} ${t}`),Gx=e=>console.log(` ${e}`);function Kx(e){if(!Ix)return Gx(Q(e)),{stop:()=>{}};let t=0,n=setInterval(()=>{process.stdout.write(`\r ${Vx(`⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏`[t++%10]??``)} ${Q(e)}`)},80);return{stop:()=>{clearInterval(n),process.stdout.write(`\r\x1B[2K`)}}}var qx=class extends Error{};async function Jx(e,t=``){if(!process.stdin.isTTY)return t;let n=w({input:process.stdin,output:process.stdout});try{return(await n.question(e)).trim()||t}finally{n.close()}}async function Yx(e,t){let n=await Jx(`${e} ${Q(t?`[Y/n]`:`[y/N]`)} `,t?`y`:`n`);return/^y/i.test(n)}function Xx(e){if(process.env.QUIRL_NO_BROWSER)return;let t=process.platform===`darwin`?`open`:process.platform===`win32`?`cmd`:`xdg-open`,n=process.platform===`win32`?[`/c`,`start`,``,e]:[e];try{o(t,n,{stdio:`ignore`,detached:!0}).on(`error`,()=>{}).unref()}catch{}}const Zx=`.quirl-export.json`,Qx=e=>e.toLowerCase().normalize(`NFKD`).replace(/[̀-ͯ]/g,``).replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``).slice(0,80)||`untitled`;function $x(e){return`---\n${[[`title`,e.title],[`type`,e.type],[`status`,e.status],[`source`,e.source],[`alwaysLoad`,e.alwaysLoad],[`id`,e.id],[`created`,e.createdAt],[`updated`,e.updatedAt]].map(([e,t])=>`${e}: ${JSON.stringify(t)}`).join(`
214
+ - If the project briefing isn't already in your context, call quirl_context first.`}),r={p_project:e.project},i=()=>({tool:n.server.getClientVersion()?.name??`mcp`,model:process.env.QUIRL_AGENT_MODEL}),a=e=>async t=>{try{return Kb(await e(t))}catch(e){if(e instanceof Ur)return{...Kb(e.message),isError:!0};throw e}};n.registerTool(`quirl_context`,{title:`Project briefing`,description:`The project briefing: always-loaded docs in full, glossary, capabilities, your open tasks and the list of other docs. Usually already loaded at session start.`,inputSchema:{}},a(async()=>zb(await t.context(e.project)))),n.registerTool(`search_docs`,{title:`Search docs`,description:`Full-text search across the project's docs (README, ADRs, guides, runbooks). Returns matching sections with their content. Use for anything not in the briefing.`,inputSchema:{query:B().describe(`Words to search for, e.g. 'refund approval limits'`),limit:V().int().min(1).max(20).optional()}},a(({query:e,limit:n})=>t.call(`search_docs`,{...r,p_query:e,p_limit:n??6}))),n.registerTool(`read_doc`,{title:`Read a doc`,description:`Read one doc in full, by id, title or source path. source says where it lives: 'quirl' for docs written in Quirl (editable with edit_doc), otherwise the repo or folder it's synced from.`,inputSchema:{doc:B().describe(`Doc id, title or path, e.g. 'docs/adr/004-queues.md'`)}},a(({doc:e})=>t.call(`read_doc`,{...r,p_doc:e})));let o=[`product`,`guideline`,`architecture`,`decision`,`how_to`,`reference`];n.registerTool(`create_doc`,{title:`Write a new doc`,description:`Write a doc in Quirl itself: a PRD, spec or product note with no file behind it. Docs about code that tests or builds rely on belong in their repo, where sync picks them up. Use product for PRDs and specs. Never include secret values.`,inputSchema:{title:B(),body:B().describe(`Markdown. Headings (##, ###) split it into sections edit_doc can change one at a time.`),type:W(o).optional().describe(`Defaults to reference`)}},a(({title:e,body:n,type:a})=>t.call(`create_doc`,{...r,p_title:e,p_body:n,p_type:a??`reference`,p_agent:i()}))),n.registerTool(`edit_doc`,{title:`Edit a doc written in Quirl`,description:`Change one section of a doc written in Quirl, or the whole doc, without rewriting the rest. A section is named by its heading, or by its path when a heading repeats ('Billing > Refunds'). replace swaps the section's text (keeping its heading, unless the new text starts with one); append adds to the end of it. Without a section, replace rewrites the doc and append adds to its end. Docs synced from a repo or folder are changed there instead. The edit fails if the doc changed since it was read, rather than overwriting that change.`,inputSchema:{doc:B().describe(`Doc id or title`),section:B().optional().describe(`Heading text or path, e.g. 'Scope' or 'Billing > Refunds'`),content:B().describe(`Markdown`),mode:W([`replace`,`append`]).optional().describe(`Defaults to replace`),title:B().optional().describe(`A new title for the doc`),type:W(o).optional()}},a(async({doc:e,section:n,content:a,mode:o,title:s,type:c})=>{let l=await t.call(`read_doc`,{...r,p_doc:e});if(!l.editable)throw new Ur(`"${l.title}" comes from ${l.source}. Change it there; sync brings it into Quirl.`);let u;try{u=Gb(l.body,n,a,o??`replace`)}catch(e){throw new Ur(e.message)}return{...await t.call(`update_doc`,{...r,p_doc:l.id,p_title:s??null,p_body:u,p_type:c??null,p_expected_hash:l.contentHash,p_agent:i()}),edited:n??`the whole doc`,sections:Hb(u)}})),n.registerTool(`doc_history`,{title:`A doc's history`,description:`Who changed a doc and when, newest first, with lines added and removed. Pass a version to see what it changed (a diff against the version before), or full to get that version's whole text, e.g. to bring back wording with edit_doc.`,inputSchema:{doc:B().describe(`Doc id or title`),version:V().int().optional(),full:em().optional().describe(`With version: its whole text instead of the diff`)}},a(async({doc:e,version:n,full:i})=>{let a=await t.call(`doc_history`,{...r,p_doc:e,p_limit:n?200:21}),o=a.versions,s=e=>o.find(t=>t.version===e-1);if(n){let e=o.find(e=>e.version===n);if(!e)throw new Ur(`"${a.title}" has no version ${n}; the latest is ${o[0]?.version??0}.`);if(i)return{version:n,title:e.title,body:e.body};let t=s(n);return{version:n,author:e.author??`unknown`,at:e.createdAt,...t&&t.title!==e.title?{renamed:`${t.title} → ${e.title}`}:{},diff:t?Ib(t.body,e.body)||`(no text changes)`:`(first version)`}}return{title:a.title,source:a.source,versions:o.slice(0,20).map(e=>{let t=s(e.version);return{version:e.version,author:e.author??`unknown`,at:e.createdAt,change:t?Pb(Nb(t.body,e.body)):`first version`}})}})),n.registerTool(`archive_doc`,{title:`Archive a doc written in Quirl`,description:`Remove a doc written in Quirl that's no longer true or was a mistake. It's archived and stays in history. Docs synced from a repo or folder are deleted there instead.`,inputSchema:{doc:B().describe(`Doc id or title`),reason:B().optional().describe(`Why, for history`)}},a(({doc:e,reason:n})=>t.call(`archive_doc`,{...r,p_doc:e,p_reason:n??null,p_agent:i()}))),n.registerTool(`lookup`,{title:`Look up a term, capability or contract`,description:`Find glossary terms, capabilities, features and API/table contracts matching a name. Use it to check what a word means here, or the request/response shape of an endpoint or table.`,inputSchema:{query:B().describe(`A term, capability, endpoint or table name, e.g. 'Visit' or 'POST /login'`)}},a(({query:e})=>t.call(`lookup`,{...r,p_query:e})));let s=(e,t,r,i)=>{n.registerTool(e,r,i),n.registerTool(t,{...r,description:`Old name for ${e}; use ${e}. ${r.description}`},i)};s(`list_tasks`,`list_cards`,{title:`List tasks`,description:`List tasks on the board. Defaults to your own tasks that aren't done.`,inputSchema:{onlyMine:em().optional(),includeDone:em().optional()}},a(({onlyMine:e,includeDone:n})=>t.call(`list_cards`,{...r,p_only_mine:e??!0,p_include_done:n??!1})));let c=`Markdown: short paragraphs, and lists for steps or parts, not one long block.`,l=`Kind of work: e.g. Frontend, Backend, Database, Design, DevOps, Testing, Docs, Research. Only tags from the task set are accepted (see tagSets in quirl_context); propose a new value with propose_term (kind tag, tagSet task_work).`,u=B().describe(`Task number, e.g. 'K-104' or '104'`),d=B().optional().describe(`Who does it: "me", a member's email or name (only people on the project), or "none"`);return s(`get_task`,`get_card`,{title:`Get a task`,description:`A task with its feature, docs, dependencies and evidence.`,inputSchema:{task:u.optional(),card:u.optional()}},a(({task:e,card:n})=>t.call(`get_card`,{...r,p_card:e??n}))),s(`create_task`,`create_card`,{title:`Create a task`,description:`Add a task to the board (status: todo). Use it for work you discover that should be tracked. Put it under the feature it serves.`,inputSchema:{title:B(),description:B().optional().describe(`What to do and why. ${c}`),type:W([`feature_work`,`bug`,`chore`,`research`]).optional(),feature:B().optional().describe(`Feature name or id (e.g. F-4) this task belongs to`),tags:H(B()).optional().describe(l),assignee:d.describe(`Who does it: "me" (the default), a member's email or name, or "none"`)}},a(async({title:e,description:n,type:a,feature:o,tags:s,assignee:c})=>{let l=await t.call(`create_card`,{...r,p_title:e,p_description:n??``,p_type:a??`feature_work`,p_feature:o??null,p_agent:i()});return(s?.length||c)&&await t.call(`update_card`,{...r,p_card:l,p_patch:{...s?.length?{tags:s}:{},...c?{assignee:c}:{}},p_agent:i()}),l})),s(`update_task`,`update_card`,{title:`Update a task`,description:`Move a task, mark it blocked (with a reason) or unblocked, assign it, put it under a feature, set its tags, rewrite its title or description, and attach evidence: a branch, commit or pull request. Repos are referenced by name.`,inputSchema:{task:u.optional(),card:u.optional(),assignee:d,status:W([`backlog`,`todo`,`in_progress`,`review`,`done`]).optional(),feature:B().optional().describe(`Feature name or id (e.g. F-4) to put the task under; an empty string takes it off its feature`),title:B().optional(),description:B().optional().describe(`Replaces the description. ${c}`),tags:H(B()).optional().describe(`${l} Replaces the current tags.`),blocked:em().optional(),blockedReason:B().optional(),addBranch:U({repo:B(),name:B()}).optional(),addCommit:U({repo:B(),sha:B(),message:B().optional()}).optional(),addPullRequest:U({repo:B(),number:V().int(),url:B(),state:W([`open`,`merged`,`closed`]).optional()}).optional()}},a(({task:e,card:n,...a})=>t.call(`update_card`,{...r,p_card:e??n,p_patch:a,p_agent:i()}))),n.registerTool(`archive_task`,{title:`Archive a task`,description:`Remove a task that shouldn't be there: a duplicate or a mistake. It's archived and stays in history, and its feature's status is worked out without it. For work that's finished, move it to done instead.`,inputSchema:{task:u,reason:B().optional().describe(`Why, for history`)}},a(({task:e,reason:n})=>t.call(`archive_card`,{...r,p_card:e,p_reason:n??null,p_agent:i()}))),n.registerTool(`propose_term`,{title:`Propose a glossary term`,description:`Suggest a new glossary term. It shows up for approval; it isn't used until a person approves it.`,inputSchema:{term:B(),plain:B().describe(`What it means, for someone non-technical`),technical:B().describe(`What it means in the code`),kind:W([`concept`,`tag`,`name`]).optional(),tagSet:B().optional().describe(`Required for kind 'tag': the set the value belongs to, e.g. feature_change, task_work, capability_audience, capability_kind (see tagSets in quirl_context)`),reason:B().optional()}},a(({term:e,plain:n,technical:a,kind:o,tagSet:s,reason:c})=>t.call(`propose_term`,{...r,p_term:e,p_plain:n,p_technical:a,p_kind:o??`concept`,p_tag_set:s??null,p_reason:c??null,p_agent:i()}))),n.registerTool(`propose_term_retire`,{title:`Retire a glossary term`,description:`Propose retiring a glossary term or tag that's no longer used or was a mistake. With replaceWith, the term stays as one not to say (agents are told the replacement); without it, it's removed. Either way it comes off every capability, task and feature that used it. A person approves it. Built-in tag values can't be retired.`,inputSchema:{term:B().describe(`The term or tag to retire`),replaceWith:B().optional().describe(`An approved term to say instead, if there is one`),reason:B().optional()}},a(({term:e,replaceWith:n,reason:a})=>t.call(`propose_term_retire`,{...r,p_term:e,p_replace_with:n??null,p_reason:a??null,p_agent:i()}))),n.registerTool(`list_flags`,{title:`List flags`,description:`Flags are messages people send about a section of the project: a capability, feature, task, doc or glossary term. Lists open (waiting for an admin) and approved (to act on) flags, or only those with the given status.`,inputSchema:{status:W([`open`,`approved`,`removed`,`done`]).optional()}},a(({status:e})=>t.call(`list_flags`,{...r,p_status:e??null}))),n.registerTool(`decide_flag`,{title:`Approve or remove a flag`,description:`Admins only. Approve a flag so agents act on it at the start of their sessions, or remove it. An approved flag can still be removed. Only do this when the person you work for asks you to.`,inputSchema:{flag:B().describe(`The flag's id, from the briefing or list_flags`),decision:W([`approve`,`remove`])}},a(({flag:e,decision:n})=>t.call(`decide_flag`,{...r,p_flag:e,p_approve:n===`approve`,p_agent:i()}))),n.registerTool(`resolve_flag`,{title:`Mark a flag done`,description:`Mark an approved flag done once you've handled it, so it leaves the briefing. Say briefly what you did.`,inputSchema:{flag:B().describe(`The flag's id, from the briefing or list_flags`),note:B().optional().describe(`What was done, e.g. 'Updated C-12 to mention SMS'`)}},a(({flag:e,note:n})=>t.call(`resolve_flag`,{...r,p_flag:e,p_note:n??null,p_agent:i()}))),n.registerTool(`set_capability_icon`,{title:`Set a capability's icon`,description:`Give a capability an icon that fits what it does; it's shown on the capability's card. Use the same icon a related feature has when one fits both.`,inputSchema:{capability:B().describe(`Capability name or id (e.g. C-12)`),icon:W(Lb)}},a(({capability:e,icon:n})=>t.call(`set_capability_icon`,{...r,p_capability:e,p_icon:n,p_agent:i()}))),n.registerTool(`add_resource`,{title:`Add or fill in a resource`,description:"Record a service the project runs on that `quirl sync` can't see from the code: a hosted database another team runs, a SaaS named only in docs or the console, a staging copy. Sync already finds most things from env templates, docker-compose and client packages, so check Stack first (lookup) and don't add what it found. A resource with the same provider and environment is filled in rather than duplicated: the fields you give are set, and repos and capabilities are added to its links. Never pass URLs with credentials, keys or other secret values.",inputSchema:{name:B().describe(`What the team calls it, e.g. "Postgres", "Stripe"`),type:W(qb),provider:B().optional().describe(`Who runs it, e.g. "Google Cloud SQL", "Stripe". Resources are matched on this. Defaults to the name.`),description:B().optional().describe(`One plain sentence on what the project uses it for`),technical:B().optional().describe(`Technical notes for developers: setup, access, limits`),environment:B().optional().describe(`Defaults to "production"; e.g. "staging"`),repos:H(B()).optional().describe(`Repos that use it, by name`),capabilities:H(B()).optional().describe(`Capabilities that run on it, by name or id (e.g. C-12)`),account:B().optional().describe(`The cloud project, account or team it lives in, e.g. GCP project "domainarium-staging". Sync files deployments, jobs and secrets by it. Never a key.`)}},a(e=>t.call(`add_resource`,{...r,p_name:e.name,p_type:e.type,p_provider:e.provider??null,p_description:e.description??null,p_technical:e.technical??null,p_environment:e.environment??null,p_repos:e.repos??null,p_capabilities:e.capabilities??null,p_account:e.account??null,p_agent:i()}))),n.registerTool(`list_resources`,{title:`List the project's resources`,description:`Every resource on Stack: name, type, provider, environment, whether sync found it or someone added it, the repos that use it, the capabilities that run on it, and the tables and endpoints filed under it (per repo, with a few names). Tables in the wrong database or endpoints under the wrong API: fix with move_contracts.`,inputSchema:{}},a(()=>t.call(`list_resources`,r))),n.registerTool(`update_resource`,{title:`Change a resource`,description:`Correct a resource: rename it, relabel its environment (a scanned one that's really the local docker database becomes 'local'), or change its type, provider, descriptions or links. Only the fields you pass change. repos and capabilities replace its links; use add_resource to add to them. A repo you take off stays off: sync won't link it again until a person adds it back. Sync keeps updating a relabelled resource instead of adding it again. Never pass secret values.`,inputSchema:{...Qb,name:B().optional(),type:W(qb).optional(),provider:B().optional(),environment:B().optional().describe(`e.g. "production", "staging", "dev", "local"`),description:B().optional().describe(`One plain sentence on what the project uses it for`),technical:B().optional().describe(`Notes for developers`),repos:H(B()).optional().describe(`Replaces the repos that use it. Ones left out stay off through later syncs.`),capabilities:H(B()).optional().describe(`Replaces the capabilities that run on it (names or C-12)`),account:B().optional().describe(`The cloud project, account or team it lives in, e.g. GCP project "domainarium-staging". Sync files deployments, jobs and secrets by it. Never a key. Empty clears it.`)}},a(e=>t.call(`update_resource`,{...r,p_resource:e.resource,p_in_environment:e.inEnvironment??null,p_name:e.name??null,p_type:e.type??null,p_provider:e.provider??null,p_environment:e.environment??null,p_description:e.description??null,p_technical:e.technical??null,p_repos:e.repos??null,p_capabilities:e.capabilities??null,p_account:e.account??null,p_agent:i()}))),n.registerTool(`remove_resource`,{title:`Remove a wrong resource`,description:`Remove a resource that isn't one: a false match from sync, a duplicate, something no longer used. It's archived, stays in history, and sync won't add it again. A resource holding endpoints or tables from sync can't be removed; relabel it instead.`,inputSchema:{...Qb,reason:B().optional().describe(`Why it's wrong, for history`)}},a(e=>t.call(`remove_resource`,{...r,p_resource:e.resource,p_in_environment:e.inEnvironment??null,p_reason:e.reason??null,p_agent:i()}))),n.registerTool(`get_resource`,{title:`Get a resource and what it holds`,description:`One resource with everything it holds: endpoints, tables, functions, deployments, variables (names only), jobs, domains, events, roles, models. Each with its fields (spec), whether sync found it or someone added it, and its links (what it runs, calls, uses or protects, and what points at it). Use before adding or changing what a resource holds.`,inputSchema:Qb},a(e=>t.call(`get_resource`,{...r,p_resource:e.resource,p_in_environment:e.inEnvironment??null}))),n.registerTool(`add_contract`,{title:`Add something a resource holds`,description:`Record what the code doesn't show: a Cloud Scheduler job set up in the console, the variables Secret Manager holds (names, never values), a Cloud Run service, the roles the product has, the AI models it calls, a webhook it receives, a domain. Sync finds endpoints and tables from OpenAPI files and migrations, so check get_resource first. What you add stays until someone removes it; if sync later finds the same thing in code, it takes it over. Never pass secret values, keys or URLs with credentials.\n\n${Xb}`,inputSchema:{...Qb,kind:W(Jb),name:B().optional().describe(`e.g. "nightly-invoices", "STRIPE_SECRET_KEY", "admin", "claude-opus-5-5". Endpoints default to "METHOD /path".`),description:B().optional().describe(`One plain sentence: what it is or does`),spec:_m(B(),im()).optional().describe(`The kind's fields; see the list above`),repo:B().optional().describe(`The repo it belongs to, if any`),links:Zb.optional()}},a(e=>t.call(`add_contract`,{...r,p_resource:e.resource,p_in_environment:e.inEnvironment??null,p_kind:e.kind,p_name:e.name??null,p_description:e.description??null,p_spec:e.spec??null,p_repo:e.repo??null,p_links:e.links??null,p_agent:i()}))),n.registerTool(`update_contract`,{title:`Change something a resource holds`,description:`Correct or fill in a contract: its description, its fields, its links. spec is merged: given fields are set, a field set to null is removed. links, when given, replace the links people added (sync's stay). On something sync found (an endpoint from OpenAPI, a table from migrations) only the description and links change here; the rest follows the code. To file it under another resource, use move_contracts.\n\n${Xb}`,inputSchema:{contract:B().describe(`kind:name ("job:nightly-invoices", "endpoint:GET /domains"), a unique name, or its id (from get_resource)`),resource:B().optional().describe(`Its resource, when the name is in several`),inEnvironment:B().optional(),name:B().optional(),description:B().optional(),spec:_m(B(),im()).optional(),links:Zb.optional()}},a(e=>t.call(`update_contract`,{...r,p_contract:e.contract,p_resource:e.resource??null,p_in_environment:e.inEnvironment??null,p_name:e.name??null,p_description:e.description??null,p_spec:e.spec??null,p_links:e.links??null,p_agent:i()}))),n.registerTool(`remove_contract`,{title:`Remove something added to a resource`,description:`Remove a contract someone added that's wrong or gone: a deleted job, a retired variable. It's archived and stays in history. What sync found from code can't be removed here: change the code, or move it with move_contracts if it's filed in the wrong place.`,inputSchema:{contract:B().describe(`kind:name ("variable:OLD_KEY"), a unique name, or its id`),resource:B().optional(),inEnvironment:B().optional(),reason:B().optional().describe(`Why, for history`)}},a(e=>t.call(`remove_contract`,{...r,p_contract:e.contract,p_resource:e.resource??null,p_in_environment:e.inEnvironment??null,p_reason:e.reason??null,p_agent:i()}))),n.registerTool(`move_contracts`,{title:`Move what sync filed to another resource`,description:`Correct where sync filed a repo's tables (which database), endpoints (which API), deployments (which Cloud Run project), jobs, variables, functions, roles or models. Without names, all of the repo's ones of that kind move and later syncs put new ones there too. With names, only those move and sync leaves them there. list_resources shows what's filed where. For deployments in the wrong environment, setting the resource's account (update_resource) also fixes later syncs. With also, they're filed under this resource as well as where they are: the same endpoints served by the dev and the prod API.`,inputSchema:{repo:B().describe(`The repo they come from: name, URL or id`),kind:W([...Jb,`tables`,`endpoints`]),to:B().describe(`The resource they belong to: name, provider or id`),toEnvironment:B().optional().describe(`Its environment, when it exists in several`),names:H(B()).optional().describe(`Only these, e.g. ["bookings"] or ["GET /bookings"]; leave out to move all`),also:em().optional().describe(`Keep them where they are and file them here too, e.g. endpoints served in dev and in prod`)}},a(e=>t.call(`move_contracts`,{...r,p_repo:e.repo,p_kind:e.kind,p_to:e.to,p_in_environment:e.toEnvironment??null,p_names:e.names??null,p_also:e.also??!1,p_agent:i()}))),n.registerTool(`remove_repo`,{title:`Remove a repo`,description:"Remove a repo from the project, for admins: one that's retired, or was imported by mistake. Its dependencies, endpoints, tables and synced docs are archived with it, and it's unlinked from capabilities, tasks and resources. Sync skips it from then on; running `quirl init` in it adds it back. Only on the person's request: confirm with them first. To rename a repo instead, set its name in .quirl/project.json and sync.",inputSchema:{repo:B().describe(`The repo's name, URL or id`),reason:B().optional().describe(`Why it's removed, for history`)}},a(e=>t.call(`remove_repo`,{...r,p_repo:e.repo,p_reason:e.reason??null,p_agent:i()}))),n.registerTool(`list_features`,{title:`List features`,description:`List the project's features with their status, the capability each changes (or createsCapability when it has none), and task counts. Shipped ones are left out unless includeShipped. Check here before requesting a feature.`,inputSchema:{includeShipped:em().optional()}},a(({includeShipped:e})=>t.call(`list_features`,{...r,p_include_shipped:e??!1}))),n.registerTool(`get_feature`,{title:`Get a feature`,description:`A feature with its description, status, the capability it changes (and what that capability does) and its tasks.`,inputSchema:{feature:B().describe(`Feature name or id (e.g. F-4)`)}},a(({feature:e})=>t.call(`get_feature`,{...r,p_feature:e}))),n.registerTool(`request_feature`,{title:`Request a feature`,description:`Request a feature: a change to the product that stakeholders follow on the Features page, usually made of several tasks. Check list_features first so you don't request one twice. It shows as requested straight away and a person accepts or declines it. Put tasks under it with create_task or update_task.`,inputSchema:{name:B().describe(`Short name, e.g. 'Repeat appointments'`),description:B().describe(`What changes for the user, in plain words. Markdown: short paragraphs, and lists for parts`),capability:B().optional().describe(`Capability name or id (e.g. C-12) it changes. Leave it out when the feature creates a new capability`),tags:H(B()).optional().describe(`Kind of change: e.g. New, Improvement, Visual, Fix, Performance, Security, Removal, Internal (the feature_change set in quirl_context)`),reason:B().optional().describe(`Why it's worth doing`),icon:W(Lb).optional().describe(`An icon that fits the feature, shown on its card`)}},a(async({name:e,description:n,capability:a,tags:o,reason:s,icon:c})=>{let l=await t.call(`request_feature`,{...r,p_name:e,p_description:n,p_capability:a??null,p_tags:o??null,p_reason:s??null,p_agent:i()});return c&&l===`requested`&&await t.call(`set_feature_icon`,{...r,p_feature:e,p_icon:c,p_agent:i()}),l})),n.registerTool(`set_feature_icon`,{title:`Set a feature's icon`,description:`Give a feature an icon that fits what it does; it's shown on the feature's card. list_features shows which features have none.`,inputSchema:{feature:B().describe(`Feature name or id (e.g. F-4)`),icon:W(Lb)}},a(({feature:e,icon:n})=>t.call(`set_feature_icon`,{...r,p_feature:e,p_icon:n,p_agent:i()}))),n.registerTool(`update_feature`,{title:`Correct a feature`,description:`Fix a feature's name, description or the capability it changes, e.g. after requesting it with the wrong one. Only the fields you pass change; it shows in the feature's history. Tags: tag_feature; icon: set_feature_icon.`,inputSchema:{feature:B().describe(`Feature name or id (e.g. F-4)`),name:B().optional(),description:B().optional().describe(`What changes for the user, in plain words. Markdown: short paragraphs, and lists for parts`),capability:B().optional().describe(`The capability it changes (name or C-12), or "none" when it creates a new one`)}},a(({feature:e,name:n,description:a,capability:o})=>t.call(`update_feature`,{...r,p_feature:e,p_name:n??null,p_description:a??null,p_capability:o??null,p_agent:i()}))),n.registerTool(`withdraw_feature`,{title:`Withdraw a feature`,description:`Remove a feature that shouldn't be there: a duplicate, a mistake, or an idea dropped before any work. It's archived and stays in history. One that shipped can't be withdrawn; move or archive its tasks first (update_task, archive_task).`,inputSchema:{feature:B().describe(`Feature name or id (e.g. F-4)`),reason:B().optional().describe(`Why, for history`)}},a(({feature:e,reason:n})=>t.call(`withdraw_feature`,{...r,p_feature:e,p_reason:n??null,p_agent:i()}))),n.registerTool(`tag_feature`,{title:`Tag a feature`,description:`Set a feature's kind-of-change tags (replaces the current ones). Only values from the feature_change tag set are accepted.`,inputSchema:{feature:B().describe(`Feature name or id (e.g. F-4)`),tags:H(B()).describe(`Kind of change: e.g. New, Improvement, Visual, Fix, Performance, Security, Removal, Internal`)}},a(({feature:e,tags:n})=>t.call(`tag_feature`,{...r,p_feature:e,p_tags:n,p_agent:i()}))),n.registerTool(`list_capabilities`,{title:`List the capabilities`,description:`Every capability as data: id (C-12), name, status, icon, the capability it's part of, what it does, what it relies on, its tags and the features changing it. Retired ones only with includeRetired.`,inputSchema:{includeRetired:em().optional()}},a(({includeRetired:e})=>t.call(`list_capabilities`,{...r,p_include_retired:e??!1}))),n.registerTool(`propose_capability`,{title:`Propose a capability`,description:"Draft a capability: one thing the product does today, described for a non-technical reader. Use it when the project has none yet (for example right after `quirl init`), when you find one that's missing, or when a feature that creates a new capability ships (pass it in features). Never for something not built yet: request a feature instead. A person approves it before it shows up.",inputSchema:{name:B().describe(`Short name, e.g. 'Online booking'`),whatItDoes:B().describe(`One or two plain sentences, no jargon`),technical:B().optional().describe(`Where it lives in the code and how it works. Markdown: short paragraphs, and lists for parts, not one long block`),features:H(B()).optional().describe(`Feature names or ids (e.g. F-4) that create or change this capability; they're linked to it once it's approved`),reason:B().optional()}},a(({name:e,whatItDoes:n,technical:a,features:o,reason:s})=>t.call(`propose_capability`,{...r,p_name:e,p_what_it_does:n,p_technical:a??``,p_features:o??null,p_reason:s??null,p_agent:i()}))),n.registerTool(`propose_capability_archive`,{title:`Propose archiving a capability`,description:`Suggest retiring a capability that no longer describes what the product does, or that was drafted for something not built yet. Unshipped features linked to it will create a new capability when they ship. A person approves it.`,inputSchema:{capability:B().describe(`Capability name or id (e.g. C-12)`),reason:B().describe(`Why it should go`)}},a(({capability:e,reason:n})=>t.call(`propose_capability_archive`,{...r,p_capability:e,p_reason:n,p_agent:i()}))),n.registerTool(`propose_capability_update`,{title:`Propose a capability correction`,description:`Suggest a corrected name or description for a capability when the code no longer matches it. A person approves it.`,inputSchema:{capability:B().describe(`Capability name or id (e.g. C-12)`),field:W([`name`,`what_it_does`,`technical_description`]),after:B().describe(`The new name, or the corrected text. Markdown: short paragraphs, and lists for parts, not one long block`),reason:B().optional()}},a(({capability:e,field:n,after:a,reason:o})=>t.call(`propose_capability_update`,{...r,p_capability:e,p_field:n,p_after:a,p_reason:o??null,p_agent:i()}))),n.registerTool(`propose_capability_details`,{title:`Propose how a capability works and its connections`,description:`Suggest a capability's 'How it works' steps, its tags (glossary terms of kind 'tag'), the capability it's part of, and its connections: capabilities it relies on, repos, resources it runs on, glossary terms and docs. Each part you pass replaces that part when a person approves it; parts you leave out are kept. Names are matched to existing, approved items. What it relies on draws the arrows on the Home map, so link the steps a user goes through (e.g. invoicing relies on booking).`,inputSchema:{capability:B().describe(`Capability name or id (e.g. C-12)`),howItWorks:H(B()).optional().describe(`3 to 5 plain-language steps, as the user experiences it`),reliesOn:H(U({capability:B().describe(`Capability name or id (e.g. C-12)`),label:B().describe(`How it relies on it, read before the name, e.g. 'extends'`)})).optional(),parent:B().optional().describe(`The capability this one is part of (name or id, e.g. C-2), or 'none' to make it top-level. Parts are listed under their parent instead of on their own`),repos:H(B()).optional().describe(`Repo names`),resources:H(B()).optional().describe(`Resource names it runs on`),terms:H(B()).optional().describe(`Glossary terms`),docs:H(B()).optional().describe(`Doc titles, or <repo>/<path> (e.g. quirl/AGENTS.md) when titles repeat`),tags:H(B()).optional().describe(`Who it's for (Customer, Admin, Developer, Agent) and its kind (Interface, Integration, Data, Automation, Infrastructure, Access and security, AI): the capability tag sets in quirl_context`),reason:B().optional()}},a(({capability:e,howItWorks:n,reliesOn:a,parent:o,repos:s,resources:c,terms:l,docs:u,tags:d,reason:f})=>t.call(`propose_capability_details`,{...r,p_capability:e,p_how_it_works:n??null,p_relies_on:a??null,p_parent:o??null,p_repos:s??null,p_resources:c??null,p_terms:l??null,p_docs:u??null,p_tags:d??null,p_reason:f??null,p_agent:i()}))),n}async function ex(e){await $b(e).connect(new Mb)}const tx=`0.1.13`,nx=process.env.QUIRL_SERVER===`local`?{apiUrl:`http://127.0.0.1:54321`,publishableKey:`sb_publishable_ACJWlzQHlZjBrEguHvfOxg_3BJgxAaH`,appUrl:`http://localhost:5173`}:{apiUrl:`https://dugevhzlzrdtasuibdzr.supabase.co`,publishableKey:`sb_publishable_45P7GyyZoJsN0AO3wfmqNA_CXbx1iCW`,appUrl:`https://app.quirl.io`};function rx(){return{apiUrl:process.env.QUIRL_API_URL??nx.apiUrl,publishableKey:process.env.QUIRL_PUBLISHABLE_KEY??nx.publishableKey,appUrl:process.env.QUIRL_APP_URL??nx.appUrl}}const ix=()=>x(process.env.XDG_CONFIG_HOME??x(h(),`.config`),`quirl`),ax=()=>x(ix(),`credentials.json`);async function ox(){try{return JSON.parse(await u(ax(),`utf8`))}catch{return{}}}async function sx(){return process.env.QUIRL_KEY?{apiUrl:rx().apiUrl,key:process.env.QUIRL_KEY,email:``}:(await ox())[rx().apiUrl]??null}async function cx(e){let t=await ox();t[e.apiUrl]=e,await l(ix(),{recursive:!0,mode:448}),await m(ax(),`${JSON.stringify(t,null,` `)}\n`,{mode:384}),await s(ax(),384)}async function lx(){let e=await ox();delete e[rx().apiUrl],Object.keys(e).length?await m(ax(),`${JSON.stringify(e,null,` `)}\n`,{mode:384}):await f(ax(),{force:!0})}async function ux(){let e=rx();return{apiUrl:e.apiUrl,publishableKey:e.publishableKey,key:(await sx())?.key??``}}function dx(e){return(e.repos??[]).map(e=>typeof e==`string`?{path:e}:e)}function fx(e=process.cwd()){try{return a(`git`,[`rev-parse`,`--show-toplevel`],{cwd:e,stdio:[`ignore`,`pipe`,`ignore`]}).toString().trim()}catch{return e}}const px=e=>x(e,`.quirl`,`project.json`);async function mx(e=process.cwd()){let t=e;for(;;)try{return{root:t,link:JSON.parse(await u(px(t),`utf8`))}}catch{let e=y(t);if(e===t)return null;t=e}}async function hx(e,t){await l(x(e,`.quirl`),{recursive:!0}),await m(px(e),`${JSON.stringify(t,null,` `)}\n`)}function gx(e){let t=``;for(let n=0;n<e.length;n++){let r=e[n];r===`*`?e[n+1]===`*`?(t+=e[n+2]===`/`?`(?:.*/)?`:`.*`,n+=e[n+2]===`/`?2:1):t+=`[^/]*`:t+=r===`?`?`[^/]`:r.replace(/[.+^${}()|[\]\\]/g,`\\$&`)}return RegExp(`^${t}$`)}function _x(e){let t=[];for(let n of e.split(/\r?\n/)){let e=n.replace(/\s+$/,``);if(!e||e.startsWith(`#`))continue;let r=e.startsWith(`!`);r&&(e=e.slice(1));let i=e.endsWith(`/`);i&&(e=e.slice(0,-1));let a=e.includes(`/`);e=e.replace(/^\//,``);let o=gx(e).source.slice(1,-1);t.push({regex:RegExp(a?`^${o}$`:`^(?:.*/)?${o}$`),negate:r,dirOnly:i})}return t}function vx(e,t){if(!e.length)return!1;let n=t.split(`/`);for(let t=1;t<=n.length;t++){let r=n.slice(0,t).join(`/`),i=t<n.length,a=!1;for(let t of e)(!t.dirOnly||i)&&t.regex.test(r)&&(a=!t.negate);if(a)return!0}return!1}async function yx(e){try{return _x(await u(_.join(e,`.quirlignore`),`utf8`))}catch{return[]}}function bx(e,t){return new Promise(n=>{if(!t.length)return n(/* @__PURE__ */ new Set);i(`git`,[`check-ignore`,`--stdin`,`-z`],{cwd:e,maxBuffer:268435456,timeout:6e4},(e,t)=>n(new Set(String(t??``).split(`\0`).filter(Boolean)))).stdin?.end(`${t.join(`\0`)}\0`)})}const xx=n(i),Sx=/* @__PURE__ */ new Set([`.git`,`node_modules`,`dist`,`build`,`.next`,`vendor`,`.venv`,`venv`,`__pycache__`,`coverage`,`.turbo`,`.svelte-kit`,`.nuxt`,`.output`,`.cache`,`.vercel`,`.pnpm-store`,`fixtures`,`test-fixtures`,`__fixtures__`,`testdata`]),Cx=1048576,wx=2e5;async function Tx(e){let t=[],n=await yx(e),r=(await Dx(e,t)).filter(e=>!vx(n,e.path)),i=await bx(e,r.map(e=>e.path)),a=r.filter(e=>!i.has(e.path)),o=new Map(a.map(e=>[e.path,e]));return{root:e,files:a,warnings:t,file:e=>o.get(e),async readText(e,n=Cx){if(e.size>n)return t.push(`${e.path}: skipped, ${Px(e.size)} is over the ${Px(n)} limit`),null;try{return await u(e.absolutePath,`utf8`)}catch(n){return t.push(`${e.path}: could not be read (${Mx(n)})`),null}}}}async function Ex(e,t){let n=[],r=await yx(e),{stdout:i}=await xx(`git`,[`ls-tree`,`-r`,`-l`,`-z`,`--full-tree`,t],{cwd:e,maxBuffer:268435456,timeout:6e4}),a=[];for(let e of i.split(`\0`)){let t=e.indexOf(` `);if(t===-1)continue;let[i,o,s,c]=e.slice(0,t).trim().split(/\s+/),l=e.slice(t+1);if(o===`blob`&&i!==`120000`&&s&&!l.split(`/`).some(e=>Sx.has(e))&&!vx(r,l)){if(a.length>=wx){n.push(`Stopped after ${wx} files; the rest of the tree was not scanned`);break}a.push({path:l,absolutePath:s,size:Number(c)||0})}}Ox(a);let o=new Map(a.map(e=>[e.path,e]));return{root:e,files:a,warnings:n,file:e=>o.get(e),async readText(t,r=Cx){if(t.size>r)return n.push(`${t.path}: skipped, ${Px(t.size)} is over the ${Px(r)} limit`),null;try{let{stdout:n}=await xx(`git`,[`cat-file`,`blob`,t.absolutePath],{cwd:e,maxBuffer:r+1024,timeout:3e4});return n}catch(e){return n.push(`${t.path}: could not be read (${Mx(e)})`),null}}}}async function Dx(e,t){let n=[],r=[``];for(;r.length>0;){let i=r.pop(),a;try{a=await d(_.join(e,i),{withFileTypes:!0})}catch(e){t.push(`${i||`.`}: folder could not be read (${Mx(e)})`);continue}for(let o of a){let a=i?`${i}/${o.name}`:o.name;if(o.isSymbolicLink())continue;if(o.isDirectory()){!Sx.has(o.name)&&!C(_.join(e,a,`.git`))&&r.push(a);continue}if(!o.isFile())continue;if(n.length>=wx)return t.push(`Stopped after ${wx} files; the rest of the tree was not scanned`),Ox(n);let s=_.join(e,a);try{let e=await c(s);n.push({path:a,absolutePath:s,size:e.size})}catch(e){t.push(`${a}: could not be read (${Mx(e)})`)}}}return Ox(n)}function Ox(e){return e.sort((e,t)=>e.path<t.path?-1:+(e.path>t.path))}function kx(e){let t=e.lastIndexOf(`/`);return t===-1?e:e.slice(t+1)}function Ax(e){let t=e.lastIndexOf(`/`);return t===-1?``:e.slice(0,t)}function jx(e,t){return e?`${e}/${t}`:t}function Mx(e){return Kr(e instanceof Error?e.message:String(e))}function Z(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Nx(e){return typeof e==`string`?e:void 0}function Px(e){return e>=1048576?`${(e/1048576).toFixed(1)} MB`:`${Math.ceil(e/1024)} KB`}async function Fx({hook:e=!1}={}){let t=await mx();if(!t){if(e)return;throw Error("This folder isn't linked to a Quirl project. Run `quirl init`.")}try{let n=await new Wr(await ux()).context(t.link.projectId);process.stdout.write(`${zb(n,e?9500:void 0)}\n`)}catch(n){if(!e)throw n;process.stdout.write(`Quirl project "${t.link.name}": couldn't load the briefing (${Mx(n)}). The quirl MCP tools may still work.\n`)}}const Ix=process.stdout.isTTY&&!process.env.NO_COLOR,Lx=e=>t=>Ix?`\x1b[${e}m${t}\x1b[0m`:t,Rx=Lx(1),Q=Lx(2),zx=Lx(32),Bx=Lx(31),Vx=Lx(36),Hx=e=>console.log(`${zx(`✓`)} ${e}`),Ux=e=>console.log(` ${e}`),Wx=(e,t)=>console.log(`\n${e} ${t}`),Gx=e=>console.log(` ${e}`);function Kx(e){if(!Ix)return Gx(Q(e)),{stop:()=>{}};let t=0,n=setInterval(()=>{process.stdout.write(`\r ${Vx(`⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏`[t++%10]??``)} ${Q(e)}`)},80);return{stop:()=>{clearInterval(n),process.stdout.write(`\r\x1B[2K`)}}}var qx=class extends Error{};async function Jx(e,t=``){if(!process.stdin.isTTY)return t;let n=w({input:process.stdin,output:process.stdout});try{return(await n.question(e)).trim()||t}finally{n.close()}}async function Yx(e,t){let n=await Jx(`${e} ${Q(t?`[Y/n]`:`[y/N]`)} `,t?`y`:`n`);return/^y/i.test(n)}function Xx(e){if(process.env.QUIRL_NO_BROWSER)return;let t=process.platform===`darwin`?`open`:process.platform===`win32`?`cmd`:`xdg-open`,n=process.platform===`win32`?[`/c`,`start`,``,e]:[e];try{o(t,n,{stdio:`ignore`,detached:!0}).on(`error`,()=>{}).unref()}catch{}}const Zx=`.quirl-export.json`,Qx=e=>e.toLowerCase().normalize(`NFKD`).replace(/[̀-ͯ]/g,``).replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``).slice(0,80)||`untitled`;function $x(e){return`---\n${[[`title`,e.title],[`type`,e.type],[`status`,e.status],[`source`,e.source],[`alwaysLoad`,e.alwaysLoad],[`id`,e.id],[`created`,e.createdAt],[`updated`,e.updatedAt]].map(([e,t])=>`${e}: ${JSON.stringify(t)}`).join(`
215
215
  `)}\n---\n\n`}async function eS({dir:e=`quirl-docs`,all:t=!1}){let n=await mx();if(!n)throw new qx("This folder isn't linked to a Quirl project. Run `quirl init`.");let r=new Wr(await ux()),i=_.resolve(e);Wx(`📤`,`Exporting ${t?`all`:`Quirl-written`} docs from ${Rx(n.link.name)}`);let a=[];for(let e=0;;e+=100){let i=await r.call(`export_docs`,{p_project:n.link.projectId,p_only_quirl:!t,p_offset:e,p_limit:100});if(a.push(...i),i.length<100)break}let o=[],s=/* @__PURE__ */ new Set;await l(i,{recursive:!0});for(let e of a){let t=`${e.type}/${Qx(e.title)}.md`;for(let n=2;s.has(t);n++)t=`${e.type}/${Qx(e.title)}-${n}.md`;s.add(t),await l(_.join(i,e.type),{recursive:!0}),await m(_.join(i,t),$x(e)+e.body.replace(/\n*$/,`
216
216
  `)),o.push(t)}let c=0;try{let e=JSON.parse(await u(_.join(i,Zx),`utf8`));for(let t of e.files??[])s.has(t)||t.includes(`..`)||(await f(_.join(i,t),{force:!0}),c++)}catch{}await m(_.join(i,Zx),`${JSON.stringify({project:n.link.project,exportedAt:(/* @__PURE__ */ new Date()).toISOString(),all:t,files:o},null,` `)}\n`),Gx(`${zx(`✓`)} ${a.length} ${a.length===1?`doc`:`docs`} written to ${Vx(_.relative(process.cwd(),i)||`.`)}${c?Q(` · ${c} removed`):``}`),t||Gx(Q(`Docs synced from repos are left out; add --all to include them.`)),console.log(``)}async function tS(e,t=3){let n=[],r=async(e,i)=>{if(C(_.join(e,`.git`))&&n.push(e),i>=t)return;let a;try{a=await d(e,{withFileTypes:!0})}catch{return}for(let t of a)!t.isDirectory()||t.name.startsWith(`.`)||Sx.has(t.name)||await r(_.join(e,t.name),i+1)};return await r(_.resolve(e),0),n.sort((e,t)=>e.localeCompare(t))}const nS=`<!-- quirl:start -->`,rS=`<!-- quirl:end -->`,iS=`# quirl: keep the project in sync`;function aS(){try{let e=a(process.platform===`win32`?`where`:`which`,[`quirl`],{stdio:[`ignore`,`pipe`,`ignore`]}).toString();if(!/[\\/]_npx[\\/]/.test(e))return{command:`quirl`,args:[],shell:`quirl`,portable:!0}}catch{}return{command:`npx`,args:[`-y`,`quirl-cli`],shell:`npx -y quirl-cli`,portable:!0}}const oS=[`QUIRL_SERVER`,`QUIRL_API_URL`,`QUIRL_PUBLISHABLE_KEY`,`QUIRL_APP_URL`];function sS(){return Object.fromEntries(oS.flatMap(e=>process.env[e]?[[e,process.env[e]]]:[]))}function cS(){return`${Object.entries(sS()).map(([e,t])=>`${e}="${t}" `).join(``)}${aS().shell}`}async function lS(e){try{return JSON.parse(await u(e,`utf8`))}catch(t){if(t.code===`ENOENT`)return{};throw Error(`${e} isn't valid JSON; fix it and run \`quirl init\` again.`)}}const uS=async(e,t)=>{await l(y(e),{recursive:!0}),await m(e,`${JSON.stringify(t,null,2)}\n`)};async function dS(e){let t=x(e,`.mcp.json`),n=await lS(t),r=aS();n.mcpServers={...n.mcpServers,quirl:{command:r.command,args:[...r.args,`mcp`],...Object.keys(sS()).length?{env:sS()}:{}}},await uS(t,n)}async function fS(e){let t=x(e,`.claude`,`settings.json`),n=await lS(t),r=n.hooks??{},i=`${cS()} context --hook`;r.SessionStart=[...(r.SessionStart??[]).map(e=>({...e,hooks:e.hooks.filter(e=>!/\bcontext --hook$/.test(e.command))})).filter(e=>e.hooks.length),{hooks:[{type:`command`,command:i,timeout:15}]}],n.hooks=r,await uS(t,n)}async function pS(e,t,n=[]){let r=x(e,`CLAUDE.md`),i=``;try{i=await u(r,`utf8`)}catch{}let a=`${nS}
217
217
  ## Quirl
@@ -371,11 +371,13 @@ default:yield*this.pop(),yield*this.step()}}*blockMap(e){let t=e.items[e.items.l
371
371
  /* istanbul ignore else should not happen */
372
372
  n?this.stack.push(n):(yield*this.pop(),yield*this.step())}else{let t=this.peek(2);if(t.type===`block-map`&&(this.type===`map-value-ind`&&t.indent===e.indent||this.type===`newline`&&!t.items[t.items.length-1].sep))yield*this.pop(),yield*this.step();else if(this.type===`map-value-ind`&&t.type!==`flow-collection`){let n=c(s(t));u(e);let r=e.end.splice(1,e.end.length);r.push(this.sourceToken);let i={type:`block-map`,offset:e.offset,indent:e.indent,items:[{start:n,key:e,sep:r}]};this.onKeyLine=!0,this.stack[this.stack.length-1]=i}else yield*this.lineEnd(e)}}flowScalar(e){if(this.onNewLine){let e=this.source.indexOf(`
373
373
  `)+1;for(;e!==0;)this.onNewLine(this.offset+e),e=this.source.indexOf(`
374
- `,e)+1}return{type:e,offset:this.offset,indent:this.indent,source:this.source}}startBlockValue(e){switch(this.type){case`alias`:case`scalar`:case`single-quoted-scalar`:case`double-quoted-scalar`:return this.flowScalar(this.type);case`block-scalar-header`:return{type:`block-scalar`,offset:this.offset,indent:this.indent,props:[this.sourceToken],source:``};case`flow-map-start`:case`flow-seq-start`:return{type:`flow-collection`,offset:this.offset,indent:this.indent,start:this.sourceToken,items:[],end:[]};case`seq-item-ind`:return{type:`block-seq`,offset:this.offset,indent:this.indent,items:[{start:[this.sourceToken]}]};case`explicit-key-ind`:{this.onKeyLine=!0;let t=c(s(e));return t.push(this.sourceToken),{type:`block-map`,offset:this.offset,indent:this.indent,items:[{start:t,explicitKey:!0}]}}case`map-value-ind`:{this.onKeyLine=!0;let t=c(s(e));return{type:`block-map`,offset:this.offset,indent:this.indent,items:[{start:t,key:null,sep:[this.sourceToken]}]}}}return null}atIndentedComment(e,t){return this.type!==`comment`||this.indent<=t?!1:e.every(e=>e.type===`newline`||e.type===`space`)}*documentEnd(e){this.type!==`doc-mode`&&(e.end?e.end.push(this.sourceToken):e.end=[this.sourceToken],this.type===`newline`&&(yield*this.pop()))}*lineEnd(e){switch(this.type){case`comma`:case`doc-start`:case`doc-end`:case`flow-seq-end`:case`flow-map-end`:case`map-value-ind`:yield*this.pop(),yield*this.step();break;case`newline`:this.onKeyLine=!1;default:e.end?e.end.push(this.sourceToken):e.end=[this.sourceToken],this.type===`newline`&&(yield*this.pop())}}}})),lw=/* @__PURE__ */ E((e=>{var t=tw(),n=RC(),r=zC(),i=lC(),a=$(),o=sw(),s=cw();function c(e){let t=e.prettyErrors!==!1;return{lineCounter:e.lineCounter||t&&new o.LineCounter||null,prettyErrors:t}}function l(e,n={}){let{lineCounter:i,prettyErrors:a}=c(n),o=new s.Parser(i?.addNewLine),l=new t.Composer(n),u=Array.from(l.compose(o.parse(e)));if(a&&i)for(let t of u)t.errors.forEach(r.prettifyError(e,i)),t.warnings.forEach(r.prettifyError(e,i));return u.length>0?u:Object.assign([],{empty:!0},l.streamInfo())}function u(e,n={}){let{lineCounter:i,prettyErrors:a}=c(n),o=new s.Parser(i?.addNewLine),l=new t.Composer(n),u=null;for(let t of l.compose(o.parse(e),!0,e.length))if(!u)u=t;else if(u.options.logLevel!==`silent`){u.errors.push(new r.YAMLParseError(t.range.slice(0,2),`MULTIPLE_DOCS`,`Source contains multiple documents; please use YAML.parseAllDocuments()`));break}return a&&i&&(u.errors.forEach(r.prettifyError(e,i)),u.warnings.forEach(r.prettifyError(e,i))),u}function d(e,t,n){let r;typeof t==`function`?r=t:n===void 0&&t&&typeof t==`object`&&(n=t);let a=u(e,n);if(!a)return null;if(a.warnings.forEach(e=>i.warn(a.options.logLevel,e)),a.errors.length>0){if(a.options.logLevel!==`silent`)throw a.errors[0];a.errors=[]}return a.toJS(Object.assign({reviver:r},n))}function f(e,t,r){let i=null;if(typeof t==`function`||Array.isArray(t)?i=t:r===void 0&&t&&(r=t),typeof r==`string`&&(r=r.length),typeof r==`number`){let e=Math.round(r);r=e<1?void 0:e>8?{indent:8}:{indent:e}}if(e===void 0){let{keepUndefined:e}=r??t??{};if(!e)return}return a.isDocument(e)&&!i?e.toString(r):new n.Document(e,i,r).toString(r)}e.parse=d,e.parseAllDocuments=l,e.parseDocument=u,e.stringify=f})),uw=(/* @__PURE__ */ E((e=>{var t=tw(),n=RC(),r=IC(),i=zC(),a=eC(),o=$(),s=fC(),c=tC(),l=mC(),u=gC();aw();var d=ow(),f=sw(),p=cw(),m=lw(),h=JS();e.Composer=t.Composer,e.Document=n.Document,e.Schema=r.Schema,e.YAMLError=i.YAMLError,e.YAMLParseError=i.YAMLParseError,e.YAMLWarning=i.YAMLWarning,e.Alias=a.Alias,e.isAlias=o.isAlias,e.isCollection=o.isCollection,e.isDocument=o.isDocument,e.isMap=o.isMap,e.isNode=o.isNode,e.isPair=o.isPair,e.isScalar=o.isScalar,e.isSeq=o.isSeq,e.Pair=s.Pair,e.Scalar=c.Scalar,e.YAMLMap=l.YAMLMap,e.YAMLSeq=u.YAMLSeq,e.Lexer=d.Lexer,e.LineCounter=f.LineCounter,e.Parser=p.Parser,e.parse=m.parse,e.parseAllDocuments=m.parseAllDocuments,e.parseDocument=m.parseDocument,e.stringify=m.stringify,e.visit=h.visit,e.visitAsync=h.visitAsync})))();function dw(e,t){let n=(0,uw.parse)(e,{uniqueKeys:!1});if(!Z(n))throw Error(`not a YAML mapping`);let r=new HS(`npm`,t),i=Z(n.importers)?n.importers:{".":n};for(let e of Object.values(i))if(Z(e))for(let t of[`dependencies`,`devDependencies`,`optionalDependencies`]){let n=e[t];if(Z(n))for(let[e,t]of Object.entries(n)){let n=Z(t)?t.version:t;if(typeof n!=`string`||fw(n))continue;let i=mw(n);i?r.add(i.name,i.version,!0):r.add(e,pw(n),!0)}}for(let e of[`packages`,`snapshots`]){let t=n[e];if(Z(t))for(let e of Object.keys(t)){let t=mw(e);t&&!fw(t.version)&&r.add(t.name,t.version,!1)}}return r.rows()}function fw(e){return/^(link|file|workspace):/.test(e)}function pw(e){return e.replace(/\(.*$/,``).replace(/_(?=[^/]*@).*$/,``)}function mw(e){let t=e.replace(/^\//,``).replace(/\(.*$/,``),n=t.indexOf(`@`,1);if(n>0)return{name:t.slice(0,n),version:pw(t.slice(n+1))};if(!e.startsWith(`/`))return null;let r=t.lastIndexOf(`/`);return r<=0?null:{name:t.slice(0,r),version:pw(t.slice(r+1))}}function hw(e,t){let n=GS(e);if(!Z(n))throw Error(`not a JSON object`);let r=new HS(`npm`,t);if(Z(n.packages)){let e=/* @__PURE__ */ new Set;for(let[t,r]of Object.entries(n.packages))if(!t.includes(`node_modules/`))for(let t of WS(r))e.add(t);for(let[t,i]of Object.entries(n.packages)){let n=t.lastIndexOf(`node_modules/`);if(n===-1||!Z(i)||i.link===!0)continue;let a=t.slice(n+13),o=typeof i.name==`string`?i.name:a;if(typeof i.version!=`string`)continue;let s=t===`node_modules/${a}`;r.add(o,i.version,s&&e.has(a))}return r.rows()}if(Z(n.dependencies)){let e=(t,n)=>{for(let[i,a]of Object.entries(t)){if(!Z(a))continue;let t=a.version;typeof t==`string`&&!fw(t)&&r.add(i,t,n===0&&a.dev!==!0),Z(a.dependencies)&&e(a.dependencies,n+1)}};e(n.dependencies,0)}return r.rows()}function gw(e,t,n){let r=new HS(`npm`,t),i=[],a=!1;for(let t of e.split(/\r?\n/)){if(t===``||t.startsWith(`#`))continue;if(!/^\s/.test(t)&&t.endsWith(`:`)){let e=t.slice(0,-1).split(`,`).map(e=>e.trim().replace(/^"|"$/g,``));a=e.some(e=>/@(workspace|link|file|portal):/.test(e)),i=[...new Set(e.map(_w).filter(e=>e!==null))];continue}let e=/^\s+version:?\s+"?([^"\s]+)"?/.exec(t)?.[1];if(e&&!a){for(let t of i)r.add(t,e,n.has(t));i=[]}}return r.rows()}function _w(e){if(e===`__metadata`)return null;let t=e.indexOf(`@`,1);return t>0?e.slice(0,t):null}async function vw(e,t){let n=Ax(t),r=/* @__PURE__ */ new Set,i=await yw(e,jx(n,`package.json`));for(let e of WS(i))r.add(e);if(!Z(i))return r;let a=i.workspaces,o=(Array.isArray(a)?a:Z(a)&&Array.isArray(a.packages)?a.packages:[]).filter(e=>typeof e==`string`).map(e=>bw(jx(n,e.replace(/^\.\//,``).replace(/\/$/,``))));if(o.length===0)return r;for(let t of e.files){if(!t.path.endsWith(`package.json`))continue;let n=Ax(t.path);if(o.some(e=>e.test(n)))for(let n of WS(await yw(e,t.path)))r.add(n)}return r}async function yw(e,t){let n=e.file(t);if(!n)return null;let r=await e.readText(n);if(r===null)return null;try{return GS(r)}catch{return e.warnings.push(`${t}: not valid JSON, skipped`),null}}function bw(e){let t=e.split(`/`).map(e=>e===`**`?`.*`:e.replace(/[.+^${}()|[\]\\]/g,`\\$&`).replace(/\*/g,`[^/]*`)).join(`/`);return RegExp(`^${t}$`)}function xw(e){return e.toLowerCase().replace(/[-_.]+/g,`-`)}function Sw(e,t,n){let r=new HS(`pip`,t),i=!1,a=null,o=null,s=!1,c=()=>{a&&o&&!s&&r.add(a,o,n.has(xw(a))),a=null,o=null,s=!1};for(let t of e.split(/\r?\n/)){if(/^\s*\[{1,2}([^\]]+)\]{1,2}\s*$/.exec(t)){t.trim()===`[[package]]`?(c(),i=!0):i=!1;continue}if(!i)continue;let e=/^\s*(name|version|source)\s*=\s*(.+)$/.exec(t);if(!e)continue;let n=e[2]?.trim()??``;if(e[1]===`source`)s=/\b(editable|virtual)\s*=/.test(n);else{let t=/^"([^"]*)"/.exec(n)?.[1];e[1]===`name`&&t&&(a=t),e[1]===`version`&&t&&(o=t)}}return c(),r.rows()}function Cw(e){let t=/* @__PURE__ */ new Set,n=``,r=null,i=``,a=e=>{let n=/^\s*([A-Za-z0-9][A-Za-z0-9._-]*)/.exec(e)?.[1];n&&t.add(xw(n))},o=()=>{for(let e of i.matchAll(/"([^"]*)"|'([^']*)'/g))a(e[1]??e[2]??``);r=null,i=``},s=e=>e.replace(/"[^"]*"|'[^']*'/g,``).includes(`]`);for(let a of e.split(/\r?\n/)){let e=a.replace(/\s+#.*$/,``);if(r!==null){i+=` ${e}`,s(e)&&o();continue}let c=/^\s*\[([^\]]+)\]\s*$/.exec(e);if(c){n=(c[1]??``).trim();continue}let l=/^\s*"?([A-Za-z0-9_.-]+)"?\s*=\s*(.*)$/.exec(e);if(!l)continue;let u=l[1]??``,d=l[2]??``;n===`tool.poetry.dependencies`||n===`tool.poetry.dev-dependencies`||/^tool\.poetry\.group\.[^.]+\.dependencies$/.test(n)?xw(u)!==`python`&&t.add(xw(u)):(n===`project`&&u===`dependencies`||n===`project.optional-dependencies`||n===`dependency-groups`)&&d.trimStart().startsWith(`[`)&&(r=u,i=d,s(d.trimStart().slice(1))&&o())}return t}function ww(e,t){let n=new HS(`pip`,t),r=0;for(let t of e.split(/\r?\n/)){let e=t.replace(/(^|\s)#.*$/,``).trim();if(e===``||e.startsWith(`-`))continue;let i=/^([A-Za-z0-9][A-Za-z0-9._-]*)\s*(?:\[[^\]]*\])?\s*===?\s*([^\s;,\\]+)/.exec(e);i?.[1]&&i[2]?n.add(i[1],i[2],!0):r++}return{rows:n.rows(),unpinned:r}}async function Tw(e){let t=[];for(let n of e.files)try{let r=await Ew(e,n);r&&t.push(...r)}catch(t){e.warnings.push(`${n.path}: could not be parsed (${Mx(t)})`)}return t}async function Ew(e,t){let n=kx(t.path),r=Ax(t.path),i=t=>t?e.readText(t,52428800):Promise.resolve(null),a=t=>e.file(jx(r,t));switch(n){case`pnpm-lock.yaml`:{let e=await i(t);return e===null?null:dw(e,t.path)}case`package-lock.json`:case`npm-shrinkwrap.json`:{let e=await i(t);return e===null?null:hw(e,t.path)}case`yarn.lock`:{let n=await i(t);return n===null?null:gw(n,t.path,await vw(e,t.path))}case`composer.lock`:{let e=await i(t);return e===null?null:KS(e,t.path,await i(a(`composer.json`)))}case`poetry.lock`:case`uv.lock`:{let e=await i(t);if(e===null)return null;let n=await i(a(`pyproject.toml`)),r=n?Cw(n):/* @__PURE__ */ new Set;return Sw(e,t.path,r)}case`go.sum`:case`go.mod`:return n===`go.mod`&&a(`go.sum`)?null:qS(await i(a(`go.mod`)),n===`go.sum`?await i(t):null,t.path)}if(/^requirements[\w.-]*\.txt$/i.test(n)||/(^|\/)requirements\/[^/]+\.txt$/.test(t.path)){let n=await i(t);if(n===null)return null;let{rows:r,unpinned:a}=ww(n,t.path);return a>0&&e.warnings.push(`${t.path}: ${a} requirement${a===1?``:`s`} without an exact == pin skipped`),r}return null}const Dw={name:`Supabase`,type:`database`,provider:`Supabase Postgres`},Ow={name:`Postgres`,type:`database`,provider:`Postgres`},kw={name:`MySQL`,type:`database`,provider:`MySQL`},Aw={name:`MongoDB`,type:`database`,provider:`MongoDB`},jw={name:`Redis`,type:`database`,provider:`Redis`},Mw={name:`Elasticsearch`,type:`database`,provider:`Elasticsearch`},Nw={name:`AWS S3`,type:`storage`,provider:`AWS S3`},Pw={name:`AWS SQS`,type:`queue`,provider:`AWS SQS`},Fw={name:`AWS`,type:`service`,provider:`AWS`},Iw={name:`MinIO`,type:`storage`,provider:`MinIO`},Lw={name:`Cloudinary`,type:`storage`,provider:`Cloudinary`},Rw={name:`RabbitMQ`,type:`queue`,provider:`RabbitMQ`},zw={name:`Kafka`,type:`queue`,provider:`Kafka`},Bw={name:`Stripe`,type:`external_api`,provider:`Stripe`},Vw={name:`Twilio`,type:`external_api`,provider:`Twilio`},Hw={name:`SendGrid`,type:`service`,provider:`SendGrid`},Uw={name:`Postmark`,type:`service`,provider:`Postmark`},Ww={name:`Resend`,type:`service`,provider:`Resend`},Gw={name:`Mailgun`,type:`service`,provider:`Mailgun`},Kw={name:`Email (SMTP)`,type:`service`,provider:`SMTP`},qw={name:`Firebase`,type:`service`,provider:`Firebase`},Jw={name:`OpenAI`,type:`ai`,provider:`OpenAI`},Yw={name:`Anthropic`,type:`ai`,provider:`Anthropic`},Xw={name:`Sentry`,type:`monitoring`,provider:`Sentry`},Zw={name:`Auth0`,type:`auth`,provider:`Auth0`},Qw={name:`Clerk`,type:`auth`,provider:`Clerk`},$w={name:`Auth.js`,type:`auth`,provider:`Auth.js`},eT={name:`Algolia`,type:`external_api`,provider:`Algolia`},tT={name:`Google Cloud`,type:`service`,provider:`Google Cloud`},nT={name:`Cloud Storage`,type:`storage`,provider:`Google Cloud Storage`},rT={name:`Pub/Sub`,type:`queue`,provider:`Google Cloud Pub/Sub`},iT={name:`BigQuery`,type:`database`,provider:`Google BigQuery`},aT={name:`Firestore`,type:`database`,provider:`Google Firestore`},oT={name:`Secret Manager`,type:`secrets`,provider:`Google Secret Manager`},sT={name:`Gemini`,type:`ai`,provider:`Google Gemini`},cT={name:`Vertex AI`,type:`ai`,provider:`Google Vertex AI`},lT={name:`SerpApi`,type:`external_api`,provider:`SerpApi`},uT={name:`Zyte`,type:`external_api`,provider:`Zyte`},dT={name:`Open Exchange Rates`,type:`external_api`,provider:`Open Exchange Rates`},fT={name:`reCAPTCHA`,type:`external_api`,provider:`Google reCAPTCHA`},pT={name:`DuckDB`,type:`database`,provider:`DuckDB`},mT=[[/^SUPABASE_/,Dw],[/^(DATABASE_URL|POSTGRES_|PG(HOST|USER|PASSWORD|DATABASE|PORT)$)/,Ow],[/^MYSQL_/,kw],[/^MONGO(DB)?_/,Aw],[/^(REDIS_|UPSTASH_REDIS_)/,jw],[/^(ELASTIC(SEARCH)?_)/,Mw],[/^(AWS_)?S3_|_S3_BUCKET$|^AWS_BUCKET/,Nw],[/^(AWS_)?SQS_/,Pw],[/^AWS_(ACCESS_KEY_ID|SECRET_ACCESS_KEY|REGION|DEFAULT_REGION)$/,Fw],[/^MINIO_/,Iw],[/^CLOUDINARY_/,Lw],[/^(RABBITMQ_|AMQP_URL)/,Rw],[/^KAFKA_/,zw],[/^STRIPE_/,Bw],[/^TWILIO_/,Vw],[/^SENDGRID_/,Hw],[/^POSTMARK_/,Uw],[/^RESEND_/,Ww],[/^MAILGUN_/,Gw],[/^SMTP_/,Kw],[/^FIREBASE_/,qw],[/^OPENAI_/,Jw],[/^ANTHROPIC_/,Yw],[/^SENTRY_/,Xw],[/^AUTH0_/,Zw],[/^CLERK_/,Qw],[/^(NEXTAUTH_|AUTH_SECRET$)/,$w],[/^ALGOLIA_/,eT],[/^(GCS_BUCKET|GOOGLE_CLOUD_STORAGE_|GCS_)/,nT],[/^(PUBSUB_|GOOGLE_PUBSUB_)/,rT],[/^BIGQUERY_/,iT],[/^FIRESTORE_/,aT],[/^(GEMINI_|GOOGLE_GENAI_)/,sT],[/^VERTEX(_AI)?_/,cT],[/^(SERPAPI_|SERP_API_)/,lT],[/^ZYTE_/,uT],[/^(OPEN_EXCHANGE_RATES_|OPENEXCHANGERATES_|OXR_)/,dT],[/^RECAPTCHA_/,fT],[/^(GOOGLE_CLOUD_PROJECT|GCP_PROJECT(_ID)?|GCLOUD_PROJECT|GOOGLE_APPLICATION_CREDENTIALS)$/,tT]],hT=[[[`@supabase/supabase-js`,`@supabase/ssr`,`supabase`,`github.com/supabase-community/*`,`supabase/supabase-php`],Dw],[[`pg`,`postgres`,`pg-promise`,`@neondatabase/serverless`,`@vercel/postgres`,`psycopg2`,`psycopg2-binary`,`psycopg`,`asyncpg`,`github.com/jackc/pgx*`,`github.com/lib/pq`],Ow],[[`mysql`,`mysql2`,`pymysql`,`mysqlclient`,`github.com/go-sql-driver/mysql`],kw],[[`mongodb`,`mongoose`,`pymongo`,`motor`,`go.mongodb.org/mongo-driver*`,`mongodb/mongodb`],Aw],[[`redis`,`ioredis`,`@upstash/redis`,`predis/predis`,`github.com/redis/go-redis*`,`github.com/go-redis/redis*`],jw],[[`@elastic/elasticsearch`,`elasticsearch`,`elasticsearch/elasticsearch`],Mw],[[`@aws-sdk/client-s3`,`github.com/aws/aws-sdk-go-v2/service/s3`,`league/flysystem-aws-s3-v3`],Nw],[[`@aws-sdk/client-sqs`,`github.com/aws/aws-sdk-go-v2/service/sqs`],Pw],[[`aws-sdk`,`boto3`,`aws/aws-sdk-php`,`github.com/aws/aws-sdk-go`],Fw],[[`minio`],Iw],[[`cloudinary`,`cloudinary/cloudinary_php`],Lw],[[`amqplib`,`pika`,`php-amqplib/php-amqplib`,`github.com/rabbitmq/amqp091-go`],Rw],[[`kafkajs`,`kafka-python`,`confluent-kafka`,`github.com/segmentio/kafka-go`],zw],[[`stripe`,`@stripe/stripe-js`,`@stripe/react-stripe-js`,`stripe/stripe-php`,`github.com/stripe/stripe-go*`],Bw],[[`twilio`,`twilio/sdk`,`github.com/twilio/twilio-go`],Vw],[[`@sendgrid/`,`sendgrid`,`sendgrid/sendgrid`],Hw],[[`postmark`,`wildbit/postmark-php`],Uw],[[`resend`,`resend/resend-php`],Ww],[[`mailgun.js`,`mailgun/mailgun-php`],Gw],[[`nodemailer`],Kw],[[`firebase`,`firebase-admin`,`firebase-functions`,`kreait/firebase-php`,`firebase.google.com/go*`],qw],[[`openai`,`openai-php/client`,`github.com/sashabaranov/go-openai`],Jw],[[`@anthropic-ai/sdk`,`anthropic`,`github.com/anthropics/anthropic-sdk-go`],Yw],[[`@sentry/`,`sentry-sdk`,`sentry/sentry`,`sentry/sentry-laravel`,`github.com/getsentry/sentry-go`],Xw],[[`@auth0/`,`auth0`,`auth0/auth0-php`],Zw],[[`@clerk/`],Qw],[[`next-auth`,`@auth/`],$w],[[`algoliasearch`,`algolia/algoliasearch-client-php`],eT],[[`@google-cloud/storage`,`google-cloud-storage`,`cloud.google.com/go/storage`],nT],[[`@google-cloud/pubsub`,`google-cloud-pubsub`,`cloud.google.com/go/pubsub*`],rT],[[`@google-cloud/bigquery`,`google-cloud-bigquery`,`cloud.google.com/go/bigquery`],iT],[[`@google-cloud/firestore`,`google-cloud-firestore`,`cloud.google.com/go/firestore`],aT],[[`@google-cloud/secret-manager`,`google-cloud-secret-manager`,`cloud.google.com/go/secretmanager`],oT],[[`@google/genai`,`@google/generative-ai`,`google-genai`,`google-generativeai`],sT],[[`@google-cloud/vertexai`,`google-cloud-aiplatform`,`vertexai`],cT],[[`serpapi`,`google-search-results`],lT],[[`zyte-api`,`scrapy-zyte-api`],uT],[[`open-exchange-rates`],dT],[[`react-google-recaptcha`,`react-google-recaptcha-v3`,`vue-recaptcha`,`vue-recaptcha-v3`,`@google-cloud/recaptcha-enterprise`,`google-cloud-recaptcha-enterprise`,`django-recaptcha`],fT],[[`@google-cloud/`,`google-cloud-*`,`google-auth-library`,`google-auth`,`cloud.google.com/go*`],tT],[[`duckdb`,`@duckdb/`],pT]],gT=[[/^supabase\//,Dw],[/(^|\/)(postgres|postgis|timescaledb)$/,Ow],[/(^|\/)(mysql|mariadb)$/,kw],[/(^|\/)mongo(db)?$/,Aw],[/(^|\/)(redis|redis-stack|valkey)$/,jw],[/(^|\/)(elasticsearch|opensearch)$/,Mw],[/(^|\/)minio$/,Iw],[/(^|\/)rabbitmq$/,Rw],[/(^|\/)(kafka|cp-kafka)$/,zw],[/(^|\/)localstack$/,Fw],[/(^|\/)(cloud-sdk|google-cloud-cli)$/,tT],[/(^|\/)(gcloud-pubsub-emulator|pubsub-emulator)$/,rT],[/(^|\/)fake-gcs-server$/,nT]];function _T(e){return/^\.env(\.[\w-]+)*\.(example|sample|template|dist)$/i.test(e)||/^(example|sample)\.env$/i.test(e)}function vT(e){let t=kx(e);return/^\.gitlab-ci\.ya?ml$/.test(t)||/^cloudbuild\.ya?ml$/.test(t)||t===`bitbucket-pipelines.yml`||/(^|\/)\.github\/workflows\/[^/]+\.ya?ml$/.test(e)}function yT(e){return[...new Set(e.match(/\b[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+\b/g)??[])]}function bT(e){return/^(docker-)?compose([.-][\w.-]+)?\.ya?ml$/i.test(e)}var xT=class{#e=/* @__PURE__ */ new Map;add(e,t){let n=this.#e.get(e.provider);n?n.evidence.includes(t)||n.evidence.push(t):this.#e.set(e.provider,{...e,evidence:[t]})}list(){return[...this.#e.values()].sort((e,t)=>e.name.localeCompare(t.name))}};async function ST(e,t){let n=new xT,r=(e,t)=>{let r=e.replace(/^(NEXT_PUBLIC_|VITE_|PUBLIC_|REACT_APP_|EXPO_PUBLIC_|NUXT_PUBLIC_|NUXT_)/,``),i=mT.find(([e])=>e.test(r));i&&n.add(i[1],t)};for(let t of e.files){let i=kx(t.path);if(_T(i)){let n=await e.readText(t);if(n===null)continue;for(let e of CT(n))r(e,`env: ${e} (${t.path})`)}else if(vT(t.path)){let n=await e.readText(t);if(n===null)continue;for(let e of yT(n))r(e,`pipeline: ${e} (${t.path})`)}else if(bT(i)){let i=await e.readText(t);if(i===null)continue;let a;try{a=(0,uw.parse)(i)}catch(n){e.warnings.push(`${t.path}: could not be parsed (${Mx(n)})`);continue}let o=Z(a)&&Z(a.services)?a.services:{};for(let[e,i]of Object.entries(o)){if(!Z(i))continue;let a=i.environment,o=Array.isArray(a)?a.map(e=>String(e).split(`=`,1)[0]??``):Z(a)?Object.keys(a):[];for(let n of o)r(n,`docker-compose: ${e} env ${n} in ${t.path}`);if(typeof i.image!=`string`)continue;let s=wT(i.image),c=gT.find(([e])=>e.test(s));c&&n.add(c[1],`docker-compose: service ${e} (${i.image}) in ${t.path}`)}}else t.path===`supabase/config.toml`||t.path.endsWith(`/supabase/config.toml`)?n.add(Dw,`file: ${t.path}`):i===`firebase.json`?n.add(qw,`file: ${t.path}`):/^cloudbuild\.ya?ml$/.test(i)&&n.add(tT,`file: ${t.path}`)}for(let e of t){if(!e.direct)continue;let t=hT.find(([t])=>t.some(t=>TT(t,e.package)));t&&n.add(t[1],`dependency: ${e.package} (${e.sourceLockfile})`)}return n.list()}function CT(e){let t=[];for(let n of e.split(/\r?\n/)){let e=/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/.exec(n);e?.[1]&&t.push(e[1])}return t}function wT(e){let t=e.toLowerCase().replace(/@.*$/,``),n=t.lastIndexOf(`/`),r=t.indexOf(`:`,n+1);r!==-1&&(t=t.slice(0,r));let i=t.split(`/`);return i.length>1&&/[.:]|^localhost$/.test(i[0]??``)&&i.shift(),i[0]===`library`&&i.shift(),i.join(`/`)}function TT(e,t){return e.endsWith(`*`)?t.startsWith(e.slice(0,-1)):e.endsWith(`/`)?t.startsWith(e):t===e}const ET={name:`Supabase Auth`,type:`auth`,provider:`Supabase Auth`},DT={name:`pg_cron`,type:`scheduler`,provider:`pg_cron`},OT={postgres:[Dw,Ow],mysql:[kw]};function kT(e,t){let n=new Map(t.map(e=>[e.provider,e])),r=(e,t)=>{let r=n.get(e.provider);if(r)return r.provider;let i={...e,evidence:[t]};return n.set(e.provider,i),i.provider};for(let t of e){let e=t.sourcePath.slice(0,t.sourcePath.lastIndexOf(`/`)+1),i=/(^|\/)supabase\//i.test(t.sourcePath);if(t.kind===`job`){t.resource===DT.provider&&r(DT,`cron.schedule in ${t.sourcePath}`);continue}if(t.kind!==`table`&&t.kind!==`function`&&t.kind!==`role`)continue;if(t.kind===`role`){let e=[...n.values()].find(e=>e.type===`auth`);if(e){t.resource=e.provider;continue}if(i){t.resource=r(ET,`roles: ${t.sourcePath}`);continue}}if(i){t.resource=r(Dw,`migrations: ${e}`);continue}let a=(t.dialect===`postgres`||t.dialect===`mysql`?OT[t.dialect]:[...OT.postgres,...OT.mysql]).find(e=>n.has(e.provider));a?t.resource=a.provider:t.dialect===`postgres`?t.resource=r(Ow,`migrations: ${e}`):t.dialect===`mysql`&&(t.resource=r(kw,`migrations: ${e}`))}return[...n.values()].sort((e,t)=>e.name.localeCompare(t.name))}const AT=(e,t,n=e)=>({name:e,type:t,provider:n}),jT=AT(`Environment variables`,`secrets`),MT=AT(`GitHub Actions secrets`,`secrets`),NT=AT(`GitHub Actions`,`scheduler`),PT=AT(`Cloud Run`,`hosting`,`Google Cloud Run`),FT=AT(`Cloud Scheduler`,`scheduler`,`Google Cloud Scheduler`),IT=AT(`Vercel`,`hosting`),LT=AT(`Vercel Cron`,`scheduler`),RT=AT(`Netlify`,`hosting`),zT=AT(`Netlify Scheduled Functions`,`scheduler`),BT=AT(`Fly.io`,`hosting`),VT=AT(`AWS Lambda`,`hosting`),HT=AT(`EventBridge schedules`,`scheduler`,`Amazon EventBridge`),UT=AT(`Kubernetes CronJobs`,`scheduler`,`Kubernetes CronJob`),WT=AT(`Kubernetes`,`hosting`);function GT(e){let t={"@hourly":`every hour`,"@daily":`every day at 00:00`,"@midnight":`every day at 00:00`,"@weekly":`every Sunday at 00:00`,"@monthly":`on the 1st of every month at 00:00`,"@yearly":`every year on 1 January at 00:00`,"@annually":`every year on 1 January at 00:00`},n=e.trim();if(t[n])return t[n];let r=n.split(/\s+/);if(r.length!==5)return;let[i=``,a=``,o=``,s=``,c=``]=r,l=e=>/^\*\/(\d+)$/.exec(e)?.[1],u=e=>/^\d+$/.test(e),d=(...e)=>e.every(e=>e===`*`),f=(e,t)=>`${e.padStart(2,`0`)}:${t.padStart(2,`0`)}`;if(i===`*`&&d(a,o,s,c))return`every minute`;if(l(i)&&d(a,o,s,c))return`every ${l(i)} minutes`;if(u(i)&&d(a,o,s,c))return i===`0`?`every hour`:`every hour at :${i.padStart(2,`0`)}`;if(u(i)&&l(a)&&d(o,s,c))return`every ${l(a)} hours`;if(!u(i)||!u(a))return;let p=f(a,i);if(d(o,s,c))return`every day at ${p}`;let m=[`Sunday`,`Monday`,`Tuesday`,`Wednesday`,`Thursday`,`Friday`,`Saturday`,`Sunday`];if(d(o,s)){if(c===`1-5`)return`every weekday at ${p}`;let e=c.split(`,`).map(e=>m[Number(e)]);return e.every(Boolean)?`every ${e.join(` and `)} at ${p}`:void 0}if(u(o)&&d(s,c))return`on day ${o} of every month at ${p}`}function KT(e){let t=/* @__PURE__ */ new Map;for(let n of e.matchAll(/--([\w-]+)(?:[= ]+("[^"]*"|'[^']*'|(?!--)[^\s]+))?/g))t.set(n[1]??``,(n[2]??``).replace(/^["']|["']$/g,``));return t}function qT(e){return(e??``).split(/[,\n]/).map(e=>e.trim()).filter(e=>e.includes(`=`)).map(e=>{let[t=``,n=``]=e.split(`=`,2);return[t.trim(),n.trim()]})}const JT=e=>e.replace(/:[^:/]*$/,``).replace(/^.*\/secrets\//,``),YT=e=>/^projects\/([^/]+)\/secrets\//.exec(e)?.[1],XT=e=>e&&!/[$%{}]/.test(e)?e:void 0,ZT=e=>/(SECRET|TOKEN|PASSWORD|PASSWD|PRIVATE|API_KEY|_KEY$|CREDENTIAL|DSN|AUTH)/i.test(e),QT=/["'`]((?:claude-(?:opus|sonnet|haiku|fable|instant|\d)[\w.-]*)|(?:gpt-(?:\d|4o)[\w.-]*)|(?:o[134](?:-mini|-pro|-preview)?(?:-\d{4}-\d{2}-\d{2})?)|(?:text-embedding-[\w-]+)|(?:gemini-(?:\d|embedding)[\w.-]*)|whisper-1|dall-e-[23]|gpt-image-1)["'`]/g,$T=/\.(?:[cm]?[jt]sx?|py|go|rb|java|kt|cs|php|rs|swift|ya?ml|toml|json)$/i,eE=/(^|\/)(?:package(?:-lock)?\.json|pnpm-lock\.yaml|yarn\.lock|composer\.lock|[^/]*\.lock|tsconfig[^/]*\.json)$|(^|\/)(?:__tests__|tests?|fixtures?|test-fixtures|docs?|examples?|demo|seeds?|mocks?)\//i;var tE=class{resources=/* @__PURE__ */ new Map;contracts=[];#e=/* @__PURE__ */ new Map;resource(e,t){let n=this.resources.get(e.provider);return n?n.evidence.includes(t)||n.evidence.push(t):this.resources.set(e.provider,{...e,evidence:[t]}),e.provider}add(e,t){this.contracts.some(e=>e.kind===t.kind&&e.name===t.name)||this.contracts.push({...t,resource:this.resource(e,`${t.kind}: ${t.name} (${t.sourcePath})`)})}variable(e,t,n,r,i){if(!/^[A-Za-z_][\w-]*$/.test(n))return;let a=this.#e.get(n),o=[.../* @__PURE__ */ new Set([...a?.contract.setIn??[],e.name])];if(a&&a.priority<=t){a.contract.setIn=o;return}let s={kind:`variable`,name:n,sourcePath:r,secret:ZT(n),...i,setIn:o,resource:this.resource(e,`variable: ${n} (${r})`)};a&&this.contracts.splice(this.contracts.indexOf(a.contract),1),this.contracts.push(s),this.#e.set(n,{contract:s,priority:t})}};function nE(e,t,n,r,i,a,o){if(!n||/^[$%{]/.test(n))return;let s=XT(o),c=s?{project:s}:{},l=[{relation:`runs`,to:`repo:.`}];for(let[n]of i)e.variable(PT,2,n,t,{secret:ZT(n),...c}),l.push({relation:`uses`,to:`variable:${n}`});for(let[n,r]of a){let i=JT(r),a=XT(YT(r))??s;e.variable(oT,1,i,t,{secret:!0,...n===i?{}:{envName:n},...a?{project:a}:{}}),l.push({relation:`uses`,to:`variable:${i}`})}e.add(PT,{kind:`deployment`,name:n,sourcePath:t,...r?{region:r}:{},...c,trigger:`HTTP`,links:l})}function rE(e,t,n){let r=n.replace(/\\\r?\n\s*/g,` `);for(let n of r.matchAll(/gcloud\s+(?:beta\s+)?run\s+deploy\s+([^\s'"`]+)([^\n]*)/g)){let r=KT(n[2]??``);nE(e,t,n[1]??``,r.get(`region`),qT(r.get(`set-env-vars`)??r.get(`update-env-vars`)),qT(r.get(`set-secrets`)??r.get(`update-secrets`)),r.get(`project`))}for(let n of r.matchAll(/gcloud\s+(?:beta\s+)?scheduler\s+jobs\s+(?:create|update)\s+(http|pubsub|app-engine)\s+([^\s'"`]+)([^\n]*)/g)){let r=n[2]??``,i=KT(n[3]??``),a=i.get(`schedule`);if(!a||/^[$%{]/.test(r))continue;let o=[],s=i.get(`uri`),c;try{c=s?new URL(s).pathname:void 0}catch{}c&&o.push({relation:`calls`,to:`endpoint:${(i.get(`http-method`)??`POST`).toUpperCase()} ${c}`});let l=XT(i.get(`project`));e.add(FT,{kind:`job`,name:r,sourcePath:t,schedule:a,...GT(a)?{scheduleText:GT(a)}:{},...i.get(`time-zone`)?{timeZone:i.get(`time-zone`)}:{},...l?{project:l}:{},runs:n[1]===`pubsub`?`Publishes to Pub/Sub topic ${i.get(`topic`)??``}`.trim():s?`Calls ${s.replace(/^https?:\/\/[^/]+/,``)}`:void 0,links:o})}}const iE=(e,t)=>new RegExp(String.raw`\b${t}\s*=\s*"([^"]*)"`).exec(e)?.[1];function aE(e,t,n){let r=/provider\s+"google(?:-beta)?"\s*\{([\s\S]*?)\n\}/.exec(n)?.[1],i=XT(r?iE(r,`project`):void 0);for(let r of n.matchAll(/resource\s+"(google_cloud_scheduler_job|google_cloud_run_service|google_cloud_run_v2_service|google_secret_manager_secret)"\s+"[\w-]+"\s*\{([\s\S]*?)\n\}/g)){let n=r[2]??``,a=XT(iE(n,`project`))??i,o=a?{project:a}:{};if(r[1]===`google_cloud_scheduler_job`){let r=iE(n,`name`),i=iE(n,`schedule`);if(!r||!i)continue;e.add(FT,{kind:`job`,name:r,sourcePath:t,schedule:i,...GT(i)?{scheduleText:GT(i)}:{},...iE(n,`time_zone`)?{timeZone:iE(n,`time_zone`)}:{},...o})}else if(r[1]===`google_secret_manager_secret`){let r=iE(n,`secret_id`);r&&e.variable(oT,1,r,t,{secret:!0,...o})}else{let r=iE(n,`name`);r&&e.add(PT,{kind:`deployment`,name:r,sourcePath:t,...iE(n,`location`)?{region:iE(n,`location`)}:{},...o,trigger:`HTTP`,links:[{relation:`runs`,to:`repo:.`}]})}}}function oE(e,t,n){if(!Z(n))return;let r=typeof n.name==`string`?n.name:kx(t).replace(/\.ya?ml$/,``),i=Z(n.on)?n.on:Z(n.true)?n.true:null,a=Array.isArray(i?.schedule)?i.schedule.flatMap(e=>Z(e)&&typeof e.cron==`string`?[e.cron]:[]):[];for(let n of a)e.add(NT,{kind:`job`,name:a.length>1?`${r} (${n})`:r,sourcePath:t,schedule:n,...GT(n)?{scheduleText:GT(n)}:{},timeZone:`UTC`,runs:`GitHub Actions workflow ${t}`});let o=Z(n.jobs)?Object.values(n.jobs):[];for(let n of o){let r=Z(n)&&Array.isArray(n.steps)?n.steps:[];for(let n of r){if(!Z(n)||typeof n.uses!=`string`||!n.uses.startsWith(`google-github-actions/deploy-cloudrun`)||!Z(n.with))continue;let r=n.with,i=e=>typeof e==`string`?e:void 0;nE(e,t,i(r.service)??``,i(r.region),qT(i(r.env_vars)),qT(i(r.secrets)),i(r.project_id))}}}function sE(e,t,n){for(let r of n){if(!Z(r)||!Z(r.metadata))continue;let n=r.metadata.name;if(typeof n!=`string`)continue;let i=Z(r.spec)?r.spec:{};if(r.kind===`CronJob`&&typeof i.schedule==`string`&&String(r.apiVersion??``).startsWith(`batch/`))e.add(UT,{kind:`job`,name:n,sourcePath:t,schedule:i.schedule,...GT(i.schedule)?{scheduleText:GT(i.schedule)}:{},...typeof i.timeZone==`string`?{timeZone:i.timeZone}:{}});else if(r.kind===`Service`&&String(r.apiVersion??``).startsWith(`serving.knative.dev`)){let a=Z(i.template)&&Z(i.template.spec)&&Array.isArray(i.template.spec.containers)?i.template.spec.containers:[],o=[],s=[];for(let e of a)if(Z(e)&&Array.isArray(e.env))for(let t of e.env){if(!Z(t)||typeof t.name!=`string`)continue;let e=Z(t.valueFrom)&&Z(t.valueFrom.secretKeyRef)?t.valueFrom.secretKeyRef.name:void 0;typeof e==`string`?s.push([t.name,e]):o.push([t.name,``])}let c=(Z(r.metadata.labels)?r.metadata.labels:{})[`cloud.googleapis.com/location`];nE(e,t,n,typeof c==`string`?c:void 0,o,s)}else r.kind===`Deployment`&&String(r.apiVersion??``).startsWith(`apps/`)&&e.add(WT,{kind:`deployment`,name:n,sourcePath:t,links:[{relation:`runs`,to:`repo:.`}]})}}const cE=(e,t)=>new RegExp(String.raw`^\s*${t}\s*=\s*["']([^"']+)["']`,`m`).exec(e)?.[1];async function lE(e,t,n){let r=new tE,i=e=>{let t=e.lastIndexOf(`/`);return t>0?kx(e.slice(0,t)):n};for(let t of e.files){let a=kx(t.path),o=t.path,s=()=>e.readText(t);if(_T(a)){let e=await s();if(e===null)continue;let t=/^\.env\.([\w-]+)\./i.exec(a)?.[1];for(let n of CT(e))r.variable(jT,4,n,o,t?{environments:[t]}:{})}else if(/(^|\/)\.github\/workflows\/[^/]+\.ya?ml$/.test(o)){let e=await s();if(e===null)continue;for(let t of e.matchAll(/\$\{\{\s*secrets\.([A-Za-z_][A-Za-z0-9_]*)\s*\}\}/g))t[1]&&t[1]!==`GITHUB_TOKEN`&&r.variable(MT,3,t[1],o,{secret:!0});let t=(0,uw.parseAllDocuments)(e).map(e=>e.toJS());for(let e of t)oE(r,o,e);rE(r,o,e)}else if(/^cloudbuild\.ya?ml$/.test(a)){let e=await s();if(e===null)continue;for(let t of(0,uw.parseAllDocuments)(e).map(e=>e.toJS()))rE(r,o,(Z(t)&&Array.isArray(t.steps)?t.steps:[]).flatMap(e=>Z(e)&&Array.isArray(e.args)?[`${e.entrypoint===`gcloud`||/cloud-sdk/.test(String(e.name))?`gcloud `:``}${e.args.join(` `)}`]:[]).join(`
375
- `));rE(r,o,e)}else if(vT(o)||/\.(sh|bash)$/.test(a)||/^(Makefile|justfile|Taskfile\.ya?ml)$/i.test(a)||a===`package.json`&&!o.includes(`/node_modules/`)){let e=await s();e!==null&&rE(r,o,e)}else if(a.endsWith(`.tf`)){let e=await s();e!==null&&aE(r,o,e)}else if(a===`vercel.json`){let e=await s();if(e===null)continue;r.add(IT,{kind:`deployment`,name:i(o),sourcePath:o,links:[{relation:`runs`,to:`repo:.`}]});try{let t=JSON.parse(e);for(let e of Array.isArray(t.crons)?t.crons:[])Z(e)&&typeof e.path==`string`&&typeof e.schedule==`string`&&r.add(LT,{kind:`job`,name:e.path,sourcePath:o,schedule:e.schedule,...GT(e.schedule)?{scheduleText:GT(e.schedule)}:{},timeZone:`UTC`,links:[{relation:`calls`,to:`endpoint:GET ${e.path.split(`?`)[0]}`}]})}catch{}}else if(a===`netlify.toml`){let e=await s();if(e===null)continue;r.add(RT,{kind:`deployment`,name:i(o),sourcePath:o,...cE(e,`publish`)?{path:cE(e,`publish`)}:{},links:[{relation:`runs`,to:`repo:.`}]});for(let t of e.matchAll(/\[functions\.["']?([\w-]+)["']?\]([^[]*)/g)){let e=cE(t[2]??``,`schedule`);e&&r.add(zT,{kind:`job`,name:t[1]??``,sourcePath:o,schedule:e,...GT(e)?{scheduleText:GT(e)}:{},timeZone:`UTC`,runs:`Netlify function ${t[1]}`})}}else if(a===`fly.toml`){let e=await s();if(e===null)continue;let t=cE(e,`app`);t&&r.add(BT,{kind:`deployment`,name:t,sourcePath:o,...cE(e,`primary_region`)?{region:cE(e,`primary_region`)}:{},links:[{relation:`runs`,to:`repo:.`}]})}else if(/^serverless\.ya?ml$/.test(a)){let e=await s();if(e===null)continue;let t=(0,uw.parseAllDocuments)(e)[0]?.toJS();if(!Z(t)||!Z(t.functions))continue;let i=typeof t.service==`string`?t.service:n,a=Z(t.provider)&&typeof t.provider.region==`string`?t.provider.region:void 0;for(let[e,n]of Object.entries(t.functions)){let t=`${i}-${e}`;r.add(VT,{kind:`deployment`,name:t,sourcePath:o,...a?{region:a}:{},links:[{relation:`runs`,to:`repo:.`}]});let s=Z(n)&&Array.isArray(n.events)?n.events:[];for(let e of s){let n=Z(e)?e.schedule:void 0,i=typeof n==`string`?n:Z(n)&&typeof n.rate==`string`?n.rate:void 0;i&&r.add(HT,{kind:`job`,name:`${t} schedule`,sourcePath:o,schedule:i,runs:`AWS Lambda ${t}`})}}}else if(/\.ya?ml$/.test(a)){let e=await s();if(e===null||!/\bkind:\s*(CronJob|Service|Deployment)\b/.test(e))continue;try{sE(r,o,(0,uw.parseAllDocuments)(e).map(e=>e.toJS()))}catch{}}}let a=new Set(t.map(e=>e.provider)),o=a.has(cT.provider)&&!a.has(sT.provider)?cT:sT,s=/* @__PURE__ */ new Map;for(let t of e.files){if(!$T.test(t.path)||eE.test(t.path)||t.size>3e5)continue;let n=await e.readText(t);if(n!==null)for(let e of n.matchAll(QT)){let n=(e[1]??``).replace(/[.-]+$/,``),r=n.startsWith(`claude-`)?Yw:n.startsWith(`gemini-`)?o:Jw,i=s.get(n)??{kind:r,paths:[]};i.paths.includes(t.path)||i.paths.push(t.path),s.set(n,i)}}for(let[e,{kind:t,paths:n}]of s)r.add(t,{kind:`model`,name:e,sourcePath:n[0]??``,modelId:e,calledFrom:n.slice(0,5)});let c=[...r.resources.values()].map(e=>{let t=r.contracts.filter(t=>t.resource===e.provider);return t.length>0&&t.every(e=>typeof e.project==`string`)?{...e,perProject:!0}:e});return{contracts:r.contracts,resources:c}}const uE={ts:`TypeScript`,tsx:`TypeScript`,mts:`TypeScript`,cts:`TypeScript`,js:`JavaScript`,jsx:`JavaScript`,mjs:`JavaScript`,cjs:`JavaScript`,py:`Python`,go:`Go`,rb:`Ruby`,php:`PHP`,java:`Java`,kt:`Kotlin`,kts:`Kotlin`,swift:`Swift`,rs:`Rust`,cs:`C#`,fs:`F#`,c:`C`,h:`C`,cc:`C++`,cpp:`C++`,cxx:`C++`,hpp:`C++`,m:`Objective-C`,mm:`Objective-C++`,scala:`Scala`,dart:`Dart`,ex:`Elixir`,exs:`Elixir`,erl:`Erlang`,clj:`Clojure`,hs:`Haskell`,ml:`OCaml`,lua:`Lua`,r:`R`,pl:`Perl`,groovy:`Groovy`,zig:`Zig`,sol:`Solidity`,sql:`SQL`,sh:`Shell`,bash:`Shell`,zsh:`Shell`,ps1:`PowerShell`,tf:`HCL`,vue:`Vue`,svelte:`Svelte`,astro:`Astro`,html:`HTML`,css:`CSS`,scss:`SCSS`,sass:`SCSS`,less:`Less`};function dE(e){let t=/* @__PURE__ */ new Map;for(let n of e){let e=n.path.lastIndexOf(`.`);if(e===-1||e<n.path.lastIndexOf(`/`))continue;let r=uE[n.path.slice(e+1).toLowerCase()];r&&t.set(r,(t.get(r)??0)+1)}return[...t.entries()].sort((e,t)=>t[1]-e[1]||e[0].localeCompare(t[0])).slice(0,5).map(([e])=>e)}const fE=/* @__PURE__ */ new Set([`auth`,`storage`,`realtime`,`_realtime`,`extensions`,`graphql`,`graphql_public`,`supabase_functions`,`supabase_migrations`,`pgsodium`,`pgsodium_masks`,`vault`,`net`,`cron`,`pgbouncer`,`pg_catalog`,`information_schema`]),pE=/^(not|null|default|primary|unique|references|check|constraint|generated|collate|deferrable|initially|identity)$/i;function mE(e){if(!/\.sql$/i.test(e))return!1;let t=e.toLowerCase();return/(^|\/)migrations\//.test(t)||/(^|\/)db\/migrate\//.test(t)}const hE=e=>e.slice(0,e.lastIndexOf(`/`)+1),gE=[[`postgres`,/\b(?:bigserial|serial|jsonb|timestamptz|bytea|tsvector|plpgsql|gen_random_uuid|uuid_generate_v4|create\s+extension|create\s+policy|enable\s+row\s+level\s+security)\b|\$\$|::[a-z_]+/gi],[`mysql`,/\bauto_increment\b|\bengine\s*=|\bunsigned\b|`[^`\n]+`/gi],[`sqlite`,/\bautoincrement\b|\bwithout\s+rowid\b|\bpragma\b/gi]];function _E(e){let t=null,n=0;for(let[r,i]of gE){let a=e.match(i)?.length??0;a>n&&(t=r,n=a)}return t}function vE(e,t){let n=e.toLowerCase();if(!n.endsWith(`.sql`)||mE(e))return!1;let r=n.slice(n.lastIndexOf(`/`)+1);return/seed|fixture|sample|test|demo/.test(r)?!1:/schema|structure/.test(r)||t.has(hE(n))||/(^|\/)docker-entrypoint-initdb\.d\//.test(n)}async function yE(e){let t=/* @__PURE__ */ new Map,n=bE(),r=e.files.filter(e=>mE(e.path)),i=new Set(r.flatMap(e=>{let t=/^(.*\/)?(migrations|db\/migrate)\//.exec(e.path.toLowerCase());return t?[t[1]??``]:[]})),a=e.files.filter(e=>vE(e.path,i)).sort((e,t)=>e.path<t.path?-1:1);r.sort((e,t)=>{let n=e.path.slice(e.path.lastIndexOf(`/`)+1),r=t.path.slice(t.path.lastIndexOf(`/`)+1);return n<r?-1:n>r?1:e.path<t.path?-1:1});let o=/* @__PURE__ */ new Map,s=/* @__PURE__ */ new Map;for(let i of[...a,...r]){let r=await e.readText(i);if(r===null)continue;let a=_E(r);a&&(o.set(i.path,a),s.set(a,(s.get(a)??0)+1));for(let a of DE(r))try{FE(a,i.path,t,e.warnings),TE(a,i.path,n)}catch(t){e.warnings.push(`${i.path}: could not read statement "${GE(a)}" (${Mx(t)})`)}}let c=[...s.entries()].sort((e,t)=>t[1]-e[1])[0]?.[0]??null,l=e=>o.get(e)??c;return{tables:[...t.values()].filter(e=>!fE.has(e.schema)).map(e=>{let t=e.schema===`public`?e.table:`${e.schema}.${e.table}`;return{kind:`table`,name:t,sourcePath:e.sourcePath,table:t,columns:e.columns,dialect:l(e.sourcePath)}}),objects:EE(n,l)}}const bE=()=>({functions:/* @__PURE__ */ new Map,roleEnums:/* @__PURE__ */ new Map,cronJobs:/* @__PURE__ */ new Map});function xE(e){let{schema:t,table:n}=NE(e);return{schema:t,name:t===`public`?n:`${t}.${n}`}}function SE(e,t){let n=0;for(let r=t;r<e.length;r++){let i=e[r];if(i===`(`)n++;else if(i===`)`&&(n--,n===0))return[e.slice(t+1,r),e.slice(r+1)]}return null}const CE=e=>e.replace(/\s+/g,` `).trim(),wE=()=>String.raw`((?:${jE}\s*(?:\([^)]*\))?\s*,?\s*)+)`;function TE(e,t,n){let r=/^create\s+(?:or\s+replace\s+)?function\s+/i.exec(e);if(r){let i=e.indexOf(`(`,r[0].length),a=i>0?SE(e,i):null;if(!a)return;let{schema:o,name:s}=xE(e.slice(r[0].length,i));if(fE.has(o))return;let c=/^\s*returns\s+(setof\s+\S+|table\s*\([\s\S]*?\)(?=\s)|[\w."[\] ]+?)\s+(?:language|as|security|set|stable|immutable|volatile|strict|parallel|cost|leakproof|called|begin)\b/i.exec(a[1])?.[1];if(!c||/^(event_)?trigger$/i.test(c.trim())){n.functions.delete(s);return}let l=n.functions.get(s);n.functions.set(s,{name:s,sourcePath:t,arguments:`(${CE(a[0]).slice(0,300)})`,returns:CE(c),definer:/\bsecurity\s+definer\b/i.test(a[1].split(/\$\w*\$/)[0]??``),callers:l?.callers??/* @__PURE__ */ new Set});return}let i=new RegExp(String.raw`^drop\s+function\s+(?:if\s+exists\s+)?${wE()}`,`i`).exec(e);if(i?.[1]){for(let e of i[1].split(/,(?![^(]*\))/))n.functions.delete(xE(e.replace(/\(.*$/s,``)).name);return}let a=new RegExp(String.raw`^(grant|revoke)\s+execute\s+on\s+function\s+${wE()}\s+(?:to|from)\s+(.+)$`,`is`).exec(e);if(a?.[1]&&a[2]&&a[a.length-1]){let e=(a[a.length-1]??``).split(`,`).map(e=>e.trim().toLowerCase()).filter(e=>e&&e!==`public`);for(let t of a[2].split(/,(?![^(]*\))/)){let r=n.functions.get(xE(t.replace(/\(.*$/s,``)).name);if(r)for(let t of e)a[1].toLowerCase()===`grant`?r.callers.add(t):r.callers.delete(t)}return}let o=new RegExp(String.raw`^create\s+type\s+${jE}\s+as\s+enum\s*\(([^)]*)\)`,`i`).exec(e);if(o?.[1]&&/role/i.test(o[1])){n.roleEnums.set(NE(o[1]).table,{values:[...(o[2]??``).matchAll(/'((?:[^']|'')*)'/g)].map(e=>(e[1]??``).replace(/''/g,`'`)),sourcePath:t});return}let s=new RegExp(String.raw`^alter\s+type\s+${jE}\s+add\s+value\s+(?:if\s+not\s+exists\s+)?'((?:[^']|'')*)'`,`i`).exec(e);if(s?.[1]){let e=n.roleEnums.get(NE(s[1]).table),t=(s[2]??``).replace(/''/g,`'`);e&&!e.values.includes(t)&&e.values.push(t)}else{for(let r of e.matchAll(/cron\.schedule\s*\(\s*'([^']*)'\s*,\s*(?:'([^']*)'\s*,\s*)?(\$\w*\$[\s\S]*?\$\w*\$|'(?:[^']|'')*')/gi)){let[e,i]=r[2]===void 0?[null,r[1]]:[r[1],r[2]];if(!i)continue;let a=/select\s+([\w."]+)\s*\(/i.exec(r[3]??``)?.[1]??null;n.cronJobs.set(e??`pg_cron ${i}`,{schedule:i,sourcePath:t,calls:a?xE(a).name:null})}for(let t of e.matchAll(/cron\.unschedule\s*\(\s*'([^']*)'/gi))n.cronJobs.delete(t[1]??``)}}function EE(e,t){let n=[];for(let r of e.functions.values()){let e=[...r.callers].sort();n.push({kind:`function`,name:r.name,sourcePath:r.sourcePath,dialect:t(r.sourcePath),arguments:r.arguments,returns:r.returns,access:(e.length?`Callable by ${e.join(`, `)}`:`Not granted to any app role`)+(r.definer?`; runs with its owner's rights`:``)})}let r=/* @__PURE__ */ new Map;for(let t of e.roleEnums.values())for(let e of t.values)r.set(e,(r.get(e)??0)+1);for(let[i,a]of e.roleEnums)for(let e of a.values)n.push({kind:`role`,name:(r.get(e)??0)>1?`${e} (${i})`:e,sourcePath:a.sourcePath,dialect:t(a.sourcePath),definedIn:i});for(let[t,r]of e.cronJobs)n.push({kind:`job`,name:t,sourcePath:r.sourcePath,resource:`pg_cron`,schedule:r.schedule,...r.calls?{links:[{relation:`calls`,to:`function:${r.calls}`}]}:{}});return n}function DE(e){let t=[],n=``,r=0;for(;r<e.length;){let i=e[r],a=e[r+1];if(i===`-`&&a===`-`){let t=e.indexOf(`
376
- `,r);r=t===-1?e.length:t,n+=` `}else if(i===`/`&&a===`*`){let t=1;for(r+=2;r<e.length&&t>0;)e.startsWith(`/*`,r)?(t++,r+=2):e.startsWith(`*/`,r)?(t--,r+=2):r++;n+=` `}else if(i===`'`||i===`"`){let t=r+1;for(;t<e.length;)if(e[t]===i){if(e[t+1]===i)t+=2;else break}else t++;n+=e.slice(r,t+1),r=t+1}else{if(i===`$`){let t=/^\$[A-Za-z_]?[A-Za-z0-9_]*\$/.exec(e.slice(r,r+64))?.[0];if(t){let i=e.indexOf(t,r+t.length),a=i===-1?e.length:i+t.length;n+=e.slice(r,a),r=a;continue}}i===`;`?(n.trim()&&t.push(n.trim()),n=``,r++):(n+=i,r++)}}return n.trim()&&t.push(n.trim()),t.map(e=>e.replace(/\s+/g,` `))}function OE(e){let t=[],n=0,r=null,i=0;for(let a=0;a<e.length;a++){let o=e[a];r?o===r&&(r=null):o===`'`||o===`"`?r=o:o===`(`?n++:o===`)`?n--:o===`,`&&n===0&&(t.push(e.slice(i,a).trim()),i=a+1)}return t.push(e.slice(i).trim()),t.filter(Boolean)}function kE(e){let t=[],n=0;for(;n<e.length;){let r=e[n];if(/\s/.test(r)){n++;continue}if(r===`(`){let r=0,i=n,a=null;for(;i<e.length;i++){let t=e[i];if(a)t===a&&(a=null);else if(t===`'`||t===`"`)a=t;else if(t===`(`)r++;else if(t===`)`&&--r===0)break}t.push(e.slice(n,i+1)),n=i+1;continue}let i=n,a=null;for(;i<e.length;i++){let t=e[i];if(a)t===a&&(a=null);else if(t===`'`||t===`"`)a=t;else if(/\s/.test(t)||t===`(`)break}t.push(e.slice(n,i)),n=i}return t}const AE=String.raw`(?:"(?:[^"]|"")+"|[A-Za-z_][\w$]*)`,jE=String.raw`(${AE}(?:\s*\.\s*${AE})?)`;function ME(e){let t=e.trim();return t.startsWith(`"`)?t.slice(1,-1).replace(/""/g,`"`):t.toLowerCase()}function NE(e){let t=e.match(new RegExp(AE,`g`))??[e];return t.length>=2?{schema:ME(t[0]??``),table:ME(t[1]??``)}:{schema:`public`,table:ME(t[0]??e)}}function PE(e,t){return`${e}.${t}`}function FE(e,t,n,r){if(/^create\s+(?:(?:global|local)\s+)?(?:temp(?:orary)?\s+|unlogged\s+)?table\b/i.test(e)){IE(e,t,n,r);return}let i=new RegExp(String.raw`^alter\s+table\s+(?:if\s+exists\s+)?(?:only\s+)?${jE}\s+(.+)$`,`i`).exec(e);if(i?.[1]&&i[2]){UE(NE(i[1]),i[2],t,n,r);return}let a=/^drop\s+table\s+(?:if\s+exists\s+)?(.+?)(?:\s+(?:cascade|restrict))?$/i.exec(e);if(a?.[1])for(let e of OE(a[1])){let{schema:t,table:r}=NE(e);n.delete(PE(t,r))}}function IE(e,t,n,r){let i=new RegExp(String.raw`^create\s+(?:(?:global|local)\s+)?(?:temp(?:orary)?\s+|unlogged\s+)?table\s+(?:if\s+not\s+exists\s+)?${jE}\s*\(`,`i`).exec(e);if(!i?.[1]){r.push(`${t}: skipped a create table statement it couldn't read: "${GE(e)}"`);return}let{schema:a,table:o}=NE(i[1]),s=i[0].length-1,c=LE(e,s);if(c===-1){r.push(`${t}: unbalanced parentheses in create table ${o}`);return}let l=PE(a,o);if(n.has(l)&&/\bif\s+not\s+exists\b/i.test(e.slice(0,s)))return;let u={schema:a,table:o,sourcePath:t,columns:[]};for(let i of OE(e.slice(s+1,c))){if(/^(constraint|primary\s+key|unique|foreign\s+key|check|exclude|like)\b/i.test(i)){HE(u,i,n);continue}let e=RE(i,n);e?u.columns.push(e):r.push(`${t}: skipped column definition "${GE(i)}" in ${o}`)}n.set(l,u)}function LE(e,t){let n=0,r=null;for(let i=t;i<e.length;i++){let t=e[i];if(r)t===r&&(r=null);else if(t===`'`||t===`"`)r=t;else if(t===`(`)n++;else if(t===`)`&&--n===0)return i}return-1}function RE(e,t){let n=kE(e),r=n[0];if(!r||n.length<2)return null;let i=1,a=[];for(;i<n.length&&!pE.test(n[i]??``);)a.push(n[i]),i++;if(a.length===0)return null;let o={name:ME(r),type:a.join(` `).replace(/\s+\(/g,`(`).toLowerCase(),required:!1};return zE(o,n.slice(i),t),o}function zE(e,t,n){for(let r=0;r<t.length;r++){let i=t[r]?.toLowerCase(),a=t[r+1]?.toLowerCase();if(i===`not`&&a===`null`)e.required=!0,r++;else if(i===`primary`&&a===`key`)e.primaryKey=!0,e.required=!0,r++;else if(i===`unique`)e.unique=!0;else if(i==="default"){let n=[];for(;r+1<t.length&&!pE.test(t[r+1]??``);)n.push(t[r+1]),r++;n.length>0&&(e.default=BE(n))}else if(i===`references`){let i=t[r+1];if(!i)continue;let a=t[r+2]?.startsWith(`(`)?t[r+2]:void 0;e.references=VE(i,a,n),r+=a?2:1}}}function BE(e){return e.join(` `).replace(/\s+\(/g,`(`)}function VE(e,t,n){let{schema:r,table:i}=NE(e),a=r===`public`?i:`${r}.${i}`,o=t?ME(t.slice(1,-1).split(`,`)[0]??``):null;return o||=n.get(PE(r,i))?.columns.find(e=>e.primaryKey)?.name??`id`,`${a}.${o}`}function HE(e,t,n){let r=t.replace(new RegExp(String.raw`^constraint\s+${AE}\s+`,`i`),``),i=e=>(e??``).split(`,`).map(e=>ME(e)).filter(Boolean),a=/^primary\s+key\s*\(([^)]*)\)/i.exec(r);if(a){for(let t of i(a[1])){let n=e.columns.find(e=>e.name===t);n&&(n.primaryKey=!0,n.required=!0)}return}let o=/^unique\s*(?:nulls\s+(?:not\s+)?distinct\s*)?\(([^)]*)\)/i.exec(r);if(o){let t=i(o[1]),n=t.length===1?e.columns.find(e=>e.name===t[0]):void 0;n&&(n.unique=!0);return}let s=new RegExp(String.raw`^foreign\s+key\s*\(([^)]*)\)\s*references\s+${jE}\s*(\([^)]*\))?`,`i`).exec(r);if(s?.[2]){let t=i(s[1]),r=s[3]?i(s[3].slice(1,-1)):[];t.forEach((t,i)=>{let a=e.columns.find(e=>e.name===t);if(!a)return;let o=r[i];a.references=VE(s[2],o?`(${o})`:void 0,n)})}}function UE(e,t,n,r,i){let a=r.get(PE(e.schema,e.table));if(!a){!fE.has(e.schema)&&/\b(add|drop|alter|rename)\s+column\b/i.test(t)&&i.push(`${n}: alter table ${e.table} before any create table for it, skipped`);return}let o=new RegExp(String.raw`^rename\s+to\s+(${AE})$`,`i`).exec(t);if(o?.[1]){r.delete(PE(a.schema,a.table)),a.table=ME(o[1]),r.set(PE(a.schema,a.table),a);return}let s=new RegExp(String.raw`^rename\s+(?:column\s+)?(${AE})\s+to\s+(${AE})$`,`i`).exec(t);if(s?.[1]&&s[2]){let e=a.columns.find(e=>e.name===ME(s[1]));e&&(e.name=ME(s[2]))}else for(let e of OE(t)){let t=/^add\s+(?:column\s+)?(?:if\s+not\s+exists\s+)?(.+)$/i.exec(e);if(t?.[1]&&!/^add\s+(constraint|primary|unique|foreign|check|exclude)\b/i.test(e)){let o=RE(t[1],r);if(!o){i.push(`${n}: skipped "${GE(e)}" on ${a.table}`);continue}a.columns.some(e=>e.name===o.name)||a.columns.push(o);continue}let o=/^add\s+(.+)$/i.exec(e);if(o?.[1]){HE(a,o[1],r);continue}let s=new RegExp(String.raw`^drop\s+(?:column\s+)?(?:if\s+exists\s+)?(${AE})`,`i`).exec(e);if(s?.[1]&&!/^drop\s+constraint\b/i.test(e)){let e=ME(s[1]);a.columns=a.columns.filter(t=>t.name!==e);continue}let c=new RegExp(String.raw`^alter\s+(?:column\s+)?(${AE})\s+(.+)$`,`i`).exec(e);if(c?.[1]&&c[2]){let e=a.columns.find(e=>e.name===ME(c[1]));e&&WE(e,c[2])}}}function WE(e,t){if(/^set\s+not\s+null$/i.test(t))e.required=!0;else if(/^drop\s+not\s+null$/i.test(t))e.required=!!e.primaryKey;else if(/^drop\s+default$/i.test(t))delete e.default;else{let n=/^set\s+default\s+(.+)$/i.exec(t);if(n?.[1]){e.default=BE(kE(n[1]));return}let r=/^(?:set\s+data\s+)?type\s+(.+?)(?:\s+(?:using|collate)\s+.*)?$/i.exec(t);r?.[1]&&(e.type=r[1].replace(/\s+\(/g,`(`).toLowerCase())}}function GE(e){return e.length>60?`${e.slice(0,57)}...`:e}const KE=[`GET`,`POST`,`PUT`,`PATCH`,`DELETE`],qE=/^(openapi|swagger)([.-][\w.-]*)?\.(json|ya?ml)$/i,JE=/\.(json|ya?ml)$/i;async function YE(e){let t=[];for(let n of e.files){let r=qE.test(kx(n.path));if(!r&&!JE.test(n.path)||!r&&(n.size>1048576||/(^|\/)[^/]*lock[^/]*$/i.test(n.path)))continue;let i=await e.readText(n,r?10485760:void 0);if(i===null||!r&&!/^\s*["']?(openapi|swagger)["']?\s*:/m.test(i))continue;let a;try{a=/\.json$/i.test(n.path)?JSON.parse(i):(0,uw.parse)(i)}catch(t){e.warnings.push(`${n.path}: OpenAPI file could not be parsed (${Mx(t)})`);continue}!Z(a)||typeof a.openapi!=`string`&&typeof a.swagger!=`string`?r&&e.warnings.push(`${n.path}: no top-level openapi or swagger version, skipped`):t.push(...XE(a,n.path,e.warnings))}return t}function XE(e,t,n){let r=typeof e.swagger==`string`,i=new ZE(e,t,n),a=r?e.securityDefinitions:$E(e.components)?.securitySchemes,o=Z(a)?a:{},s=Z(e.paths)?e.paths:{},c=[];for(let[n,a]of Object.entries(s)){let s=i.resolve(a);if(s)for(let a of KE){let l=$E(s[a.toLowerCase()]);if(!l)continue;let u=[...Array.isArray(s.parameters)?s.parameters:[],...Array.isArray(l.parameters)?l.parameters:[]],d=l.security??e.security;c.push({kind:`endpoint`,name:Nx(l.summary)?.trim()||Nx(l.operationId)||`${a} ${n}`,sourcePath:t,method:a,path:n,auth:pD(d,o,i),request:r?iD(u,l,e,i):tD(l.requestBody,i),responses:aD(l,e,r,i)})}}return c}var ZE=class{#e;#t;#n;#r=/* @__PURE__ */ new Set;constructor(e,t,n){this.#e=e,this.#t=t,this.#n=n}resolve(e){let t=e;for(let e=0;e<8;e++){if(!Z(t))return null;let e=t.$ref;if(typeof e!=`string`)return t;t=this.#i(e)}return null}refName(e){if(!Z(e)||typeof e.$ref!=`string`)return null;let t=e.$ref.slice(e.$ref.lastIndexOf(`/`)+1);return t?QE(t):null}#i(e){if(!e.startsWith(`#/`))return this.#r.has(e)||(this.#r.add(e),this.#n.push(`${this.#t}: external $ref "${e}" not followed`)),null;let t=this.#e;for(let n of e.slice(2).split(`/`)){if(!Z(t))break;t=t[QE(n)]}return t===void 0&&!this.#r.has(e)&&(this.#r.add(e),this.#n.push(`${this.#t}: $ref "${e}" points at nothing`)),t}};function QE(e){return decodeURIComponent(e).replace(/~1/g,`/`).replace(/~0/g,`~`)}function $E(e){return Z(e)?e:null}function eD(e){if(!Z(e))return null;let t=Object.entries(e).filter(e=>Z(e[1]));return t.find(([e])=>e===`application/json`)??t.find(([e])=>/json/.test(e))??t[0]??null}function tD(e,t){let n=t.resolve(e),r=n?eD(n.content):null;return r?nD(r[0],r[1],t):null}function nD(e,t,n){let r=t.schema;return{contentType:e,fields:lD(r,n),example:rD(t,n)??fD(r,n,0)}}function rD(e,t){if(e.example!==void 0)return e.example;if(Z(e.examples)){let n=t.resolve(Object.values(e.examples)[0]);if(n&&n.value!==void 0)return n.value}}function iD(e,t,n,r){let i=e.map(e=>r.resolve(e)).filter(e=>e!==null),a=sD(t.consumes)??sD(n.consumes),o=i.find(e=>e.in===`body`);if(o)return{contentType:a??`application/json`,fields:lD(o.schema,r),example:fD(o.schema,r,0)};let s=i.filter(e=>e.in===`formData`);if(s.length===0)return null;let c=s.map(e=>({name:Nx(e.name)??``,type:dD(e,r),required:e.required===!0,...uD(e)}));return{contentType:a??`application/x-www-form-urlencoded`,fields:c,example:Object.fromEntries(s.map(e=>[Nx(e.name)??``,fD(e,r,1)]))}}function aD(e,t,n,r){if(!Z(e.responses))return[];let i=sD(e.produces)??sD(t.produces)??`application/json`,a=[];for(let[t,o]of Object.entries(e.responses)){let e=r.resolve(o);if(!e)continue;let s=null;if(n){if(e.schema!==void 0){let t=$E(e.examples);s={contentType:i,fields:lD(e.schema,r),example:t?.[i]??fD(e.schema,r,0)}}}else{let t=eD(e.content);t&&(s=nD(t[0],t[1],r))}a.push({status:oD(t),description:Nx(e.description)??``,body:s})}return a}function oD(e){let t=e.replace(/x/gi,`0`),n=Number.parseInt(t,10);return Number.isNaN(n)?0:n}function sD(e){return Array.isArray(e)&&typeof e[0]==`string`?e[0]:void 0}function cD(e,t,n=0){let r=t.resolve(e);if(!r||n>8)return r;if(Array.isArray(r.allOf)){let e={},i=[];for(let a of r.allOf){let r=cD(a,t,n+1);r&&(Z(r.properties)&&Object.assign(e,r.properties),Array.isArray(r.required)&&i.push(...r.required.filter(e=>typeof e==`string`)))}return Z(r.properties)&&Object.assign(e,r.properties),Array.isArray(r.required)&&i.push(...r.required.filter(e=>typeof e==`string`)),{...r,type:`object`,properties:e,required:i}}let i=Array.isArray(r.oneOf)?r.oneOf:Array.isArray(r.anyOf)?r.anyOf:null;return i&&i.length>0&&!r.properties?cD(i[0],t,n+1):r}function lD(e,t){let n=cD(e,t);if(n?.type===`array`&&(n=cD(n.items,t)),!n||!Z(n.properties))return[];let r=new Set(Array.isArray(n.required)?n.required:[]);return Object.entries(n.properties).map(([e,n])=>{let i=cD(n,t)??{};return{name:e,type:dD(n,t),required:r.has(e),...uD(i)}})}function uD(e){let t={},n=Nx(e.description)?.trim();return n&&(t.description=n),Array.isArray(e.enum)&&(t.values=e.enum.map(e=>String(e))),t}function dD(e,t,n=0){let r=t.refName(e),i=cD(e,t);if(!i)return r??`unknown`;let a=Array.isArray(i.type)?i.type.filter(e=>e!==`null`).join(` | `):Nx(i.type);return a===`array`?n>8?`array`:`${dD(i.items,t,n+1)}[]`:r&&(a===`object`||a===void 0)?r:Nx(i.format)??a??(i.properties?`object`:`unknown`)}function fD(e,t,n){let r=cD(e,t);if(!r||n>8)return null;if(r.example!==void 0)return r.example;if(Array.isArray(r.enum)&&r.enum.length>0)return r.enum[0];let i=Array.isArray(r.type)?r.type.find(e=>e!==`null`):r.type;if(i===`object`||i===void 0&&Z(r.properties)){let e=Z(r.properties)?r.properties:{};return Object.fromEntries(Object.entries(e).map(([e,r])=>[e,fD(r,t,n+1)]))}switch(i){case`array`:return[fD(r.items,t,n+1)];case`string`:return`string`;case`integer`:case`number`:return 0;case`boolean`:return!1;default:return null}}function pD(e,t,n){if(!Array.isArray(e)||e.length===0)return null;let r=[];for(let i of e){if(!Z(i))continue;let e=Object.keys(i);e.length===0?r.push(`none`):r.push(e.map(e=>mD(e,n.resolve(t[e]))).join(` + `))}let i=[...new Set(r)];return i.length===0||i.length===1&&i[0]===`none`?null:i.map(e=>e===`none`?`no auth`:e).join(` or `)}function mD(e,t){if(!t)return e;switch(Nx(t.type)?.toLowerCase()){case`http`:{let e=Nx(t.scheme)?.toLowerCase();if(e===`bearer`){let e=Nx(t.bearerFormat);return e?`Bearer token (${e})`:`Bearer token`}return e===`basic`?`Basic auth`:`HTTP ${e??`auth`}`}case`basic`:return`Basic auth`;case`apikey`:return`apikey ${Nx(t.in)??`header`} ${Nx(t.name)??e}`;case`oauth2`:return`OAuth2`;case`openidconnect`:return`OpenID Connect`;case`mutualtls`:return`Mutual TLS`;default:return e}}const hD=[`readme.md`,`readme.mdx`,`readme.markdown`,`readme.txt`,`readme`];async function gD(e){let t=e.files.find(e=>!e.path.includes(`/`)&&hD.includes(e.path.toLowerCase()));if(!t)return null;let n=await e.readText(t);return{path:t.path,oneLiner:n===null?null:_D(n)}}function _D(e){let t=e.replace(/\r\n/g,`
374
+ `,e)+1}return{type:e,offset:this.offset,indent:this.indent,source:this.source}}startBlockValue(e){switch(this.type){case`alias`:case`scalar`:case`single-quoted-scalar`:case`double-quoted-scalar`:return this.flowScalar(this.type);case`block-scalar-header`:return{type:`block-scalar`,offset:this.offset,indent:this.indent,props:[this.sourceToken],source:``};case`flow-map-start`:case`flow-seq-start`:return{type:`flow-collection`,offset:this.offset,indent:this.indent,start:this.sourceToken,items:[],end:[]};case`seq-item-ind`:return{type:`block-seq`,offset:this.offset,indent:this.indent,items:[{start:[this.sourceToken]}]};case`explicit-key-ind`:{this.onKeyLine=!0;let t=c(s(e));return t.push(this.sourceToken),{type:`block-map`,offset:this.offset,indent:this.indent,items:[{start:t,explicitKey:!0}]}}case`map-value-ind`:{this.onKeyLine=!0;let t=c(s(e));return{type:`block-map`,offset:this.offset,indent:this.indent,items:[{start:t,key:null,sep:[this.sourceToken]}]}}}return null}atIndentedComment(e,t){return this.type!==`comment`||this.indent<=t?!1:e.every(e=>e.type===`newline`||e.type===`space`)}*documentEnd(e){this.type!==`doc-mode`&&(e.end?e.end.push(this.sourceToken):e.end=[this.sourceToken],this.type===`newline`&&(yield*this.pop()))}*lineEnd(e){switch(this.type){case`comma`:case`doc-start`:case`doc-end`:case`flow-seq-end`:case`flow-map-end`:case`map-value-ind`:yield*this.pop(),yield*this.step();break;case`newline`:this.onKeyLine=!1;default:e.end?e.end.push(this.sourceToken):e.end=[this.sourceToken],this.type===`newline`&&(yield*this.pop())}}}})),lw=/* @__PURE__ */ E((e=>{var t=tw(),n=RC(),r=zC(),i=lC(),a=$(),o=sw(),s=cw();function c(e){let t=e.prettyErrors!==!1;return{lineCounter:e.lineCounter||t&&new o.LineCounter||null,prettyErrors:t}}function l(e,n={}){let{lineCounter:i,prettyErrors:a}=c(n),o=new s.Parser(i?.addNewLine),l=new t.Composer(n),u=Array.from(l.compose(o.parse(e)));if(a&&i)for(let t of u)t.errors.forEach(r.prettifyError(e,i)),t.warnings.forEach(r.prettifyError(e,i));return u.length>0?u:Object.assign([],{empty:!0},l.streamInfo())}function u(e,n={}){let{lineCounter:i,prettyErrors:a}=c(n),o=new s.Parser(i?.addNewLine),l=new t.Composer(n),u=null;for(let t of l.compose(o.parse(e),!0,e.length))if(!u)u=t;else if(u.options.logLevel!==`silent`){u.errors.push(new r.YAMLParseError(t.range.slice(0,2),`MULTIPLE_DOCS`,`Source contains multiple documents; please use YAML.parseAllDocuments()`));break}return a&&i&&(u.errors.forEach(r.prettifyError(e,i)),u.warnings.forEach(r.prettifyError(e,i))),u}function d(e,t,n){let r;typeof t==`function`?r=t:n===void 0&&t&&typeof t==`object`&&(n=t);let a=u(e,n);if(!a)return null;if(a.warnings.forEach(e=>i.warn(a.options.logLevel,e)),a.errors.length>0){if(a.options.logLevel!==`silent`)throw a.errors[0];a.errors=[]}return a.toJS(Object.assign({reviver:r},n))}function f(e,t,r){let i=null;if(typeof t==`function`||Array.isArray(t)?i=t:r===void 0&&t&&(r=t),typeof r==`string`&&(r=r.length),typeof r==`number`){let e=Math.round(r);r=e<1?void 0:e>8?{indent:8}:{indent:e}}if(e===void 0){let{keepUndefined:e}=r??t??{};if(!e)return}return a.isDocument(e)&&!i?e.toString(r):new n.Document(e,i,r).toString(r)}e.parse=d,e.parseAllDocuments=l,e.parseDocument=u,e.stringify=f})),uw=(/* @__PURE__ */ E((e=>{var t=tw(),n=RC(),r=IC(),i=zC(),a=eC(),o=$(),s=fC(),c=tC(),l=mC(),u=gC();aw();var d=ow(),f=sw(),p=cw(),m=lw(),h=JS();e.Composer=t.Composer,e.Document=n.Document,e.Schema=r.Schema,e.YAMLError=i.YAMLError,e.YAMLParseError=i.YAMLParseError,e.YAMLWarning=i.YAMLWarning,e.Alias=a.Alias,e.isAlias=o.isAlias,e.isCollection=o.isCollection,e.isDocument=o.isDocument,e.isMap=o.isMap,e.isNode=o.isNode,e.isPair=o.isPair,e.isScalar=o.isScalar,e.isSeq=o.isSeq,e.Pair=s.Pair,e.Scalar=c.Scalar,e.YAMLMap=l.YAMLMap,e.YAMLSeq=u.YAMLSeq,e.Lexer=d.Lexer,e.LineCounter=f.LineCounter,e.Parser=p.Parser,e.parse=m.parse,e.parseAllDocuments=m.parseAllDocuments,e.parseDocument=m.parseDocument,e.stringify=m.stringify,e.visit=h.visit,e.visitAsync=h.visitAsync})))();function dw(e,t){let n=(0,uw.parse)(e,{uniqueKeys:!1});if(!Z(n))throw Error(`not a YAML mapping`);let r=new HS(`npm`,t),i=Z(n.importers)?n.importers:{".":n};for(let e of Object.values(i))if(Z(e))for(let t of[`dependencies`,`devDependencies`,`optionalDependencies`]){let n=e[t];if(Z(n))for(let[e,t]of Object.entries(n)){let n=Z(t)?t.version:t;if(typeof n!=`string`||fw(n))continue;let i=mw(n);i?r.add(i.name,i.version,!0):r.add(e,pw(n),!0)}}for(let e of[`packages`,`snapshots`]){let t=n[e];if(Z(t))for(let e of Object.keys(t)){let t=mw(e);t&&!fw(t.version)&&r.add(t.name,t.version,!1)}}return r.rows()}function fw(e){return/^(link|file|workspace):/.test(e)}function pw(e){return e.replace(/\(.*$/,``).replace(/_(?=[^/]*@).*$/,``)}function mw(e){let t=e.replace(/^\//,``).replace(/\(.*$/,``),n=t.indexOf(`@`,1);if(n>0)return{name:t.slice(0,n),version:pw(t.slice(n+1))};if(!e.startsWith(`/`))return null;let r=t.lastIndexOf(`/`);return r<=0?null:{name:t.slice(0,r),version:pw(t.slice(r+1))}}function hw(e,t){let n=GS(e);if(!Z(n))throw Error(`not a JSON object`);let r=new HS(`npm`,t);if(Z(n.packages)){let e=/* @__PURE__ */ new Set;for(let[t,r]of Object.entries(n.packages))if(!t.includes(`node_modules/`))for(let t of WS(r))e.add(t);for(let[t,i]of Object.entries(n.packages)){let n=t.lastIndexOf(`node_modules/`);if(n===-1||!Z(i)||i.link===!0)continue;let a=t.slice(n+13),o=typeof i.name==`string`?i.name:a;if(typeof i.version!=`string`)continue;let s=t===`node_modules/${a}`;r.add(o,i.version,s&&e.has(a))}return r.rows()}if(Z(n.dependencies)){let e=(t,n)=>{for(let[i,a]of Object.entries(t)){if(!Z(a))continue;let t=a.version;typeof t==`string`&&!fw(t)&&r.add(i,t,n===0&&a.dev!==!0),Z(a.dependencies)&&e(a.dependencies,n+1)}};e(n.dependencies,0)}return r.rows()}function gw(e,t,n){let r=new HS(`npm`,t),i=[],a=!1;for(let t of e.split(/\r?\n/)){if(t===``||t.startsWith(`#`))continue;if(!/^\s/.test(t)&&t.endsWith(`:`)){let e=t.slice(0,-1).split(`,`).map(e=>e.trim().replace(/^"|"$/g,``));a=e.some(e=>/@(workspace|link|file|portal):/.test(e)),i=[...new Set(e.map(_w).filter(e=>e!==null))];continue}let e=/^\s+version:?\s+"?([^"\s]+)"?/.exec(t)?.[1];if(e&&!a){for(let t of i)r.add(t,e,n.has(t));i=[]}}return r.rows()}function _w(e){if(e===`__metadata`)return null;let t=e.indexOf(`@`,1);return t>0?e.slice(0,t):null}async function vw(e,t){let n=Ax(t),r=/* @__PURE__ */ new Set,i=await yw(e,jx(n,`package.json`));for(let e of WS(i))r.add(e);if(!Z(i))return r;let a=i.workspaces,o=(Array.isArray(a)?a:Z(a)&&Array.isArray(a.packages)?a.packages:[]).filter(e=>typeof e==`string`).map(e=>bw(jx(n,e.replace(/^\.\//,``).replace(/\/$/,``))));if(o.length===0)return r;for(let t of e.files){if(!t.path.endsWith(`package.json`))continue;let n=Ax(t.path);if(o.some(e=>e.test(n)))for(let n of WS(await yw(e,t.path)))r.add(n)}return r}async function yw(e,t){let n=e.file(t);if(!n)return null;let r=await e.readText(n);if(r===null)return null;try{return GS(r)}catch{return e.warnings.push(`${t}: not valid JSON, skipped`),null}}function bw(e){let t=e.split(`/`).map(e=>e===`**`?`.*`:e.replace(/[.+^${}()|[\]\\]/g,`\\$&`).replace(/\*/g,`[^/]*`)).join(`/`);return RegExp(`^${t}$`)}function xw(e){return e.toLowerCase().replace(/[-_.]+/g,`-`)}function Sw(e,t,n){let r=new HS(`pip`,t),i=!1,a=null,o=null,s=!1,c=()=>{a&&o&&!s&&r.add(a,o,n.has(xw(a))),a=null,o=null,s=!1};for(let t of e.split(/\r?\n/)){if(/^\s*\[{1,2}([^\]]+)\]{1,2}\s*$/.exec(t)){t.trim()===`[[package]]`?(c(),i=!0):i=!1;continue}if(!i)continue;let e=/^\s*(name|version|source)\s*=\s*(.+)$/.exec(t);if(!e)continue;let n=e[2]?.trim()??``;if(e[1]===`source`)s=/\b(editable|virtual)\s*=/.test(n);else{let t=/^"([^"]*)"/.exec(n)?.[1];e[1]===`name`&&t&&(a=t),e[1]===`version`&&t&&(o=t)}}return c(),r.rows()}function Cw(e){let t=/* @__PURE__ */ new Set,n=``,r=null,i=``,a=e=>{let n=/^\s*([A-Za-z0-9][A-Za-z0-9._-]*)/.exec(e)?.[1];n&&t.add(xw(n))},o=()=>{for(let e of i.matchAll(/"([^"]*)"|'([^']*)'/g))a(e[1]??e[2]??``);r=null,i=``},s=e=>e.replace(/"[^"]*"|'[^']*'/g,``).includes(`]`);for(let a of e.split(/\r?\n/)){let e=a.replace(/\s+#.*$/,``);if(r!==null){i+=` ${e}`,s(e)&&o();continue}let c=/^\s*\[([^\]]+)\]\s*$/.exec(e);if(c){n=(c[1]??``).trim();continue}let l=/^\s*"?([A-Za-z0-9_.-]+)"?\s*=\s*(.*)$/.exec(e);if(!l)continue;let u=l[1]??``,d=l[2]??``;n===`tool.poetry.dependencies`||n===`tool.poetry.dev-dependencies`||/^tool\.poetry\.group\.[^.]+\.dependencies$/.test(n)?xw(u)!==`python`&&t.add(xw(u)):(n===`project`&&u===`dependencies`||n===`project.optional-dependencies`||n===`dependency-groups`)&&d.trimStart().startsWith(`[`)&&(r=u,i=d,s(d.trimStart().slice(1))&&o())}return t}function ww(e,t){let n=new HS(`pip`,t),r=0;for(let t of e.split(/\r?\n/)){let e=t.replace(/(^|\s)#.*$/,``).trim();if(e===``||e.startsWith(`-`))continue;let i=/^([A-Za-z0-9][A-Za-z0-9._-]*)\s*(?:\[[^\]]*\])?\s*===?\s*([^\s;,\\]+)/.exec(e);i?.[1]&&i[2]?n.add(i[1],i[2],!0):r++}return{rows:n.rows(),unpinned:r}}async function Tw(e){let t=[];for(let n of e.files)try{let r=await Ew(e,n);r&&t.push(...r)}catch(t){e.warnings.push(`${n.path}: could not be parsed (${Mx(t)})`)}return t}async function Ew(e,t){let n=kx(t.path),r=Ax(t.path),i=t=>t?e.readText(t,52428800):Promise.resolve(null),a=t=>e.file(jx(r,t));switch(n){case`pnpm-lock.yaml`:{let e=await i(t);return e===null?null:dw(e,t.path)}case`package-lock.json`:case`npm-shrinkwrap.json`:{let e=await i(t);return e===null?null:hw(e,t.path)}case`yarn.lock`:{let n=await i(t);return n===null?null:gw(n,t.path,await vw(e,t.path))}case`composer.lock`:{let e=await i(t);return e===null?null:KS(e,t.path,await i(a(`composer.json`)))}case`poetry.lock`:case`uv.lock`:{let e=await i(t);if(e===null)return null;let n=await i(a(`pyproject.toml`)),r=n?Cw(n):/* @__PURE__ */ new Set;return Sw(e,t.path,r)}case`go.sum`:case`go.mod`:return n===`go.mod`&&a(`go.sum`)?null:qS(await i(a(`go.mod`)),n===`go.sum`?await i(t):null,t.path)}if(/^requirements[\w.-]*\.txt$/i.test(n)||/(^|\/)requirements\/[^/]+\.txt$/.test(t.path)){let n=await i(t);if(n===null)return null;let{rows:r,unpinned:a}=ww(n,t.path);return a>0&&e.warnings.push(`${t.path}: ${a} requirement${a===1?``:`s`} without an exact == pin skipped`),r}return null}const Dw={name:`Supabase`,type:`database`,provider:`Supabase Postgres`},Ow={name:`Postgres`,type:`database`,provider:`Postgres`},kw={name:`MySQL`,type:`database`,provider:`MySQL`},Aw={name:`MongoDB`,type:`database`,provider:`MongoDB`},jw={name:`Redis`,type:`database`,provider:`Redis`},Mw={name:`Elasticsearch`,type:`database`,provider:`Elasticsearch`},Nw={name:`AWS S3`,type:`storage`,provider:`AWS S3`},Pw={name:`AWS SQS`,type:`queue`,provider:`AWS SQS`},Fw={name:`AWS`,type:`service`,provider:`AWS`},Iw={name:`MinIO`,type:`storage`,provider:`MinIO`},Lw={name:`Cloudinary`,type:`storage`,provider:`Cloudinary`},Rw={name:`RabbitMQ`,type:`queue`,provider:`RabbitMQ`},zw={name:`Kafka`,type:`queue`,provider:`Kafka`},Bw={name:`Stripe`,type:`external_api`,provider:`Stripe`},Vw={name:`Twilio`,type:`external_api`,provider:`Twilio`},Hw={name:`SendGrid`,type:`service`,provider:`SendGrid`},Uw={name:`Postmark`,type:`service`,provider:`Postmark`},Ww={name:`Resend`,type:`service`,provider:`Resend`},Gw={name:`Mailgun`,type:`service`,provider:`Mailgun`},Kw={name:`Email (SMTP)`,type:`service`,provider:`SMTP`},qw={name:`Firebase`,type:`service`,provider:`Firebase`},Jw={name:`OpenAI`,type:`ai`,provider:`OpenAI`},Yw={name:`Anthropic`,type:`ai`,provider:`Anthropic`},Xw={name:`Sentry`,type:`monitoring`,provider:`Sentry`},Zw={name:`Auth0`,type:`auth`,provider:`Auth0`},Qw={name:`Clerk`,type:`auth`,provider:`Clerk`},$w={name:`Auth.js`,type:`auth`,provider:`Auth.js`},eT={name:`Algolia`,type:`external_api`,provider:`Algolia`},tT={name:`Google Cloud`,type:`service`,provider:`Google Cloud`},nT={name:`Cloud Storage`,type:`storage`,provider:`Google Cloud Storage`},rT={name:`Pub/Sub`,type:`queue`,provider:`Google Cloud Pub/Sub`},iT={name:`BigQuery`,type:`database`,provider:`Google BigQuery`},aT={name:`Firestore`,type:`database`,provider:`Google Firestore`},oT={name:`Secret Manager`,type:`secrets`,provider:`Google Secret Manager`},sT={name:`Gemini`,type:`ai`,provider:`Google Gemini`},cT={name:`Vertex AI`,type:`ai`,provider:`Google Vertex AI`},lT={name:`SerpApi`,type:`external_api`,provider:`SerpApi`},uT={name:`Zyte`,type:`external_api`,provider:`Zyte`},dT={name:`Open Exchange Rates`,type:`external_api`,provider:`Open Exchange Rates`},fT={name:`reCAPTCHA`,type:`external_api`,provider:`Google reCAPTCHA`},pT={name:`DuckDB`,type:`database`,provider:`DuckDB`},mT=[[/^SUPABASE_/,Dw],[/^(DATABASE_URL|POSTGRES_|PG(HOST|USER|PASSWORD|DATABASE|PORT)$)/,Ow],[/^MYSQL_/,kw],[/^MONGO(DB)?_/,Aw],[/^(REDIS_|UPSTASH_REDIS_)/,jw],[/^(ELASTIC(SEARCH)?_)/,Mw],[/^(AWS_)?S3_|_S3_BUCKET$|^AWS_BUCKET/,Nw],[/^(AWS_)?SQS_/,Pw],[/^AWS_(ACCESS_KEY_ID|SECRET_ACCESS_KEY|REGION|DEFAULT_REGION)$/,Fw],[/^MINIO_/,Iw],[/^CLOUDINARY_/,Lw],[/^(RABBITMQ_|AMQP_URL)/,Rw],[/^KAFKA_/,zw],[/^STRIPE_/,Bw],[/^TWILIO_/,Vw],[/^SENDGRID_/,Hw],[/^POSTMARK_/,Uw],[/^RESEND_/,Ww],[/^MAILGUN_/,Gw],[/^SMTP_/,Kw],[/^FIREBASE_/,qw],[/^OPENAI_/,Jw],[/^ANTHROPIC_/,Yw],[/^SENTRY_/,Xw],[/^AUTH0_/,Zw],[/^CLERK_/,Qw],[/^(NEXTAUTH_|AUTH_SECRET$)/,$w],[/^ALGOLIA_/,eT],[/^(GCS_BUCKET|GOOGLE_CLOUD_STORAGE_|GCS_)/,nT],[/^(PUBSUB_|GOOGLE_PUBSUB_)/,rT],[/^BIGQUERY_/,iT],[/^FIRESTORE_/,aT],[/^(GEMINI_|GOOGLE_GENAI_)/,sT],[/^VERTEX(_AI)?_/,cT],[/^(SERPAPI_|SERP_API_)/,lT],[/^ZYTE_/,uT],[/^(OPEN_EXCHANGE_RATES_|OPENEXCHANGERATES_|OXR_)/,dT],[/^RECAPTCHA_/,fT],[/^(GOOGLE_CLOUD_PROJECT|GCP_PROJECT(_ID)?|GCLOUD_PROJECT|GOOGLE_APPLICATION_CREDENTIALS)$/,tT]],hT=[[[`@supabase/supabase-js`,`@supabase/ssr`,`supabase`,`github.com/supabase-community/*`,`supabase/supabase-php`],Dw],[[`pg`,`postgres`,`pg-promise`,`@neondatabase/serverless`,`@vercel/postgres`,`psycopg2`,`psycopg2-binary`,`psycopg`,`asyncpg`,`github.com/jackc/pgx*`,`github.com/lib/pq`],Ow],[[`mysql`,`mysql2`,`pymysql`,`mysqlclient`,`github.com/go-sql-driver/mysql`],kw],[[`mongodb`,`mongoose`,`pymongo`,`motor`,`go.mongodb.org/mongo-driver*`,`mongodb/mongodb`],Aw],[[`redis`,`ioredis`,`@upstash/redis`,`predis/predis`,`github.com/redis/go-redis*`,`github.com/go-redis/redis*`],jw],[[`@elastic/elasticsearch`,`elasticsearch`,`elasticsearch/elasticsearch`],Mw],[[`@aws-sdk/client-s3`,`github.com/aws/aws-sdk-go-v2/service/s3`,`league/flysystem-aws-s3-v3`],Nw],[[`@aws-sdk/client-sqs`,`github.com/aws/aws-sdk-go-v2/service/sqs`],Pw],[[`aws-sdk`,`boto3`,`aws/aws-sdk-php`,`github.com/aws/aws-sdk-go`],Fw],[[`minio`],Iw],[[`cloudinary`,`cloudinary/cloudinary_php`],Lw],[[`amqplib`,`pika`,`php-amqplib/php-amqplib`,`github.com/rabbitmq/amqp091-go`],Rw],[[`kafkajs`,`kafka-python`,`confluent-kafka`,`github.com/segmentio/kafka-go`],zw],[[`stripe`,`@stripe/stripe-js`,`@stripe/react-stripe-js`,`stripe/stripe-php`,`github.com/stripe/stripe-go*`],Bw],[[`twilio`,`twilio/sdk`,`github.com/twilio/twilio-go`],Vw],[[`@sendgrid/`,`sendgrid`,`sendgrid/sendgrid`],Hw],[[`postmark`,`wildbit/postmark-php`],Uw],[[`resend`,`resend/resend-php`],Ww],[[`mailgun.js`,`mailgun/mailgun-php`],Gw],[[`nodemailer`],Kw],[[`firebase`,`firebase-admin`,`firebase-functions`,`kreait/firebase-php`,`firebase.google.com/go*`],qw],[[`openai`,`openai-php/client`,`github.com/sashabaranov/go-openai`],Jw],[[`@anthropic-ai/sdk`,`anthropic`,`github.com/anthropics/anthropic-sdk-go`],Yw],[[`@sentry/`,`sentry-sdk`,`sentry/sentry`,`sentry/sentry-laravel`,`github.com/getsentry/sentry-go`],Xw],[[`@auth0/`,`auth0`,`auth0/auth0-php`],Zw],[[`@clerk/`],Qw],[[`next-auth`,`@auth/`],$w],[[`algoliasearch`,`algolia/algoliasearch-client-php`],eT],[[`@google-cloud/storage`,`google-cloud-storage`,`cloud.google.com/go/storage`],nT],[[`@google-cloud/pubsub`,`google-cloud-pubsub`,`cloud.google.com/go/pubsub*`],rT],[[`@google-cloud/bigquery`,`google-cloud-bigquery`,`cloud.google.com/go/bigquery`],iT],[[`@google-cloud/firestore`,`google-cloud-firestore`,`cloud.google.com/go/firestore`],aT],[[`@google-cloud/secret-manager`,`google-cloud-secret-manager`,`cloud.google.com/go/secretmanager`],oT],[[`@google/genai`,`@google/generative-ai`,`google-genai`,`google-generativeai`],sT],[[`@google-cloud/vertexai`,`google-cloud-aiplatform`,`vertexai`],cT],[[`serpapi`,`google-search-results`],lT],[[`zyte-api`,`scrapy-zyte-api`],uT],[[`open-exchange-rates`],dT],[[`react-google-recaptcha`,`react-google-recaptcha-v3`,`vue-recaptcha`,`vue-recaptcha-v3`,`@google-cloud/recaptcha-enterprise`,`google-cloud-recaptcha-enterprise`,`django-recaptcha`],fT],[[`@google-cloud/`,`google-cloud-*`,`google-auth-library`,`google-auth`,`cloud.google.com/go*`],tT],[[`duckdb`,`@duckdb/`],pT]],gT=[[/^supabase\//,Dw],[/(^|\/)(postgres|postgis|timescaledb)$/,Ow],[/(^|\/)(mysql|mariadb)$/,kw],[/(^|\/)mongo(db)?$/,Aw],[/(^|\/)(redis|redis-stack|valkey)$/,jw],[/(^|\/)(elasticsearch|opensearch)$/,Mw],[/(^|\/)minio$/,Iw],[/(^|\/)rabbitmq$/,Rw],[/(^|\/)(kafka|cp-kafka)$/,zw],[/(^|\/)localstack$/,Fw],[/(^|\/)(cloud-sdk|google-cloud-cli)$/,tT],[/(^|\/)(gcloud-pubsub-emulator|pubsub-emulator)$/,rT],[/(^|\/)fake-gcs-server$/,nT]];function _T(e){return/^\.env(\.[\w-]+)*\.(example|sample|template|dist)$/i.test(e)||/^(example|sample)\.env$/i.test(e)}function vT(e){let t=kx(e);return/^\.gitlab-ci\.ya?ml$/.test(t)||/^cloudbuild\.ya?ml$/.test(t)||t===`bitbucket-pipelines.yml`||/(^|\/)\.github\/workflows\/[^/]+\.ya?ml$/.test(e)}function yT(e){return[...new Set(e.match(/\b[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+\b/g)??[])]}function bT(e){return/^(docker-)?compose([.-][\w.-]+)?\.ya?ml$/i.test(e)}var xT=class{#e=/* @__PURE__ */ new Map;add(e,t){let n=this.#e.get(e.provider);n?n.evidence.includes(t)||n.evidence.push(t):this.#e.set(e.provider,{...e,evidence:[t]})}list(){return[...this.#e.values()].sort((e,t)=>e.name.localeCompare(t.name))}};async function ST(e,t){let n=new xT,r=(e,t)=>{let r=e.replace(/^(NEXT_PUBLIC_|VITE_|PUBLIC_|REACT_APP_|EXPO_PUBLIC_|NUXT_PUBLIC_|NUXT_)/,``),i=mT.find(([e])=>e.test(r));i&&n.add(i[1],t)};for(let t of e.files){let i=kx(t.path);if(_T(i)){let n=await e.readText(t);if(n===null)continue;for(let e of CT(n))r(e,`env: ${e} (${t.path})`)}else if(vT(t.path)){let n=await e.readText(t);if(n===null)continue;for(let e of yT(n))r(e,`pipeline: ${e} (${t.path})`)}else if(bT(i)){let i=await e.readText(t);if(i===null)continue;let a;try{a=(0,uw.parse)(i)}catch(n){e.warnings.push(`${t.path}: could not be parsed (${Mx(n)})`);continue}let o=Z(a)&&Z(a.services)?a.services:{};for(let[e,i]of Object.entries(o)){if(!Z(i))continue;let a=i.environment,o=Array.isArray(a)?a.map(e=>String(e).split(`=`,1)[0]??``):Z(a)?Object.keys(a):[];for(let n of o)r(n,`docker-compose: ${e} env ${n} in ${t.path}`);if(typeof i.image!=`string`)continue;let s=wT(i.image),c=gT.find(([e])=>e.test(s));c&&n.add(c[1],`docker-compose: service ${e} (${i.image}) in ${t.path}`)}}else t.path===`supabase/config.toml`||t.path.endsWith(`/supabase/config.toml`)?n.add(Dw,`file: ${t.path}`):i===`firebase.json`?n.add(qw,`file: ${t.path}`):/^cloudbuild\.ya?ml$/.test(i)&&n.add(tT,`file: ${t.path}`)}for(let e of t){if(!e.direct)continue;let t=hT.find(([t])=>t.some(t=>TT(t,e.package)));t&&n.add(t[1],`dependency: ${e.package} (${e.sourceLockfile})`)}return n.list()}function CT(e){let t=[];for(let n of e.split(/\r?\n/)){let e=/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/.exec(n);e?.[1]&&t.push(e[1])}return t}function wT(e){let t=e.toLowerCase().replace(/@.*$/,``),n=t.lastIndexOf(`/`),r=t.indexOf(`:`,n+1);r!==-1&&(t=t.slice(0,r));let i=t.split(`/`);return i.length>1&&/[.:]|^localhost$/.test(i[0]??``)&&i.shift(),i[0]===`library`&&i.shift(),i.join(`/`)}function TT(e,t){return e.endsWith(`*`)?t.startsWith(e.slice(0,-1)):e.endsWith(`/`)?t.startsWith(e):t===e}const ET={name:`Supabase Auth`,type:`auth`,provider:`Supabase Auth`},DT={name:`pg_cron`,type:`scheduler`,provider:`pg_cron`},OT={postgres:[Dw,Ow],mysql:[kw]};function kT(e,t){let n=new Map(t.map(e=>[e.provider,e])),r=(e,t)=>{let r=n.get(e.provider);if(r)return r.provider;let i={...e,evidence:[t]};return n.set(e.provider,i),i.provider};for(let t of e){let e=t.sourcePath.slice(0,t.sourcePath.lastIndexOf(`/`)+1),i=/(^|\/)supabase\//i.test(t.sourcePath);if(t.kind===`job`){t.resource===DT.provider&&r(DT,`cron.schedule in ${t.sourcePath}`);continue}if(t.kind!==`table`&&t.kind!==`function`&&t.kind!==`role`)continue;if(t.kind===`role`){let e=[...n.values()].find(e=>e.type===`auth`);if(e){t.resource=e.provider;continue}if(i){t.resource=r(ET,`roles: ${t.sourcePath}`);continue}}if(i){t.resource=r(Dw,`migrations: ${e}`);continue}let a=(t.dialect===`postgres`||t.dialect===`mysql`?OT[t.dialect]:[...OT.postgres,...OT.mysql]).find(e=>n.has(e.provider));a?t.resource=a.provider:t.dialect===`postgres`?t.resource=r(Ow,`migrations: ${e}`):t.dialect===`mysql`&&(t.resource=r(kw,`migrations: ${e}`))}return[...n.values()].sort((e,t)=>e.name.localeCompare(t.name))}const AT=(e,t,n=e)=>({name:e,type:t,provider:n}),jT=AT(`Environment variables`,`secrets`),MT=AT(`GitHub Actions secrets`,`secrets`),NT=AT(`GitHub Actions`,`scheduler`),PT=AT(`Cloud Run`,`hosting`,`Google Cloud Run`),FT=AT(`Cloud Scheduler`,`scheduler`,`Google Cloud Scheduler`),IT=AT(`Vercel`,`hosting`),LT=AT(`Vercel Cron`,`scheduler`),RT=AT(`Netlify`,`hosting`),zT=AT(`Netlify Scheduled Functions`,`scheduler`),BT=AT(`Fly.io`,`hosting`),VT=AT(`AWS Lambda`,`hosting`),HT=AT(`EventBridge schedules`,`scheduler`,`Amazon EventBridge`),UT=AT(`Kubernetes CronJobs`,`scheduler`,`Kubernetes CronJob`),WT=AT(`Kubernetes`,`hosting`);function GT(e){let t={"@hourly":`every hour`,"@daily":`every day at 00:00`,"@midnight":`every day at 00:00`,"@weekly":`every Sunday at 00:00`,"@monthly":`on the 1st of every month at 00:00`,"@yearly":`every year on 1 January at 00:00`,"@annually":`every year on 1 January at 00:00`},n=e.trim();if(t[n])return t[n];let r=n.split(/\s+/);if(r.length!==5)return;let[i=``,a=``,o=``,s=``,c=``]=r,l=e=>/^\*\/(\d+)$/.exec(e)?.[1],u=e=>/^\d+$/.test(e),d=(...e)=>e.every(e=>e===`*`),f=(e,t)=>`${e.padStart(2,`0`)}:${t.padStart(2,`0`)}`;if(i===`*`&&d(a,o,s,c))return`every minute`;if(l(i)&&d(a,o,s,c))return`every ${l(i)} minutes`;if(u(i)&&d(a,o,s,c))return i===`0`?`every hour`:`every hour at :${i.padStart(2,`0`)}`;if(u(i)&&l(a)&&d(o,s,c))return`every ${l(a)} hours`;if(!u(i)||!u(a))return;let p=f(a,i);if(d(o,s,c))return`every day at ${p}`;let m=[`Sunday`,`Monday`,`Tuesday`,`Wednesday`,`Thursday`,`Friday`,`Saturday`,`Sunday`];if(d(o,s)){if(c===`1-5`)return`every weekday at ${p}`;let e=c.split(`,`).map(e=>m[Number(e)]);return e.every(Boolean)?`every ${e.join(` and `)} at ${p}`:void 0}if(u(o)&&d(s,c))return`on day ${o} of every month at ${p}`}function KT(e){let t=/* @__PURE__ */ new Map;for(let n of e.matchAll(/--([\w-]+)(?:[= ]+("[^"]*"|'[^']*'|(?!--)[^\s]+))?/g))t.set(n[1]??``,(n[2]??``).replace(/^["']|["']$/g,``));return t}function qT(e){return(e??``).split(/[,\n]/).map(e=>e.trim()).filter(e=>e.includes(`=`)).map(e=>{let[t=``,n=``]=e.split(`=`,2);return[t.trim(),n.trim()]})}const JT=e=>e.replace(/:[^:/]*$/,``).replace(/^.*\/secrets\//,``),YT=e=>/^projects\/([^/]+)\/secrets\//.exec(e)?.[1],XT=e=>e&&!/[$%{}]/.test(e)?e:void 0,ZT=e=>/^[A-Za-z0-9][\w.-]*$/.test(e);function QT(e){let t=/* @__PURE__ */ new Map;for(let n of e.matchAll(/^[ \t]*(?:export[ \t]+)?([A-Za-z_]\w*)[ \t]*(\?=|::?=|=)[ \t]*(.*)$/gm)){let[,e=``,r,i=``]=n;r===`?=`&&t.has(e)||t.set(e,i.replace(/\s+#.*$/,``).trim().replace(/^(["'])(.*)\1$/,`$2`))}return t}function $T(e,t){let n=e;for(let e=0;e<5&&t.size;e++){let e=n.replace(/\$\{\{\s*env\.(\w+)\s*\}\}|(?<!\$)\$(?:\((\w+)\)|\{(\w+)\}|([A-Za-z_]\w*))/g,(e,n,r,i,a)=>t.get(n??r??i??a)??e);if(e===n)break;n=e}return n}function eE(e){if(!Z(e))return[];let t=(e,t)=>{if(Z(e))for(let[n,r]of Object.entries(e)){let e=Z(r)?r.value:r;(typeof e==`string`||typeof e==`number`)&&t.set(n,String(e))}return t},n=e=>typeof e==`string`?[e]:Array.isArray(e)?e.flatMap(n):[],r=t(e.variables,t(e.env,/* @__PURE__ */ new Map)),i=(t,r=0)=>{let a=n(t.extends).flatMap(t=>{let n=e[t];return Z(n)&&r<5?[i(n,r+1)]:[]}),o={};for(let e of[...a,t])for(let[t,n]of Object.entries(e))o[t]=t===`variables`&&Z(o[t])&&Z(n)?{...o[t],...n}:n;return o};return(Z(e.jobs)?Object.values(e.jobs):Object.entries(e).filter(([e])=>!e.startsWith(`.`)).map(([,e])=>e)).flatMap(e=>{if(!Z(e))return[];let a=i(e),o=t(a.variables,t(a.env,new Map(r))),s=Array.isArray(a.steps)?a.steps:[];for(let e of s)Z(e)&&t(e.env,o);let c=[...n(a.before_script),...n(a.script),...s.flatMap(e=>Z(e)?n(e.run):[])].join(`
375
+ `);return c?[{text:c,vars:o}]:[]})}function tE(e,t,n){let r=(0,uw.parseAllDocuments)(n,{merge:!0}).map(e=>e.toJS());for(let n of r)for(let r of eE(n))lE(e,t,$T(r.text,r.vars));lE(e,t,n)}const nE=e=>/(SECRET|TOKEN|PASSWORD|PASSWD|PRIVATE|API_KEY|_KEY$|CREDENTIAL|DSN|AUTH)/i.test(e),rE=/["'`]((?:claude-(?:opus|sonnet|haiku|fable|instant|\d)[\w.-]*)|(?:gpt-(?:\d|4o)[\w.-]*)|(?:o[134](?:-mini|-pro|-preview)?(?:-\d{4}-\d{2}-\d{2})?)|(?:text-embedding-[\w-]+)|(?:gemini-(?:\d|embedding)[\w.-]*)|whisper-1|dall-e-[23]|gpt-image-1)["'`]/g,iE=/\.(?:[cm]?[jt]sx?|py|go|rb|java|kt|cs|php|rs|swift|ya?ml|toml|json)$/i,aE=/(^|\/)(?:package(?:-lock)?\.json|pnpm-lock\.yaml|yarn\.lock|composer\.lock|[^/]*\.lock|tsconfig[^/]*\.json)$|(^|\/)(?:__tests__|tests?|fixtures?|test-fixtures|docs?|examples?|demo|seeds?|mocks?)\//i,oE={run:`Google Cloud Run`,pubsub:`Google Cloud Pub/Sub`,scheduler:`Google Cloud Scheduler`,secrets:`Google Secret Manager`,storage:`Google Cloud Storage`,firestore:`Google Firestore`};var sE=class{resources=/* @__PURE__ */ new Map;projects=/* @__PURE__ */ new Map;usedIn(e,t){if(!t)return;let n=this.projects.get(e)??/* @__PURE__ */ new Set;n.add(t),this.projects.set(e,n)}contracts=[];#e=/* @__PURE__ */ new Map;resource(e,t){let n=this.resources.get(e.provider);return n?n.evidence.includes(t)||n.evidence.push(t):this.resources.set(e.provider,{...e,evidence:[t]}),e.provider}add(e,t){this.contracts.some(e=>e.kind===t.kind&&e.name===t.name)||this.contracts.push({...t,resource:this.resource(e,`${t.kind}: ${t.name} (${t.sourcePath})`)})}variable(e,t,n,r,i){if(!/^[A-Za-z_][\w-]*$/.test(n))return;let a=this.#e.get(n),o=[.../* @__PURE__ */ new Set([...a?.contract.setIn??[],e.name])];if(a&&a.priority<=t){a.contract.setIn=o;return}let s={kind:`variable`,name:n,sourcePath:r,secret:nE(n),...i,setIn:o,resource:this.resource(e,`variable: ${n} (${r})`)};a&&this.contracts.splice(this.contracts.indexOf(a.contract),1),this.contracts.push(s),this.#e.set(n,{contract:s,priority:t})}};function cE(e,t,n,r,i,a,o){if(!ZT(n))return;let s=XT(o),c=s?{project:s}:{},l=[{relation:`runs`,to:`repo:.`}];for(let[n]of i)e.variable(PT,2,n,t,{secret:nE(n),...c}),l.push({relation:`uses`,to:`variable:${n}`});for(let[n,r]of a){let i=JT(r),a=XT(YT(r))??s;e.variable(oT,1,i,t,{secret:!0,...n===i?{}:{envName:n},...a?{project:a}:{}}),l.push({relation:`uses`,to:`variable:${i}`})}e.add(PT,{kind:`deployment`,name:n,sourcePath:t,...r?{region:r}:{},...c,trigger:`HTTP`,links:l})}function lE(e,t,n){let r=n.replace(/\\\r?\n\s*/g,` `),i=XT(/gcloud\s+config\s+set\s+(?:core\/)?project\s+["']?([^\s'"]+)/.exec(r)?.[1]??/CLOUDSDK_CORE_PROJECT\s*[=:]\s*["']?([^\s'"]+)/.exec(r)?.[1]);for(let t of r.matchAll(/gcloud\s+(?:beta\s+|alpha\s+)?([a-z][\w-]*)\b([^\n]*)/g)){let n=XT(KT(t[2]??``).get(`project`))??i;e.usedIn(`Google Cloud`,n);let r=oE[t[1]??``];r&&e.usedIn(r,n)}for(let t of r.matchAll(/firebase\s[^\n]*?(?:--project|-P)[ =]["']?([^\s'"]+)/g))!/emulators:/.test(t[0])&&!/^demo(-|$)/.test(t[1]??``)&&e.usedIn(`Firebase`,XT(t[1]));for(let n of r.matchAll(/gcloud\s+(?:beta\s+)?run\s+deploy\s+["']?([^\s'"`]+)["']?([^\n]*)/g)){let r=KT(n[2]??``);cE(e,t,n[1]??``,r.get(`region`),qT(r.get(`set-env-vars`)??r.get(`update-env-vars`)),qT(r.get(`set-secrets`)??r.get(`update-secrets`)),r.get(`project`)??i)}for(let n of r.matchAll(/gcloud\s+(?:beta\s+)?scheduler\s+jobs\s+(?:create|update)\s+(http|pubsub|app-engine)\s+["']?([^\s'"`]+)["']?([^\n]*)/g)){let r=n[2]??``,a=KT(n[3]??``),o=a.get(`schedule`);if(!o||!ZT(r))continue;let s=[],c=a.get(`uri`),l;try{l=c?new URL(c).pathname:void 0}catch{}l&&s.push({relation:`calls`,to:`endpoint:${(a.get(`http-method`)??`POST`).toUpperCase()} ${l}`});let u=XT(a.get(`project`))??i;e.add(FT,{kind:`job`,name:r,sourcePath:t,schedule:o,...GT(o)?{scheduleText:GT(o)}:{},...a.get(`time-zone`)?{timeZone:a.get(`time-zone`)}:{},...u?{project:u}:{},runs:n[1]===`pubsub`?`Publishes to Pub/Sub topic ${a.get(`topic`)??``}`.trim():c?`Calls ${c.replace(/^https?:\/\/[^/]+/,``)}`:void 0,links:s})}}const uE=(e,t)=>new RegExp(String.raw`\b${t}\s*=\s*"([^"]*)"`).exec(e)?.[1];function dE(e,t,n){let r=/provider\s+"google(?:-beta)?"\s*\{([\s\S]*?)\n\}/.exec(n)?.[1],i=XT(r?uE(r,`project`):void 0);for(let r of n.matchAll(/resource\s+"(google_cloud_scheduler_job|google_cloud_run_service|google_cloud_run_v2_service|google_secret_manager_secret)"\s+"[\w-]+"\s*\{([\s\S]*?)\n\}/g)){let n=r[2]??``,a=XT(uE(n,`project`))??i,o=a?{project:a}:{};if(r[1]===`google_cloud_scheduler_job`){let r=uE(n,`name`),i=uE(n,`schedule`);if(!r||!i)continue;e.add(FT,{kind:`job`,name:r,sourcePath:t,schedule:i,...GT(i)?{scheduleText:GT(i)}:{},...uE(n,`time_zone`)?{timeZone:uE(n,`time_zone`)}:{},...o})}else if(r[1]===`google_secret_manager_secret`){let r=uE(n,`secret_id`);r&&e.variable(oT,1,r,t,{secret:!0,...o})}else{let r=uE(n,`name`);r&&e.add(PT,{kind:`deployment`,name:r,sourcePath:t,...uE(n,`location`)?{region:uE(n,`location`)}:{},...o,trigger:`HTTP`,links:[{relation:`runs`,to:`repo:.`}]})}}}function fE(e,t,n){if(!Z(n))return;let r=typeof n.name==`string`?n.name:kx(t).replace(/\.ya?ml$/,``),i=Z(n.on)?n.on:Z(n.true)?n.true:null,a=Array.isArray(i?.schedule)?i.schedule.flatMap(e=>Z(e)&&typeof e.cron==`string`?[e.cron]:[]):[];for(let n of a)e.add(NT,{kind:`job`,name:a.length>1?`${r} (${n})`:r,sourcePath:t,schedule:n,...GT(n)?{scheduleText:GT(n)}:{},timeZone:`UTC`,runs:`GitHub Actions workflow ${t}`});let o=Z(n.jobs)?Object.values(n.jobs):[];for(let r of o){let i=Z(r)&&Array.isArray(r.steps)?r.steps:[],a=/* @__PURE__ */ new Map;for(let e of[n.env,Z(r)?r.env:void 0])if(Z(e))for(let[t,n]of Object.entries(e))(typeof n==`string`||typeof n==`number`)&&a.set(t,String(n));for(let n of i){if(!Z(n)||typeof n.uses!=`string`||!n.uses.startsWith(`google-github-actions/deploy-cloudrun`)||!Z(n.with))continue;let r=n.with,i=e=>typeof e==`string`?$T(e,a):void 0;cE(e,t,i(r.service)??``,i(r.region),qT(i(r.env_vars)),qT(i(r.secrets)),i(r.project_id))}}}function pE(e,t,n){for(let r of n){if(!Z(r)||!Z(r.metadata))continue;let n=r.metadata.name;if(typeof n!=`string`)continue;let i=Z(r.spec)?r.spec:{};if(r.kind===`CronJob`&&typeof i.schedule==`string`&&String(r.apiVersion??``).startsWith(`batch/`))e.add(UT,{kind:`job`,name:n,sourcePath:t,schedule:i.schedule,...GT(i.schedule)?{scheduleText:GT(i.schedule)}:{},...typeof i.timeZone==`string`?{timeZone:i.timeZone}:{}});else if(r.kind===`Service`&&String(r.apiVersion??``).startsWith(`serving.knative.dev`)){let a=Z(i.template)&&Z(i.template.spec)&&Array.isArray(i.template.spec.containers)?i.template.spec.containers:[],o=[],s=[];for(let e of a)if(Z(e)&&Array.isArray(e.env))for(let t of e.env){if(!Z(t)||typeof t.name!=`string`)continue;let e=Z(t.valueFrom)&&Z(t.valueFrom.secretKeyRef)?t.valueFrom.secretKeyRef.name:void 0;typeof e==`string`?s.push([t.name,e]):o.push([t.name,``])}let c=(Z(r.metadata.labels)?r.metadata.labels:{})[`cloud.googleapis.com/location`];cE(e,t,n,typeof c==`string`?c:void 0,o,s)}else r.kind===`Deployment`&&String(r.apiVersion??``).startsWith(`apps/`)&&e.add(WT,{kind:`deployment`,name:n,sourcePath:t,links:[{relation:`runs`,to:`repo:.`}]})}}const mE=(e,t)=>new RegExp(String.raw`^\s*${t}\s*=\s*["']([^"']+)["']`,`m`).exec(e)?.[1];async function hE(e,t,n){let r=new sE,i=e=>{let t=e.lastIndexOf(`/`);return t>0?kx(e.slice(0,t)):n};for(let t of e.files){let a=kx(t.path),o=t.path,s=()=>e.readText(t);if(_T(a)){let e=await s();if(e===null)continue;let t=/^\.env\.([\w-]+)\./i.exec(a)?.[1];for(let n of CT(e))r.variable(jT,4,n,o,t?{environments:[t]}:{})}else if(/(^|\/)\.github\/workflows\/[^/]+\.ya?ml$/.test(o)){let e=await s();if(e===null)continue;for(let t of e.matchAll(/\$\{\{\s*secrets\.([A-Za-z_][A-Za-z0-9_]*)\s*\}\}/g))t[1]&&t[1]!==`GITHUB_TOKEN`&&r.variable(MT,3,t[1],o,{secret:!0});let t=(0,uw.parseAllDocuments)(e).map(e=>e.toJS());for(let e of t)fE(r,o,e);tE(r,o,e)}else if(/^cloudbuild\.ya?ml$/.test(a)){let e=await s();if(e===null)continue;for(let t of(0,uw.parseAllDocuments)(e).map(e=>e.toJS()))lE(r,o,(Z(t)&&Array.isArray(t.steps)?t.steps:[]).flatMap(e=>Z(e)&&Array.isArray(e.args)?[`${e.entrypoint===`gcloud`||/cloud-sdk/.test(String(e.name))?`gcloud `:``}${e.args.join(` `)}`]:[]).join(`
376
+ `));lE(r,o,e)}else if(vT(o)||/\.(sh|bash)$/.test(a)||/^(Makefile|justfile|Taskfile\.ya?ml)$/i.test(a)||a===`package.json`&&!o.includes(`/node_modules/`)){let e=await s();if(e===null)continue;/\.ya?ml$/i.test(a)?tE(r,o,e):lE(r,o,$T(e,QT(e)))}else if(a.endsWith(`.tf`)){let e=await s();e!==null&&dE(r,o,e)}else if(a===`.firebaserc`){let e=await s();if(e===null)continue;try{let t=JSON.parse(e);if(Z(t.projects))for(let e of Object.values(t.projects))typeof e==`string`&&r.usedIn(`Firebase`,XT(e))}catch{}}else if(a===`vercel.json`){let e=await s();if(e===null)continue;r.add(IT,{kind:`deployment`,name:i(o),sourcePath:o,links:[{relation:`runs`,to:`repo:.`}]});try{let t=JSON.parse(e);for(let e of Array.isArray(t.crons)?t.crons:[])Z(e)&&typeof e.path==`string`&&typeof e.schedule==`string`&&r.add(LT,{kind:`job`,name:e.path,sourcePath:o,schedule:e.schedule,...GT(e.schedule)?{scheduleText:GT(e.schedule)}:{},timeZone:`UTC`,links:[{relation:`calls`,to:`endpoint:GET ${e.path.split(`?`)[0]}`}]})}catch{}}else if(a===`netlify.toml`){let e=await s();if(e===null)continue;r.add(RT,{kind:`deployment`,name:i(o),sourcePath:o,...mE(e,`publish`)?{path:mE(e,`publish`)}:{},links:[{relation:`runs`,to:`repo:.`}]});for(let t of e.matchAll(/\[functions\.["']?([\w-]+)["']?\]([^[]*)/g)){let e=mE(t[2]??``,`schedule`);e&&r.add(zT,{kind:`job`,name:t[1]??``,sourcePath:o,schedule:e,...GT(e)?{scheduleText:GT(e)}:{},timeZone:`UTC`,runs:`Netlify function ${t[1]}`})}}else if(a===`fly.toml`){let e=await s();if(e===null)continue;let t=mE(e,`app`);t&&r.add(BT,{kind:`deployment`,name:t,sourcePath:o,...mE(e,`primary_region`)?{region:mE(e,`primary_region`)}:{},links:[{relation:`runs`,to:`repo:.`}]})}else if(/^serverless\.ya?ml$/.test(a)){let e=await s();if(e===null)continue;let t=(0,uw.parseAllDocuments)(e)[0]?.toJS();if(!Z(t)||!Z(t.functions))continue;let i=typeof t.service==`string`?t.service:n,a=Z(t.provider)&&typeof t.provider.region==`string`?t.provider.region:void 0;for(let[e,n]of Object.entries(t.functions)){let t=`${i}-${e}`;r.add(VT,{kind:`deployment`,name:t,sourcePath:o,...a?{region:a}:{},links:[{relation:`runs`,to:`repo:.`}]});let s=Z(n)&&Array.isArray(n.events)?n.events:[];for(let e of s){let n=Z(e)?e.schedule:void 0,i=typeof n==`string`?n:Z(n)&&typeof n.rate==`string`?n.rate:void 0;i&&r.add(HT,{kind:`job`,name:`${t} schedule`,sourcePath:o,schedule:i,runs:`AWS Lambda ${t}`})}}}else if(/\.ya?ml$/.test(a)){let e=await s();if(e===null||!/\bkind:\s*(CronJob|Service|Deployment)\b/.test(e))continue;try{pE(r,o,(0,uw.parseAllDocuments)(e).map(e=>e.toJS()))}catch{}}}let a=new Set(t.map(e=>e.provider)),o=a.has(cT.provider)&&!a.has(sT.provider)?cT:sT,s=/* @__PURE__ */ new Map;for(let t of e.files){if(!iE.test(t.path)||aE.test(t.path)||t.size>3e5)continue;let n=await e.readText(t);if(n!==null)for(let e of n.matchAll(rE)){let n=(e[1]??``).replace(/[.-]+$/,``),r=n.startsWith(`claude-`)?Yw:n.startsWith(`gemini-`)?o:Jw,i=s.get(n)??{kind:r,paths:[]};i.paths.includes(t.path)||i.paths.push(t.path),s.set(n,i)}}for(let[e,{kind:t,paths:n}]of s)r.add(t,{kind:`model`,name:e,sourcePath:n[0]??``,modelId:e,calledFrom:n.slice(0,5)});let c=[...r.resources.values()].map(e=>{let t=r.contracts.filter(t=>t.resource===e.provider);return t.length>0&&t.every(e=>typeof e.project==`string`)?{...e,perProject:!0}:e});return{contracts:r.contracts,resources:c,projects:r.projects}}const gE={ts:`TypeScript`,tsx:`TypeScript`,mts:`TypeScript`,cts:`TypeScript`,js:`JavaScript`,jsx:`JavaScript`,mjs:`JavaScript`,cjs:`JavaScript`,py:`Python`,go:`Go`,rb:`Ruby`,php:`PHP`,java:`Java`,kt:`Kotlin`,kts:`Kotlin`,swift:`Swift`,rs:`Rust`,cs:`C#`,fs:`F#`,c:`C`,h:`C`,cc:`C++`,cpp:`C++`,cxx:`C++`,hpp:`C++`,m:`Objective-C`,mm:`Objective-C++`,scala:`Scala`,dart:`Dart`,ex:`Elixir`,exs:`Elixir`,erl:`Erlang`,clj:`Clojure`,hs:`Haskell`,ml:`OCaml`,lua:`Lua`,r:`R`,pl:`Perl`,groovy:`Groovy`,zig:`Zig`,sol:`Solidity`,sql:`SQL`,sh:`Shell`,bash:`Shell`,zsh:`Shell`,ps1:`PowerShell`,tf:`HCL`,vue:`Vue`,svelte:`Svelte`,astro:`Astro`,html:`HTML`,css:`CSS`,scss:`SCSS`,sass:`SCSS`,less:`Less`};function _E(e){let t=/* @__PURE__ */ new Map;for(let n of e){let e=n.path.lastIndexOf(`.`);if(e===-1||e<n.path.lastIndexOf(`/`))continue;let r=gE[n.path.slice(e+1).toLowerCase()];r&&t.set(r,(t.get(r)??0)+1)}return[...t.entries()].sort((e,t)=>t[1]-e[1]||e[0].localeCompare(t[0])).slice(0,5).map(([e])=>e)}const vE=/* @__PURE__ */ new Set([`auth`,`storage`,`realtime`,`_realtime`,`extensions`,`graphql`,`graphql_public`,`supabase_functions`,`supabase_migrations`,`pgsodium`,`pgsodium_masks`,`vault`,`net`,`cron`,`pgbouncer`,`pg_catalog`,`information_schema`]),yE=/^(not|null|default|primary|unique|references|check|constraint|generated|collate|deferrable|initially|identity)$/i;function bE(e){if(!/\.sql$/i.test(e))return!1;let t=e.toLowerCase();return/(^|\/)migrations\//.test(t)||/(^|\/)db\/migrate\//.test(t)}const xE=e=>e.slice(0,e.lastIndexOf(`/`)+1),SE=[[`postgres`,/\b(?:bigserial|serial|jsonb|timestamptz|bytea|tsvector|plpgsql|gen_random_uuid|uuid_generate_v4|create\s+extension|create\s+policy|enable\s+row\s+level\s+security)\b|\$\$|::[a-z_]+/gi],[`mysql`,/\bauto_increment\b|\bengine\s*=|\bunsigned\b|`[^`\n]+`/gi],[`sqlite`,/\bautoincrement\b|\bwithout\s+rowid\b|\bpragma\b/gi]];function CE(e){let t=null,n=0;for(let[r,i]of SE){let a=e.match(i)?.length??0;a>n&&(t=r,n=a)}return t}function wE(e,t){let n=e.toLowerCase();if(!n.endsWith(`.sql`)||bE(e))return!1;let r=n.slice(n.lastIndexOf(`/`)+1);return/seed|fixture|sample|test|demo/.test(r)?!1:/schema|structure/.test(r)||t.has(xE(n))||/(^|\/)docker-entrypoint-initdb\.d\//.test(n)}async function TE(e){let t=/* @__PURE__ */ new Map,n=EE(),r=e.files.filter(e=>bE(e.path)),i=new Set(r.flatMap(e=>{let t=/^(.*\/)?(migrations|db\/migrate)\//.exec(e.path.toLowerCase());return t?[t[1]??``]:[]})),a=e.files.filter(e=>wE(e.path,i)).sort((e,t)=>e.path<t.path?-1:1);r.sort((e,t)=>{let n=e.path.slice(e.path.lastIndexOf(`/`)+1),r=t.path.slice(t.path.lastIndexOf(`/`)+1);return n<r?-1:n>r?1:e.path<t.path?-1:1});let o=/* @__PURE__ */ new Map,s=/* @__PURE__ */ new Map;for(let i of[...a,...r]){let r=await e.readText(i);if(r===null)continue;let a=CE(r);a&&(o.set(i.path,a),s.set(a,(s.get(a)??0)+1));for(let a of NE(r))try{VE(a,i.path,t,e.warnings),jE(a,i.path,n)}catch(t){e.warnings.push(`${i.path}: could not read statement "${ZE(a)}" (${Mx(t)})`)}}let c=[...s.entries()].sort((e,t)=>t[1]-e[1])[0]?.[0]??null,l=e=>o.get(e)??c;return{tables:[...t.values()].filter(e=>!vE.has(e.schema)).map(e=>{let t=e.schema===`public`?e.table:`${e.schema}.${e.table}`;return{kind:`table`,name:t,sourcePath:e.sourcePath,table:t,columns:e.columns,dialect:l(e.sourcePath)}}),objects:ME(n,l)}}const EE=()=>({functions:/* @__PURE__ */ new Map,roleEnums:/* @__PURE__ */ new Map,cronJobs:/* @__PURE__ */ new Map});function DE(e){let{schema:t,table:n}=zE(e);return{schema:t,name:t===`public`?n:`${t}.${n}`}}function OE(e,t){let n=0;for(let r=t;r<e.length;r++){let i=e[r];if(i===`(`)n++;else if(i===`)`&&(n--,n===0))return[e.slice(t+1,r),e.slice(r+1)]}return null}const kE=e=>e.replace(/\s+/g,` `).trim(),AE=()=>String.raw`((?:${LE}\s*(?:\([^)]*\))?\s*,?\s*)+)`;function jE(e,t,n){let r=/^create\s+(?:or\s+replace\s+)?function\s+/i.exec(e);if(r){let i=e.indexOf(`(`,r[0].length),a=i>0?OE(e,i):null;if(!a)return;let{schema:o,name:s}=DE(e.slice(r[0].length,i));if(vE.has(o))return;let c=/^\s*returns\s+(setof\s+\S+|table\s*\([\s\S]*?\)(?=\s)|[\w."[\] ]+?)\s+(?:language|as|security|set|stable|immutable|volatile|strict|parallel|cost|leakproof|called|begin)\b/i.exec(a[1])?.[1];if(!c||/^(event_)?trigger$/i.test(c.trim())){n.functions.delete(s);return}let l=n.functions.get(s);n.functions.set(s,{name:s,sourcePath:t,arguments:`(${kE(a[0]).slice(0,300)})`,returns:kE(c),definer:/\bsecurity\s+definer\b/i.test(a[1].split(/\$\w*\$/)[0]??``),callers:l?.callers??/* @__PURE__ */ new Set});return}let i=new RegExp(String.raw`^drop\s+function\s+(?:if\s+exists\s+)?${AE()}`,`i`).exec(e);if(i?.[1]){for(let e of i[1].split(/,(?![^(]*\))/))n.functions.delete(DE(e.replace(/\(.*$/s,``)).name);return}let a=new RegExp(String.raw`^(grant|revoke)\s+execute\s+on\s+function\s+${AE()}\s+(?:to|from)\s+(.+)$`,`is`).exec(e);if(a?.[1]&&a[2]&&a[a.length-1]){let e=(a[a.length-1]??``).split(`,`).map(e=>e.trim().toLowerCase()).filter(e=>e&&e!==`public`);for(let t of a[2].split(/,(?![^(]*\))/)){let r=n.functions.get(DE(t.replace(/\(.*$/s,``)).name);if(r)for(let t of e)a[1].toLowerCase()===`grant`?r.callers.add(t):r.callers.delete(t)}return}let o=new RegExp(String.raw`^create\s+type\s+${LE}\s+as\s+enum\s*\(([^)]*)\)`,`i`).exec(e);if(o?.[1]&&/role/i.test(o[1])){n.roleEnums.set(zE(o[1]).table,{values:[...(o[2]??``).matchAll(/'((?:[^']|'')*)'/g)].map(e=>(e[1]??``).replace(/''/g,`'`)),sourcePath:t});return}let s=new RegExp(String.raw`^alter\s+type\s+${LE}\s+add\s+value\s+(?:if\s+not\s+exists\s+)?'((?:[^']|'')*)'`,`i`).exec(e);if(s?.[1]){let e=n.roleEnums.get(zE(s[1]).table),t=(s[2]??``).replace(/''/g,`'`);e&&!e.values.includes(t)&&e.values.push(t)}else{for(let r of e.matchAll(/cron\.schedule\s*\(\s*'([^']*)'\s*,\s*(?:'([^']*)'\s*,\s*)?(\$\w*\$[\s\S]*?\$\w*\$|'(?:[^']|'')*')/gi)){let[e,i]=r[2]===void 0?[null,r[1]]:[r[1],r[2]];if(!i)continue;let a=/select\s+([\w."]+)\s*\(/i.exec(r[3]??``)?.[1]??null;n.cronJobs.set(e??`pg_cron ${i}`,{schedule:i,sourcePath:t,calls:a?DE(a).name:null})}for(let t of e.matchAll(/cron\.unschedule\s*\(\s*'([^']*)'/gi))n.cronJobs.delete(t[1]??``)}}function ME(e,t){let n=[];for(let r of e.functions.values()){let e=[...r.callers].sort();n.push({kind:`function`,name:r.name,sourcePath:r.sourcePath,dialect:t(r.sourcePath),arguments:r.arguments,returns:r.returns,access:(e.length?`Callable by ${e.join(`, `)}`:`Not granted to any app role`)+(r.definer?`; runs with its owner's rights`:``)})}let r=/* @__PURE__ */ new Map;for(let t of e.roleEnums.values())for(let e of t.values)r.set(e,(r.get(e)??0)+1);for(let[i,a]of e.roleEnums)for(let e of a.values)n.push({kind:`role`,name:(r.get(e)??0)>1?`${e} (${i})`:e,sourcePath:a.sourcePath,dialect:t(a.sourcePath),definedIn:i});for(let[t,r]of e.cronJobs)n.push({kind:`job`,name:t,sourcePath:r.sourcePath,resource:`pg_cron`,schedule:r.schedule,...r.calls?{links:[{relation:`calls`,to:`function:${r.calls}`}]}:{}});return n}function NE(e){let t=[],n=``,r=0;for(;r<e.length;){let i=e[r],a=e[r+1];if(i===`-`&&a===`-`){let t=e.indexOf(`
377
+ `,r);r=t===-1?e.length:t,n+=` `}else if(i===`/`&&a===`*`){let t=1;for(r+=2;r<e.length&&t>0;)e.startsWith(`/*`,r)?(t++,r+=2):e.startsWith(`*/`,r)?(t--,r+=2):r++;n+=` `}else if(i===`'`||i===`"`){let t=r+1;for(;t<e.length;)if(e[t]===i){if(e[t+1]===i)t+=2;else break}else t++;n+=e.slice(r,t+1),r=t+1}else{if(i===`$`){let t=/^\$[A-Za-z_]?[A-Za-z0-9_]*\$/.exec(e.slice(r,r+64))?.[0];if(t){let i=e.indexOf(t,r+t.length),a=i===-1?e.length:i+t.length;n+=e.slice(r,a),r=a;continue}}i===`;`?(n.trim()&&t.push(n.trim()),n=``,r++):(n+=i,r++)}}return n.trim()&&t.push(n.trim()),t.map(e=>e.replace(/\s+/g,` `))}function PE(e){let t=[],n=0,r=null,i=0;for(let a=0;a<e.length;a++){let o=e[a];r?o===r&&(r=null):o===`'`||o===`"`?r=o:o===`(`?n++:o===`)`?n--:o===`,`&&n===0&&(t.push(e.slice(i,a).trim()),i=a+1)}return t.push(e.slice(i).trim()),t.filter(Boolean)}function FE(e){let t=[],n=0;for(;n<e.length;){let r=e[n];if(/\s/.test(r)){n++;continue}if(r===`(`){let r=0,i=n,a=null;for(;i<e.length;i++){let t=e[i];if(a)t===a&&(a=null);else if(t===`'`||t===`"`)a=t;else if(t===`(`)r++;else if(t===`)`&&--r===0)break}t.push(e.slice(n,i+1)),n=i+1;continue}let i=n,a=null;for(;i<e.length;i++){let t=e[i];if(a)t===a&&(a=null);else if(t===`'`||t===`"`)a=t;else if(/\s/.test(t)||t===`(`)break}t.push(e.slice(n,i)),n=i}return t}const IE=String.raw`(?:"(?:[^"]|"")+"|[A-Za-z_][\w$]*)`,LE=String.raw`(${IE}(?:\s*\.\s*${IE})?)`;function RE(e){let t=e.trim();return t.startsWith(`"`)?t.slice(1,-1).replace(/""/g,`"`):t.toLowerCase()}function zE(e){let t=e.match(new RegExp(IE,`g`))??[e];return t.length>=2?{schema:RE(t[0]??``),table:RE(t[1]??``)}:{schema:`public`,table:RE(t[0]??e)}}function BE(e,t){return`${e}.${t}`}function VE(e,t,n,r){if(/^create\s+(?:(?:global|local)\s+)?(?:temp(?:orary)?\s+|unlogged\s+)?table\b/i.test(e)){HE(e,t,n,r);return}let i=new RegExp(String.raw`^alter\s+table\s+(?:if\s+exists\s+)?(?:only\s+)?${LE}\s+(.+)$`,`i`).exec(e);if(i?.[1]&&i[2]){YE(zE(i[1]),i[2],t,n,r);return}let a=/^drop\s+table\s+(?:if\s+exists\s+)?(.+?)(?:\s+(?:cascade|restrict))?$/i.exec(e);if(a?.[1])for(let e of PE(a[1])){let{schema:t,table:r}=zE(e);n.delete(BE(t,r))}}function HE(e,t,n,r){let i=new RegExp(String.raw`^create\s+(?:(?:global|local)\s+)?(?:temp(?:orary)?\s+|unlogged\s+)?table\s+(?:if\s+not\s+exists\s+)?${LE}\s*\(`,`i`).exec(e);if(!i?.[1]){r.push(`${t}: skipped a create table statement it couldn't read: "${ZE(e)}"`);return}let{schema:a,table:o}=zE(i[1]),s=i[0].length-1,c=UE(e,s);if(c===-1){r.push(`${t}: unbalanced parentheses in create table ${o}`);return}let l=BE(a,o);if(n.has(l)&&/\bif\s+not\s+exists\b/i.test(e.slice(0,s)))return;let u={schema:a,table:o,sourcePath:t,columns:[]};for(let i of PE(e.slice(s+1,c))){if(/^(constraint|primary\s+key|unique|foreign\s+key|check|exclude|like)\b/i.test(i)){JE(u,i,n);continue}let e=WE(i,n);e?u.columns.push(e):r.push(`${t}: skipped column definition "${ZE(i)}" in ${o}`)}n.set(l,u)}function UE(e,t){let n=0,r=null;for(let i=t;i<e.length;i++){let t=e[i];if(r)t===r&&(r=null);else if(t===`'`||t===`"`)r=t;else if(t===`(`)n++;else if(t===`)`&&--n===0)return i}return-1}function WE(e,t){let n=FE(e),r=n[0];if(!r||n.length<2)return null;let i=1,a=[];for(;i<n.length&&!yE.test(n[i]??``);)a.push(n[i]),i++;if(a.length===0)return null;let o={name:RE(r),type:a.join(` `).replace(/\s+\(/g,`(`).toLowerCase(),required:!1};return GE(o,n.slice(i),t),o}function GE(e,t,n){for(let r=0;r<t.length;r++){let i=t[r]?.toLowerCase(),a=t[r+1]?.toLowerCase();if(i===`not`&&a===`null`)e.required=!0,r++;else if(i===`primary`&&a===`key`)e.primaryKey=!0,e.required=!0,r++;else if(i===`unique`)e.unique=!0;else if(i==="default"){let n=[];for(;r+1<t.length&&!yE.test(t[r+1]??``);)n.push(t[r+1]),r++;n.length>0&&(e.default=KE(n))}else if(i===`references`){let i=t[r+1];if(!i)continue;let a=t[r+2]?.startsWith(`(`)?t[r+2]:void 0;e.references=qE(i,a,n),r+=a?2:1}}}function KE(e){return e.join(` `).replace(/\s+\(/g,`(`)}function qE(e,t,n){let{schema:r,table:i}=zE(e),a=r===`public`?i:`${r}.${i}`,o=t?RE(t.slice(1,-1).split(`,`)[0]??``):null;return o||=n.get(BE(r,i))?.columns.find(e=>e.primaryKey)?.name??`id`,`${a}.${o}`}function JE(e,t,n){let r=t.replace(new RegExp(String.raw`^constraint\s+${IE}\s+`,`i`),``),i=e=>(e??``).split(`,`).map(e=>RE(e)).filter(Boolean),a=/^primary\s+key\s*\(([^)]*)\)/i.exec(r);if(a){for(let t of i(a[1])){let n=e.columns.find(e=>e.name===t);n&&(n.primaryKey=!0,n.required=!0)}return}let o=/^unique\s*(?:nulls\s+(?:not\s+)?distinct\s*)?\(([^)]*)\)/i.exec(r);if(o){let t=i(o[1]),n=t.length===1?e.columns.find(e=>e.name===t[0]):void 0;n&&(n.unique=!0);return}let s=new RegExp(String.raw`^foreign\s+key\s*\(([^)]*)\)\s*references\s+${LE}\s*(\([^)]*\))?`,`i`).exec(r);if(s?.[2]){let t=i(s[1]),r=s[3]?i(s[3].slice(1,-1)):[];t.forEach((t,i)=>{let a=e.columns.find(e=>e.name===t);if(!a)return;let o=r[i];a.references=qE(s[2],o?`(${o})`:void 0,n)})}}function YE(e,t,n,r,i){let a=r.get(BE(e.schema,e.table));if(!a){!vE.has(e.schema)&&/\b(add|drop|alter|rename)\s+column\b/i.test(t)&&i.push(`${n}: alter table ${e.table} before any create table for it, skipped`);return}let o=new RegExp(String.raw`^rename\s+to\s+(${IE})$`,`i`).exec(t);if(o?.[1]){r.delete(BE(a.schema,a.table)),a.table=RE(o[1]),r.set(BE(a.schema,a.table),a);return}let s=new RegExp(String.raw`^rename\s+(?:column\s+)?(${IE})\s+to\s+(${IE})$`,`i`).exec(t);if(s?.[1]&&s[2]){let e=a.columns.find(e=>e.name===RE(s[1]));e&&(e.name=RE(s[2]))}else for(let e of PE(t)){let t=/^add\s+(?:column\s+)?(?:if\s+not\s+exists\s+)?(.+)$/i.exec(e);if(t?.[1]&&!/^add\s+(constraint|primary|unique|foreign|check|exclude)\b/i.test(e)){let o=WE(t[1],r);if(!o){i.push(`${n}: skipped "${ZE(e)}" on ${a.table}`);continue}a.columns.some(e=>e.name===o.name)||a.columns.push(o);continue}let o=/^add\s+(.+)$/i.exec(e);if(o?.[1]){JE(a,o[1],r);continue}let s=new RegExp(String.raw`^drop\s+(?:column\s+)?(?:if\s+exists\s+)?(${IE})`,`i`).exec(e);if(s?.[1]&&!/^drop\s+constraint\b/i.test(e)){let e=RE(s[1]);a.columns=a.columns.filter(t=>t.name!==e);continue}let c=new RegExp(String.raw`^alter\s+(?:column\s+)?(${IE})\s+(.+)$`,`i`).exec(e);if(c?.[1]&&c[2]){let e=a.columns.find(e=>e.name===RE(c[1]));e&&XE(e,c[2])}}}function XE(e,t){if(/^set\s+not\s+null$/i.test(t))e.required=!0;else if(/^drop\s+not\s+null$/i.test(t))e.required=!!e.primaryKey;else if(/^drop\s+default$/i.test(t))delete e.default;else{let n=/^set\s+default\s+(.+)$/i.exec(t);if(n?.[1]){e.default=KE(FE(n[1]));return}let r=/^(?:set\s+data\s+)?type\s+(.+?)(?:\s+(?:using|collate)\s+.*)?$/i.exec(t);r?.[1]&&(e.type=r[1].replace(/\s+\(/g,`(`).toLowerCase())}}function ZE(e){return e.length>60?`${e.slice(0,57)}...`:e}const QE=[`GET`,`POST`,`PUT`,`PATCH`,`DELETE`],$E=/^(openapi|swagger)([.-][\w.-]*)?\.(json|ya?ml)$/i,eD=/\.(json|ya?ml)$/i;async function tD(e){let t=[];for(let n of e.files){let r=$E.test(kx(n.path));if(!r&&!eD.test(n.path)||!r&&(n.size>1048576||/(^|\/)[^/]*lock[^/]*$/i.test(n.path)))continue;let i=await e.readText(n,r?10485760:void 0);if(i===null||!r&&!/^\s*["']?(openapi|swagger)["']?\s*:/m.test(i))continue;let a;try{a=/\.json$/i.test(n.path)?JSON.parse(i):(0,uw.parse)(i)}catch(t){e.warnings.push(`${n.path}: OpenAPI file could not be parsed (${Mx(t)})`);continue}!Z(a)||typeof a.openapi!=`string`&&typeof a.swagger!=`string`?r&&e.warnings.push(`${n.path}: no top-level openapi or swagger version, skipped`):t.push(...nD(a,n.path,e.warnings))}return t}function nD(e,t,n){let r=typeof e.swagger==`string`,i=new rD(e,t,n),a=r?e.securityDefinitions:aD(e.components)?.securitySchemes,o=Z(a)?a:{},s=Z(e.paths)?e.paths:{},c=[];for(let[n,a]of Object.entries(s)){let s=i.resolve(a);if(s)for(let a of QE){let l=aD(s[a.toLowerCase()]);if(!l)continue;let u=[...Array.isArray(s.parameters)?s.parameters:[],...Array.isArray(l.parameters)?l.parameters:[]],d=l.security??e.security;c.push({kind:`endpoint`,name:Nx(l.summary)?.trim()||Nx(l.operationId)||`${a} ${n}`,sourcePath:t,method:a,path:n,auth:yD(d,o,i),request:r?uD(u,l,e,i):sD(l.requestBody,i),responses:dD(l,e,r,i)})}}return c}var rD=class{#e;#t;#n;#r=/* @__PURE__ */ new Set;constructor(e,t,n){this.#e=e,this.#t=t,this.#n=n}resolve(e){let t=e;for(let e=0;e<8;e++){if(!Z(t))return null;let e=t.$ref;if(typeof e!=`string`)return t;t=this.#i(e)}return null}refName(e){if(!Z(e)||typeof e.$ref!=`string`)return null;let t=e.$ref.slice(e.$ref.lastIndexOf(`/`)+1);return t?iD(t):null}#i(e){if(!e.startsWith(`#/`))return this.#r.has(e)||(this.#r.add(e),this.#n.push(`${this.#t}: external $ref "${e}" not followed`)),null;let t=this.#e;for(let n of e.slice(2).split(`/`)){if(!Z(t))break;t=t[iD(n)]}return t===void 0&&!this.#r.has(e)&&(this.#r.add(e),this.#n.push(`${this.#t}: $ref "${e}" points at nothing`)),t}};function iD(e){return decodeURIComponent(e).replace(/~1/g,`/`).replace(/~0/g,`~`)}function aD(e){return Z(e)?e:null}function oD(e){if(!Z(e))return null;let t=Object.entries(e).filter(e=>Z(e[1]));return t.find(([e])=>e===`application/json`)??t.find(([e])=>/json/.test(e))??t[0]??null}function sD(e,t){let n=t.resolve(e),r=n?oD(n.content):null;return r?cD(r[0],r[1],t):null}function cD(e,t,n){let r=t.schema;return{contentType:e,fields:hD(r,n),example:lD(t,n)??vD(r,n,0)}}function lD(e,t){if(e.example!==void 0)return e.example;if(Z(e.examples)){let n=t.resolve(Object.values(e.examples)[0]);if(n&&n.value!==void 0)return n.value}}function uD(e,t,n,r){let i=e.map(e=>r.resolve(e)).filter(e=>e!==null),a=pD(t.consumes)??pD(n.consumes),o=i.find(e=>e.in===`body`);if(o)return{contentType:a??`application/json`,fields:hD(o.schema,r),example:vD(o.schema,r,0)};let s=i.filter(e=>e.in===`formData`);if(s.length===0)return null;let c=s.map(e=>({name:Nx(e.name)??``,type:_D(e,r),required:e.required===!0,...gD(e)}));return{contentType:a??`application/x-www-form-urlencoded`,fields:c,example:Object.fromEntries(s.map(e=>[Nx(e.name)??``,vD(e,r,1)]))}}function dD(e,t,n,r){if(!Z(e.responses))return[];let i=pD(e.produces)??pD(t.produces)??`application/json`,a=[];for(let[t,o]of Object.entries(e.responses)){let e=r.resolve(o);if(!e)continue;let s=null;if(n){if(e.schema!==void 0){let t=aD(e.examples);s={contentType:i,fields:hD(e.schema,r),example:t?.[i]??vD(e.schema,r,0)}}}else{let t=oD(e.content);t&&(s=cD(t[0],t[1],r))}a.push({status:fD(t),description:Nx(e.description)??``,body:s})}return a}function fD(e){let t=e.replace(/x/gi,`0`),n=Number.parseInt(t,10);return Number.isNaN(n)?0:n}function pD(e){return Array.isArray(e)&&typeof e[0]==`string`?e[0]:void 0}function mD(e,t,n=0){let r=t.resolve(e);if(!r||n>8)return r;if(Array.isArray(r.allOf)){let e={},i=[];for(let a of r.allOf){let r=mD(a,t,n+1);r&&(Z(r.properties)&&Object.assign(e,r.properties),Array.isArray(r.required)&&i.push(...r.required.filter(e=>typeof e==`string`)))}return Z(r.properties)&&Object.assign(e,r.properties),Array.isArray(r.required)&&i.push(...r.required.filter(e=>typeof e==`string`)),{...r,type:`object`,properties:e,required:i}}let i=Array.isArray(r.oneOf)?r.oneOf:Array.isArray(r.anyOf)?r.anyOf:null;return i&&i.length>0&&!r.properties?mD(i[0],t,n+1):r}function hD(e,t){let n=mD(e,t);if(n?.type===`array`&&(n=mD(n.items,t)),!n||!Z(n.properties))return[];let r=new Set(Array.isArray(n.required)?n.required:[]);return Object.entries(n.properties).map(([e,n])=>{let i=mD(n,t)??{};return{name:e,type:_D(n,t),required:r.has(e),...gD(i)}})}function gD(e){let t={},n=Nx(e.description)?.trim();return n&&(t.description=n),Array.isArray(e.enum)&&(t.values=e.enum.map(e=>String(e))),t}function _D(e,t,n=0){let r=t.refName(e),i=mD(e,t);if(!i)return r??`unknown`;let a=Array.isArray(i.type)?i.type.filter(e=>e!==`null`).join(` | `):Nx(i.type);return a===`array`?n>8?`array`:`${_D(i.items,t,n+1)}[]`:r&&(a===`object`||a===void 0)?r:Nx(i.format)??a??(i.properties?`object`:`unknown`)}function vD(e,t,n){let r=mD(e,t);if(!r||n>8)return null;if(r.example!==void 0)return r.example;if(Array.isArray(r.enum)&&r.enum.length>0)return r.enum[0];let i=Array.isArray(r.type)?r.type.find(e=>e!==`null`):r.type;if(i===`object`||i===void 0&&Z(r.properties)){let e=Z(r.properties)?r.properties:{};return Object.fromEntries(Object.entries(e).map(([e,r])=>[e,vD(r,t,n+1)]))}switch(i){case`array`:return[vD(r.items,t,n+1)];case`string`:return`string`;case`integer`:case`number`:return 0;case`boolean`:return!1;default:return null}}function yD(e,t,n){if(!Array.isArray(e)||e.length===0)return null;let r=[];for(let i of e){if(!Z(i))continue;let e=Object.keys(i);e.length===0?r.push(`none`):r.push(e.map(e=>bD(e,n.resolve(t[e]))).join(` + `))}let i=[...new Set(r)];return i.length===0||i.length===1&&i[0]===`none`?null:i.map(e=>e===`none`?`no auth`:e).join(` or `)}function bD(e,t){if(!t)return e;switch(Nx(t.type)?.toLowerCase()){case`http`:{let e=Nx(t.scheme)?.toLowerCase();if(e===`bearer`){let e=Nx(t.bearerFormat);return e?`Bearer token (${e})`:`Bearer token`}return e===`basic`?`Basic auth`:`HTTP ${e??`auth`}`}case`basic`:return`Basic auth`;case`apikey`:return`apikey ${Nx(t.in)??`header`} ${Nx(t.name)??e}`;case`oauth2`:return`OAuth2`;case`openidconnect`:return`OpenID Connect`;case`mutualtls`:return`Mutual TLS`;default:return e}}const xD=[`readme.md`,`readme.mdx`,`readme.markdown`,`readme.txt`,`readme`];async function SD(e){let t=e.files.find(e=>!e.path.includes(`/`)&&xD.includes(e.path.toLowerCase()));if(!t)return null;let n=await e.readText(t);return{path:t.path,oneLiner:n===null?null:CD(n)}}function CD(e){let t=e.replace(/\r\n/g,`
377
378
  `).replace(/^---\n[\s\S]*?\n---\n/,``).replace(/<!--[\s\S]*?-->/g,``).replace(/^(```|~~~)[\s\S]*?^\1.*$/gm,``);for(let e of t.split(/\n\s*\n/)){let t=e.split(`
378
- `).map(e=>e.trim()).filter(Boolean),n=t[0];if(!n||/^(#|=+$|-+$|\||[-*+] |\d+\. |>|<|\[!\[|!\[)/.test(n)||/^ {4}|^\t/.test(e))continue;let r=vD(t.join(` `));if(!(r.length<15||!/[a-z]/i.test(r)))return yD(/^.+?[.!?](?=\s+["'([]?[A-Z]|\s*$)/.exec(r)?.[0]??r,200)}return null}function vD(e){return e.replace(/!\[[^\]]*\]\([^)]*\)/g,``).replace(/\[([^\]]*)\]\([^)]*\)/g,`$1`).replace(/\[([^\]]*)\]\[[^\]]*\]/g,`$1`).replace(/<[^>]+>/g,``).replace(/`([^`]*)`/g,`$1`).replace(/(\*\*|__)(.*?)\1/g,`$2`).replace(/(^|\W)[*_](\S(?:.*?\S)?)[*_](?=\W|$)/g,`$1$2`).replace(/\s+/g,` `).trim()}function yD(e,t){if(e.length<=t)return e;let n=e.slice(0,t-1),r=n.lastIndexOf(` `);return`${(r>t/2?n.slice(0,r):n).trimEnd()}…`}const bD=[`GET`,`POST`,`PUT`,`PATCH`,`DELETE`],xD=/\.(?:[cm]?[jt]sx?)$/i,SD=/(^|\/)(?:__tests__|tests?|spec|e2e|fixtures?|test-fixtures|mocks?|examples?|dist|build|\.next)\//i,CD=/\.(?:test|spec)\.[cm]?[jt]sx?$|(^|\/)test_[^/]*\.py$|_test\.(?:py|go)$/i;function wD(e){let t=e.replace(/<(?:[\w]+:)?([A-Za-z_]\w*)>/g,`{$1}`).replace(/:([A-Za-z_]\w*)\??/g,`{$1}`).replace(/\[\.\.\.([\w]+)\]/g,`{$1}`).replace(/\[([\w]+)\]/g,`{$1}`).replace(/\{\{([\w]+)\}\}/g,`{$1}`);return t.startsWith(`/`)||(t=`/${t}`),t=t.replace(/\/{2,}/g,`/`),t.length>1?t.replace(/\/$/,``):t}const TD=(...e)=>wD(e.filter(Boolean).join(`/`)),ED=(e,t,n,r,i={})=>({kind:`endpoint`,name:`${e} ${t}`,sourcePath:n,method:e,path:t,auth:null,request:null,responses:[],from:r,...i}),DD=(e,t)=>`${e} ${wD(t).replace(/\{[^}]*\}/g,`{}`).toLowerCase()}`,OD=String.raw`(['"\`])([^'"\`\n]*)['"\`]`;function kD(e,t,n){if(!t.startsWith(`.`))return;let r=e.slice(0,e.lastIndexOf(`/`)+1),i=[];for(let e of`${r}${t}`.split(`/`))e===`..`?i.pop():e!==`.`&&e!==``&&i.push(e);let a=i.join(`/`).replace(/\.[cm]?js$/,``);for(let e of[``,`.ts`,`.tsx`,`.js`,`.mjs`,`.cjs`,`/index.ts`,`/index.js`])if(n.has(a+e))return a+e}function AD(e,t,n){let r=/from\s+['"](?:express|fastify|hono|koa|@koa\/router|koa-router|@hono\/[\w-]+)['"]|require\(\s*['"](?:express|fastify|koa|@koa\/router|koa-router)['"]\s*\)/.test(t),i=/from\s+['"]@nestjs\/common['"]/.test(t);if(!r&&!i)return null;let a={path:e,routes:[],mounts:[],imports:/* @__PURE__ */ new Map};for(let r of t.matchAll(/import\s+(?:(\w+)|\*\s+as\s+(\w+)|\{([^}]*)\})\s+from\s+['"]([^'"]+)['"]/g)){let t=kD(e,r[4]??``,n);if(!t)continue;let i=r[1]??r[2]??``;i&&a.imports.set(i,t);for(let e of(r[3]??``).split(`,`))a.imports.set(e.trim().split(/\s+as\s+/).pop()??``,t)}for(let r of t.matchAll(/(?:const|let|var)\s+(\w+)\s*=\s*require\(\s*['"]([^'"]+)['"]\s*\)/g)){let t=kD(e,r[2]??``,n);t&&r[1]&&a.imports.set(r[1],t)}if(r){let r=/* @__PURE__ */ new Set([`app`,`router`,`server`,`fastify`]);for(let e of t.matchAll(/(?:const|let|var)\s+(\w+)\s*(?::\s*[\w<>.]+)?\s*=\s*(?:express\s*\(|express\.Router\s*\(|Router\s*\(|fastify\s*\(|Fastify\s*\(|new\s+(?:Hono|Router|KoaRouter)\s*\(|createRouter\s*\()/g))e[1]&&r.add(e[1]);let i=[...r].join(`|`);for(let e of t.matchAll(new RegExp(String.raw`\b(?:${i})\s*\.\s*(get|post|put|patch|delete)\s*\(\s*${OD}`,`g`))){let t=e[3]??``;(t.startsWith(`/`)||t===``)&&a.routes.push({method:(e[1]??`get`).toUpperCase(),path:t})}for(let e of t.matchAll(new RegExp(String.raw`\b(?:${i})\s*\.\s*route\s*\(\s*${OD}\s*\)((?:\s*\.\s*(?:get|post|put|patch|delete|all)\s*\([^)]*\)?)+)`,`g`)))for(let t of(e[3]??``).matchAll(/\.\s*(get|post|put|patch|delete)\s*\(/g))a.routes.push({method:(t[1]??`get`).toUpperCase(),path:e[2]??``});for(let r of t.matchAll(new RegExp(String.raw`\b(?:${i})\s*\.\s*(?:use|route)\s*\(\s*${OD}\s*,\s*(?:require\(\s*['"]([^'"]+)['"]\s*\)|(\w+))`,`g`))){let t=r[3]?kD(e,r[3],n):a.imports.get(r[4]??``);t&&a.mounts.push({prefix:r[2]??``,target:t})}for(let e of t.matchAll(/\.register\s*\(\s*(\w+)\s*,\s*\{[^}]*prefix\s*:\s*(['"`])([^'"`]*)\2/g)){let t=a.imports.get(e[1]??``);t&&a.mounts.push({prefix:e[3]??``,target:t})}}if(i)for(let e of t.split(/(?=@Controller\s*\()/).slice(1)){let t=/@Controller\s*\(\s*(?:(['"`])([^'"`]*)\1|\{[^}]*path\s*:\s*(['"`])([^'"`]*)\3)?/.exec(e);for(let n of e.matchAll(/@(Get|Post|Put|Patch|Delete)\s*\(\s*(?:(['"`])([^'"`]*)\2)?\s*\)/g))a.routes.push({method:(n[1]??`Get`).toUpperCase(),path:TD(t?.[2]??t?.[4]??``,n[3]??``)})}return a}function jD(e,t){let n=/(?:^|\/)app\/(.*)\/route\.[cm]?[jt]sx?$/.exec(e),r=/(?:^|\/)pages\/(api\/.*?)(?:\/index)?\.[cm]?[jt]sx?$/.exec(e),i=n?.[1]??r?.[1];if(i===void 0)return[];let a=wD(i.split(`/`).filter(e=>!/^\(.*\)$/.test(e)&&!e.startsWith(`@`)).join(`/`)),o=n?bD.filter(e=>new RegExp(String.raw`export\s+(?:async\s+)?(?:function\s+${e}\b|const\s+${e}\b)|export\s*\{[^}]*\b${e}\b`).test(t)):[...new Set([...t.matchAll(/req\.method\s*={2,3}\s*['"](\w+)['"]/g)].map(e=>(e[1]??``).toUpperCase()))].filter(e=>bD.includes(e));return(o.length?o:[`GET`]).map(t=>ED(t,a,e,`code`))}function MD(e){let t=new Map(e.map(e=>[e.path,e])),n=(t,r=0)=>{if(r>4)return``;for(let i of e)for(let e of i.mounts)if(e.target===t)return TD(n(i.path,r+1),e.prefix);return``},r=[];for(let e of t.values()){let t=n(e.path);for(let n of e.routes)r.push(ED(n.method,TD(t,n.path),e.path,`code`))}return r}function ND(e,t){if(!/\b(?:fastapi|flask)\b/i.test(t))return null;let n={path:e,module:e.replace(/\.py$/,``).replace(/\/__init__$/,``),routes:[],prefixes:/* @__PURE__ */ new Map,includes:[],imports:/* @__PURE__ */ new Map},r=e.includes(`/`)?e.slice(0,e.lastIndexOf(`/`)):``,i=e=>{let t=/^\.+/.exec(e)?.[0].length??0,n=r;for(let e=1;e<t;e++)n=n.slice(0,n.lastIndexOf(`/`));let i=e.slice(t).replace(/\./g,`/`);return t?[n,i].filter(Boolean).join(`/`):i};for(let e of t.matchAll(/^from\s+([\w.]+)\s+import\s+([^\n(]+|\([^)]*\))/gm)){let t=i(e[1]??``);for(let r of(e[2]??``).replace(/[()]/g,``).split(`,`)){let[e=``,i]=r.trim().split(/\s+as\s+/);e&&(n.imports.set(i??e,`${t}/${e}`),n.imports.set(`${i??e}@`,t))}}for(let e of t.matchAll(/^(\w+)\s*=\s*(?:APIRouter|Blueprint)\s*\(([^)]*)\)/gm)){let t=/(?:url_)?prefix\s*=\s*['"]([^'"]*)['"]/.exec(e[2]??``)?.[1];n.prefixes.set(e[1]??``,t??``)}for(let e of t.matchAll(/^(\w+)\s*=\s*(?:FastAPI|Flask)\s*\(/gm))n.prefixes.set(e[1]??``,``);for(let e of t.matchAll(/@(\w+)\.(get|post|put|patch|delete|route|api_route)\s*\(\s*(['"])([^'"]*)\3([^)]*)\)/g)){let t=e[2]??`get`,r=t===`route`||t===`api_route`?(/methods\s*=\s*\[([^\]]*)\]/.exec(e[5]??``)?.[1]?.match(/[A-Za-z]+/g)?.map(e=>e.toUpperCase())??[`GET`]).filter(e=>bD.includes(e)):[t.toUpperCase()];for(let t of r)n.routes.push({router:e[1]??``,method:t,path:e[4]??``})}for(let e of t.matchAll(/(\w+)\.(?:include_router|register_blueprint)\s*\(\s*([\w.]+)([^)]*)\)/g)){let t=/(?:url_)?prefix\s*=\s*['"]([^'"]*)['"]/.exec(e[3]??``)?.[1]??``;n.includes.push({owner:e[1]??``,ref:e[2]??``,prefix:t})}return n}function PD(e){let t=/* @__PURE__ */ new Map;for(let n of e){t.set(n.module,n);let e=n.module.split(`/`);for(let r=1;r<e.length;r++)t.has(e.slice(r).join(`/`))||t.set(e.slice(r).join(`/`),n)}let n=(e,n)=>{let[r=``,i]=n.split(`.`);if(i){let n=e.imports.get(r),a=n?t.get(n):void 0;return a?{file:a,router:i}:void 0}let a=e.imports.get(`${r}@`),o=a?t.get(a):void 0;return o?{file:o,router:r}:e.prefixes.has(r)?{file:e,router:r}:void 0},r=(t,i,a=0)=>{if(a>4)return``;for(let o of e)for(let e of o.includes){let s=n(o,e.ref);if(s?.file===t&&s.router===i)return TD(r(o,e.owner,a+1),o.prefixes.get(e.owner)??``,e.prefix)}return``},i=[];for(let t of e)for(let e of t.routes)i.push(ED(e.method,TD(r(t,e.router),t.prefixes.get(e.router)??``,e.path),t.path,`code`));return i}function FD(e,t){if(!/"github\.com\/(?:gin-gonic\/gin|labstack\/echo|go-chi\/chi|gofiber\/fiber)/.test(t))return[];let n=[];for(let r of t.matchAll(/\b\w+\.(GET|POST|PUT|PATCH|DELETE|Get|Post|Put|Patch|Delete)\s*\(\s*"(\/[^"]*)"/g))n.push(ED((r[1]??`GET`).toUpperCase(),wD(r[2]??`/`),e,`code`));return n}const ID=/(sk_live_|sk_test_|sk-ant-|sk-proj-|AKIA[0-9A-Z]{16}|-----BEGIN|xox[bpas]-|ghp_|eyJ[A-Za-z0-9_-]{10,}\.)/;function LD(e){if(typeof e!=`string`||!e.trim()||e.length>4e3||ID.test(e))return null;let t;try{t=JSON.parse(e)}catch{return null}return{contentType:`application/json`,fields:Z(t)?Object.entries(t).map(([e,t])=>({name:e,type:Array.isArray(t)?`array`:t===null?`null`:typeof t,required:!1})):[],example:t}}function RD(e,t){if(!Z(t)||!Z(t.info)||!Array.isArray(t.item))return[];let n=[],r=(t,i)=>{for(let a of t){if(!Z(a))continue;let t=Z(a.auth)&&typeof a.auth.type==`string`?a.auth.type:i;if(Array.isArray(a.item)){r(a.item,t);continue}let o=a.request;if(!Z(o))continue;let s=String(o.method??`GET`).toUpperCase();if(!bD.includes(s))continue;let c=o.url,l=wD((Z(c)&&Array.isArray(c.path)?c.path.map(String):String(Z(c)?c.raw??``:c??``).replace(/^[a-z]+:\/\/[^/]+|^\{\{[^}]+\}\}/i,``).split(`?`)[0]?.split(`/`)??[]).filter(Boolean).join(`/`)),u=Z(o.auth)&&typeof o.auth.type==`string`?o.auth.type:t,d=Z(o.body)?LD(o.body.raw):null,f=(Array.isArray(a.response)?a.response:[]).flatMap(e=>Z(e)&&typeof e.code==`number`?[{status:e.code,description:typeof e.name==`string`?e.name:``,body:LD(e.body)}]:[]);n.push(ED(s,l,e,`postman`,{name:typeof a.name==`string`&&a.name?a.name:`${s} ${l}`,auth:u&&u!==`noauth`?`${u} auth`:null,request:d,responses:f,...typeof o.description==`string`&&o.description.length<500?{description:o.description}:{}}))}};return r(t.item,Z(t.auth)&&typeof t.auth.type==`string`?t.auth.type:null),n}async function zD(e){let t=new Set(e.files.map(e=>e.path)),n=[],r=[],i=[],a=[];for(let o of e.files){if(o.size>5e5)continue;let s=kx(o.path);if(/\.postman_collection\.json$/i.test(s)){let t=await e.readText(o);if(t===null)continue;try{a.push(...RD(o.path,JSON.parse(t)))}catch{e.warnings.push(`${o.path}: Postman collection could not be parsed`)}}else if(!(SD.test(o.path)||CD.test(o.path))){if(xD.test(s)){let r=await e.readText(o);if(r===null)continue;i.push(...jD(o.path,r));let a=AD(o.path,r,t);a&&n.push(a)}else if(s.endsWith(`.py`)){let t=await e.readText(o);if(t===null)continue;let n=ND(o.path,t);n&&r.push(n)}else if(s.endsWith(`.go`)){let t=await e.readText(o);t!==null&&i.push(...FD(o.path,t))}}}i.push(...MD(n),...PD(r));let o=/* @__PURE__ */ new Set,s=[];for(let e of[...a,...i]){let t=DD(e.method,e.path);o.has(t)||(o.add(t),s.push(e))}return s}async function BD(e,{fromDisk:t=!1}={}){let n=_.resolve(e);if(!(await p(n)).isDirectory())throw Error(`${n} is not a folder`);let r=(/* @__PURE__ */ new Date()).toISOString(),i=[],a=t?null:await RS(n);!t&&!a&&C(_.join(n,`.git`))&&i.push(`No main or master branch found: read the files on disk instead`);let o=a?await Ex(n,a.ref):await Tx(n),s=await CS(o),[c,l,u,d,f,m,h,g]=await Promise.all([BS(n,i,a?.ref??null),gD(o),Tw(o),TS(o,s),MS(o),YE(o),yE(o),zD(o)]),v=await ST(o,u),y=await lE(o,v,c.name),b=new Set(v.map(e=>e.provider)),x=kT([...h.tables,...h.objects],[...v,...y.resources.filter(e=>!b.has(e.provider))]);return{scannedAt:r,root:n,repo:{...c,languages:dE(o.files),readme:l},dependencies:u,docs:d,agentInstructions:f,contracts:[...m,...g.filter(e=>!m.some(t=>DD(t.method,t.path)===DD(e.method,e.path))),...h.tables,...h.objects,...y.contracts],resources:x,docsConfig:{alwaysLoad:!!s.alwaysLoad},warnings:[...i,...o.warnings]}}function VD(e){let t=(e,t,n=`${t}s`)=>e?`${e} ${e===1?t:n}`:``;return[t(e.docs,`doc`)+(e.docsChanged&&e.docsChanged<e.docs?` (${e.docsChanged} changed)`:``),t(e.dependencies,`dependency`,`dependencies`),t(e.contracts,`contract`),t(e.resources,`service`)].filter(Boolean).join(` · `)||`nothing to import yet`}function HD(e){let{scannedRef:t,headSha:n}=e.repo;if(!t)return`files on disk`;let r=t.replace(/^origin\//,``);return n?`${r} @ ${n.slice(0,7)}`:r}async function UD(e,t,{quiet:n=!1,source:r=`connector`,name:i,restore:a}={}){await zS(e);let o=await BD(e),s=(i??t.repoName)?.trim();s&&Object.assign(o.repo,{name:s,nameFromConfig:!0}),a&&Object.assign(o.repo,{restore:!0});let c=await new Wr(await ux()).call(`sync_repo`,{p_project:t.projectId,p_snapshot:o,p_source:r});if(!n){Hx(`Synced ${Rx(o.repo.name)} to ${Rx(t.name)} ${Q(`from ${HD(o)}`)}`),Ux(Q(VD(c)));for(let e of o.warnings)Ux(Q(`! ${e}`))}return{snapshot:o,result:c}}async function WD(e){return FS(await Tx(e))}const GD=26214400,KD=e=>`${(e/1024/1024).toFixed(1)} MB`;async function qD(e,t,{quiet:n=!1}={}){if(!t.folder)return;let{docs:r,unsupported:i}=await WD(e),a=e=>Buffer.byteLength(e.body),o=r.reduce((e,t)=>e+a(t),0);if(o>GD){let t=/* @__PURE__ */ new Map;for(let e of r){let n=e.path.includes(`/`)?`${e.path.split(`/`)[0]}/`:e.path;t.set(n,(t.get(n)??0)+a(e))}let n=[...t].sort((e,t)=>t[1]-e[1]).slice(0,3).map(([e,t])=>`${e} (${KD(t)})`).join(`, `);throw new qx(`The documents outside the repos add up to ${KD(o)}, over the ${KD(GD)} a sync takes. The biggest: ${n}. List what Quirl should skip in ${x(v(e),`.quirlignore`)}, like .gitignore.`)}let s=new Wr(await ux()),c={p_project:t.projectId,p_folder:t.folder},l=await s.call(`folder_doc_hashes`,c),u=r.filter(e=>l[e.path]!==e.contentHash),d=0;for(let t=0;t<u.length;){let n=[],r=0;for(;t<u.length;){let e=u[t];if(n.length&&r+a(e)>2097152)break;n.push(e),r+=a(e),t++}let i=await s.call(`sync_folder_docs`,{...c,p_folder_name:v(e),p_docs:n});d+=i.docsChanged}let f={...await s.call(`sync_folder_finish`,{...c,p_paths:r.map(e=>e.path)}),docsChanged:d};return n||(Hx(`Synced the documents in ${Rx(`${v(e)}/`)} outside the repos`),Ux(Q(`${f.docs} docs (${f.docsChanged} changed${f.archived?`, ${f.archived} removed`:``})`)),i.length&&Ux(Q(`! ${i.length} PDF/Office files skipped: only markdown and text are read for now`))),f}async function JD(e={}){let t=await mx();if(!t)throw new qx("This folder isn't linked to a Quirl project. Run `quirl init`.");let n=dx(t.link),r=n.length?n.map(e=>({root:x(t.root,e.path),name:e.name})):[{root:t.root,name:void 0}],i=r.length+ +!!t.link.folder,a=0;for(let{root:o,name:s}of r)try{let r=n.length?await mx(o):null,i=s??(r?.root===o?r.link.repoName:void 0);await UD(o,t.link,{...e,name:i})}catch(e){if(a++,i===1)throw e;let n=S(t.root,o)||`.`;console.error(`${Bx(`✗`)} ${n}: ${Mx(e)}`)}if(t.link.folder)try{await qD(t.root,t.link,e)}catch(e){a++,console.error(`${Bx(`✗`)} documents in ${v(t.root)}/: ${Mx(e)}`)}if(a)throw new qx(`${a} of ${i} parts didn't sync.`)}async function YD(e){let t=fx(),n=await tS(t),r=n.length?n:[t],i=r.length>1||r[0]!==t,a=e=>S(t,e)||v(t),o=h(),s=t.startsWith(o)?`~${t.slice(o.length)}`:t;if(console.log(`\n🌀 ${Rx(`Quirl`)} ${Q(`·`)} connecting ${Rx(s)}`),i&&(Wx(`📁`,`Found ${r.length} ${r.length===1?`repo`:`repos`}`),Gx(Q(r.map(a).join(` · `))),!await Yx(` Import all of them into one project?`,!0)))throw new qx("Nothing imported. Run `quirl init` inside the repo you want instead.");let c=!1;if(i&&!n.includes(t)){let{docs:e,unsupported:n}=await WD(t);if(e.length){Wx(`📄`,`Also found ${e.length} ${e.length===1?`document`:`documents`} outside the repos`);for(let t of e.slice(0,8))Gx(Q(t.path));e.length>8&&Gx(Q(`…and ${e.length-8} more`)),n.length&&Gx(Q(`(${n.length} PDF/Office files can't be read yet and are skipped)`)),c=await Yx(` Import them too? Everyone on the project will be able to read them.`,!0)}}await sx()||await hS({quiet:!0});let l=await ZD((await new Wr(await ux()).whoami()).projects,e.project??(await mx(t))?.link.project);if(l.role===`stakeholder`)throw new qx(`You're a stakeholder on ${l.name}; ask an admin or dev to run \`quirl init\`.`);let u={project:l.slug,projectId:l.id,name:l.name};Wx(`🔗`,`Linked to ${Rx(l.name)} ${Q(`· ${l.organization}`)}`);let d=e.claude!==!1,f=e.hooks??await Yx(` Sync with Quirl on every git push?`,!0);Wx(`📦`,`Importing docs, dependencies and schemas`);let p=[],m=i?await mx(t):null,g=new Map((m?.root===t?dx(m.link):[]).filter(e=>e.name).map(e=>[e.path,e.name]));for(let e of r){let t=Kx(`Reading ${a(e)}…`);try{let n=await mx(e),r=(n?.root===e?n.link.repoName:void 0)??g.get(a(e));r&&g.set(a(e),r);let i=r?{...u,repoName:r}:u;await hx(e,i);let{snapshot:o,result:s}=await UD(e,i,{quiet:!0,restore:!0});d&&await XD(e,l.name),f&&await mS(e),t.stop(),Gx(`${zx(`✓`)} ${Rx(a(e))} ${Q(`(${HD(o)})`)} ${Q(VD(s))}`);for(let e of o.warnings)Gx(Q(` ! ${e}`));p.push(e)}catch(n){t.stop(),Gx(`${Bx(`✗`)} ${Rx(a(e))} ${Mx(n)}`)}}if(!p.length)throw new qx(`No repo was imported.`);if(i){let e=p.map(e=>{let t=g.get(a(e));return t?{path:a(e),name:t}:a(e)}),n=m,r={...u,repos:e,folder:c?n?.root===t&&n.link.folder||ee():void 0};if(await hx(t,r),c)try{let e=await qD(t,r,{quiet:!0});Gx(`${zx(`✓`)} ${Rx(`documents outside the repos`)} ${Q(`${e?.docs??0} docs`)}`)}catch(e){Gx(`${Bx(`✗`)} ${Rx(`documents outside the repos`)} ${Mx(e)}`)}d&&!p.includes(t)&&await XD(t,l.name,p.map(a))}let _=aS().portable;d&&(Wx(`🤖`,`Connected Claude Code`),Gx(Q(`.mcp.json the quirl tools`)),Gx(Q(`.claude/settings.json the briefing, loaded as each session starts`)),Gx(Q(`CLAUDE.md when to use Quirl`))),f&&Wx(`🪝`,`Quirl syncs on every ${Rx(`git push`)}`);let y=r.length-p.length,b=`.quirl .mcp.json .claude/settings.json CLAUDE.md`;Wx(y?`⚠️ `:`🎉`,y?`Done, but ${y} of ${r.length} repos failed. Fix them and run ${Rx(`quirl init`)} again.`:Rx(`All set!`)),Gx(d&&!_?Q(`Don't commit ${b} yet: they point at this checkout until the CLI is installed.`):`${Q(`1.`)} Commit what was added${i?` in each repo`:``}: ${Vx(`git add ${b}`)}`),Gx(`${Q(d&&!_?`→`:`2.`)} Start Claude Code here and approve the ${Rx(`quirl`)} server when it asks.`),i&&!p.includes(t)&&Gx(Q("Run `quirl sync` here to sync every repo at once.")),console.log(``)}async function XD(e,t,n=[]){await dS(e),await fS(e),await pS(e,t,n)}async function ZD(e,t){if(!e.length)throw new qx(`You aren't on any Quirl project yet. Ask an admin to invite you.`);if(t){let n=e.find(e=>e.slug===t||e.id===t);if(!n)throw new qx(`No project "${t}" among yours: ${e.map(e=>e.slug).join(`, `)}.`);return n}if(e.length===1)return e[0];Wx(`🗂️ `,`Which project is this part of?`);for(let[t,n]of e.entries())Gx(`${Vx(String(t+1))} ${n.name} ${Q(`· ${n.organization} · ${n.role}`)}`);let n=e[Number(await Jx(` Project [1-${e.length}]: `))-1];if(!n)throw new qx("No project picked. Run `quirl init --project <slug>`.");return n}const QD=`${Rx(`quirl`)} ${Q(tx)}: connect a repo to Quirl
379
+ `).map(e=>e.trim()).filter(Boolean),n=t[0];if(!n||/^(#|=+$|-+$|\||[-*+] |\d+\. |>|<|\[!\[|!\[)/.test(n)||/^ {4}|^\t/.test(e))continue;let r=wD(t.join(` `));if(!(r.length<15||!/[a-z]/i.test(r)))return TD(/^.+?[.!?](?=\s+["'([]?[A-Z]|\s*$)/.exec(r)?.[0]??r,200)}return null}function wD(e){return e.replace(/!\[[^\]]*\]\([^)]*\)/g,``).replace(/\[([^\]]*)\]\([^)]*\)/g,`$1`).replace(/\[([^\]]*)\]\[[^\]]*\]/g,`$1`).replace(/<[^>]+>/g,``).replace(/`([^`]*)`/g,`$1`).replace(/(\*\*|__)(.*?)\1/g,`$2`).replace(/(^|\W)[*_](\S(?:.*?\S)?)[*_](?=\W|$)/g,`$1$2`).replace(/\s+/g,` `).trim()}function TD(e,t){if(e.length<=t)return e;let n=e.slice(0,t-1),r=n.lastIndexOf(` `);return`${(r>t/2?n.slice(0,r):n).trimEnd()}…`}const ED=[`GET`,`POST`,`PUT`,`PATCH`,`DELETE`],DD=/\.(?:[cm]?[jt]sx?)$/i,OD=/(^|\/)(?:__tests__|tests?|spec|e2e|fixtures?|test-fixtures|mocks?|examples?|dist|build|\.next)\//i,kD=/\.(?:test|spec)\.[cm]?[jt]sx?$|(^|\/)test_[^/]*\.py$|_test\.(?:py|go)$/i;function AD(e){let t=e.replace(/<(?:[\w]+:)?([A-Za-z_]\w*)>/g,`{$1}`).replace(/(^|\/):([A-Za-z_]\w*)\??/g,`$1{$2}`).replace(/\[\.\.\.([\w]+)\]/g,`{$1}`).replace(/\[([\w]+)\]/g,`{$1}`).replace(/\{\{([\w]+)\}\}/g,`{$1}`);return t.startsWith(`/`)||(t=`/${t}`),t=t.replace(/\/{2,}/g,`/`),t.length>1?t.replace(/\/$/,``):t}const jD=(...e)=>AD(e.filter(Boolean).join(`/`)),MD=(e,t,n,r,i={})=>({kind:`endpoint`,name:`${e} ${t}`,sourcePath:n,method:e,path:t,auth:null,request:null,responses:[],from:r,...i}),ND=(e,t)=>`${e} ${AD(t).replace(/\{[^}]*\}/g,`{}`).toLowerCase()}`,PD=String.raw`(['"\`])([^'"\`\n]*)['"\`]`;function FD(e,t,n){if(!t.startsWith(`.`))return;let r=e.slice(0,e.lastIndexOf(`/`)+1),i=[];for(let e of`${r}${t}`.split(`/`))e===`..`?i.pop():e!==`.`&&e!==``&&i.push(e);let a=i.join(`/`).replace(/\.[cm]?js$/,``);for(let e of[``,`.ts`,`.tsx`,`.js`,`.mjs`,`.cjs`,`/index.ts`,`/index.js`])if(n.has(a+e))return a+e}function ID(e,t,n){let r=/from\s+['"](?:express|fastify|hono|koa|@koa\/router|koa-router|@hono\/[\w-]+)['"]|require\(\s*['"](?:express|fastify|koa|@koa\/router|koa-router)['"]\s*\)/.test(t),i=/from\s+['"]@nestjs\/common['"]/.test(t);if(!r&&!i)return null;let a={path:e,routes:[],mounts:[],imports:/* @__PURE__ */ new Map};for(let r of t.matchAll(/import\s+(?:(\w+)|\*\s+as\s+(\w+)|\{([^}]*)\})\s+from\s+['"]([^'"]+)['"]/g)){let t=FD(e,r[4]??``,n);if(!t)continue;let i=r[1]??r[2]??``;i&&a.imports.set(i,t);for(let e of(r[3]??``).split(`,`))a.imports.set(e.trim().split(/\s+as\s+/).pop()??``,t)}for(let r of t.matchAll(/(?:const|let|var)\s+(\w+)\s*=\s*require\(\s*['"]([^'"]+)['"]\s*\)/g)){let t=FD(e,r[2]??``,n);t&&r[1]&&a.imports.set(r[1],t)}if(r){let r=/* @__PURE__ */ new Set([`app`,`router`,`server`,`fastify`]);for(let e of t.matchAll(/(?:const|let|var)\s+(\w+)\s*(?::\s*[\w<>.]+)?\s*=\s*(?:express\s*\(|express\.Router\s*\(|Router\s*\(|fastify\s*\(|Fastify\s*\(|new\s+(?:Hono|Router|KoaRouter)\s*\(|createRouter\s*\()/g))e[1]&&r.add(e[1]);let i=[...r].join(`|`);for(let e of t.matchAll(new RegExp(String.raw`\b(?:${i})\s*\.\s*(get|post|put|patch|delete)\s*\(\s*${PD}`,`g`))){let t=e[3]??``;(t.startsWith(`/`)||t===``)&&a.routes.push({method:(e[1]??`get`).toUpperCase(),path:t})}for(let e of t.matchAll(new RegExp(String.raw`\b(?:${i})\s*\.\s*route\s*\(\s*${PD}\s*\)((?:\s*\.\s*(?:get|post|put|patch|delete|all)\s*\([^)]*\)?)+)`,`g`)))for(let t of(e[3]??``).matchAll(/\.\s*(get|post|put|patch|delete)\s*\(/g))a.routes.push({method:(t[1]??`get`).toUpperCase(),path:e[2]??``});for(let r of t.matchAll(new RegExp(String.raw`\b(?:${i})\s*\.\s*(?:use|route)\s*\(\s*${PD}\s*,\s*(?:require\(\s*['"]([^'"]+)['"]\s*\)|(\w+))`,`g`))){let t=r[3]?FD(e,r[3],n):a.imports.get(r[4]??``);t&&a.mounts.push({prefix:r[2]??``,target:t})}for(let e of t.matchAll(/\.register\s*\(\s*(\w+)\s*,\s*\{[^}]*prefix\s*:\s*(['"`])([^'"`]*)\2/g)){let t=a.imports.get(e[1]??``);t&&a.mounts.push({prefix:e[3]??``,target:t})}}if(i)for(let e of t.split(/(?=@Controller\s*\()/).slice(1)){let t=/@Controller\s*\(\s*(?:(['"`])([^'"`]*)\1|\{[^}]*path\s*:\s*(['"`])([^'"`]*)\3)?/.exec(e);for(let n of e.matchAll(/@(Get|Post|Put|Patch|Delete)\s*\(\s*(?:(['"`])([^'"`]*)\2)?\s*\)/g))a.routes.push({method:(n[1]??`Get`).toUpperCase(),path:jD(t?.[2]??t?.[4]??``,n[3]??``)})}return a}function LD(e,t){let n=/(?:^|\/)app\/(.*)\/route\.[cm]?[jt]sx?$/.exec(e),r=/(?:^|\/)pages\/(api\/.*?)(?:\/index)?\.[cm]?[jt]sx?$/.exec(e),i=n?.[1]??r?.[1];if(i===void 0)return[];let a=AD(i.split(`/`).filter(e=>!/^\(.*\)$/.test(e)&&!e.startsWith(`@`)).join(`/`)),o=n?ED.filter(e=>new RegExp(String.raw`export\s+(?:async\s+)?(?:function\s+${e}\b|const\s+${e}\b)|export\s*\{[^}]*\b${e}\b`).test(t)):[...new Set([...t.matchAll(/req\.method\s*={2,3}\s*['"](\w+)['"]/g)].map(e=>(e[1]??``).toUpperCase()))].filter(e=>ED.includes(e));return(o.length?o:[`GET`]).map(t=>MD(t,a,e,`code`))}function RD(e){let t=new Map(e.map(e=>[e.path,e])),n=(t,r=0)=>{if(r>4)return``;for(let i of e)for(let e of i.mounts)if(e.target===t)return jD(n(i.path,r+1),e.prefix);return``},r=[];for(let e of t.values()){let t=n(e.path);for(let n of e.routes)r.push(MD(n.method,jD(t,n.path),e.path,`code`))}return r}function zD(e,t){if(!/\b(?:fastapi|flask)\b/i.test(t))return null;let n={path:e,module:e.replace(/\.py$/,``).replace(/\/__init__$/,``),routes:[],prefixes:/* @__PURE__ */ new Map,includes:[],imports:/* @__PURE__ */ new Map},r=e.includes(`/`)?e.slice(0,e.lastIndexOf(`/`)):``,i=e=>{let t=/^\.+/.exec(e)?.[0].length??0,n=r;for(let e=1;e<t;e++)n=n.slice(0,n.lastIndexOf(`/`));let i=e.slice(t).replace(/\./g,`/`);return t?[n,i].filter(Boolean).join(`/`):i};for(let e of t.matchAll(/^from\s+([\w.]+)\s+import\s+([^\n(]+|\([^)]*\))/gm)){let t=i(e[1]??``);for(let r of(e[2]??``).replace(/[()]/g,``).split(`,`)){let[e=``,i]=r.trim().split(/\s+as\s+/);e&&(n.imports.set(i??e,`${t}/${e}`),n.imports.set(`${i??e}@`,t))}}for(let e of t.matchAll(/^(\w+)\s*=\s*(?:APIRouter|Blueprint)\s*\(([^)]*)\)/gm)){let t=/(?:url_)?prefix\s*=\s*['"]([^'"]*)['"]/.exec(e[2]??``)?.[1];n.prefixes.set(e[1]??``,t??``)}for(let e of t.matchAll(/^(\w+)\s*=\s*(?:FastAPI|Flask)\s*\(/gm))n.prefixes.set(e[1]??``,``);for(let e of t.matchAll(/@(\w+)\.(get|post|put|patch|delete|route|api_route)\s*\(\s*(['"])([^'"]*)\3([^)]*)\)/g)){let t=e[2]??`get`,r=t===`route`||t===`api_route`?(/methods\s*=\s*\[([^\]]*)\]/.exec(e[5]??``)?.[1]?.match(/[A-Za-z]+/g)?.map(e=>e.toUpperCase())??[`GET`]).filter(e=>ED.includes(e)):[t.toUpperCase()];for(let t of r)n.routes.push({router:e[1]??``,method:t,path:e[4]??``})}for(let e of t.matchAll(/(\w+)\.(?:include_router|register_blueprint)\s*\(\s*([\w.]+)([^)]*)\)/g)){let t=/(?:url_)?prefix\s*=\s*['"]([^'"]*)['"]/.exec(e[3]??``)?.[1]??``;n.includes.push({owner:e[1]??``,ref:e[2]??``,prefix:t})}return n}function BD(e){let t=/* @__PURE__ */ new Map;for(let n of e){t.set(n.module,n);let e=n.module.split(`/`);for(let r=1;r<e.length;r++)t.has(e.slice(r).join(`/`))||t.set(e.slice(r).join(`/`),n)}let n=(e,n)=>{let[r=``,i]=n.split(`.`);if(i){let n=e.imports.get(r),a=n?t.get(n):void 0;return a?{file:a,router:i}:void 0}let a=e.imports.get(`${r}@`),o=a?t.get(a):void 0;return o?{file:o,router:r}:e.prefixes.has(r)?{file:e,router:r}:void 0},r=(t,i,a=0)=>{if(a>4)return``;for(let o of e)for(let e of o.includes){let s=n(o,e.ref);if(s?.file===t&&s.router===i)return jD(r(o,e.owner,a+1),o.prefixes.get(e.owner)??``,e.prefix)}return``},i=[];for(let t of e)for(let e of t.routes)i.push(MD(e.method,jD(r(t,e.router),t.prefixes.get(e.router)??``,e.path),t.path,`code`));return i}function VD(e,t){if(!/"github\.com\/(?:gin-gonic\/gin|labstack\/echo|go-chi\/chi|gofiber\/fiber)/.test(t))return[];let n=[];for(let r of t.matchAll(/\b\w+\.(GET|POST|PUT|PATCH|DELETE|Get|Post|Put|Patch|Delete)\s*\(\s*"(\/[^"]*)"/g))n.push(MD((r[1]??`GET`).toUpperCase(),AD(r[2]??`/`),e,`code`));return n}const HD=/(sk_live_|sk_test_|sk-ant-|sk-proj-|AKIA[0-9A-Z]{16}|-----BEGIN|xox[bpas]-|ghp_|eyJ[A-Za-z0-9_-]{10,}\.)/;function UD(e){if(typeof e!=`string`||!e.trim()||e.length>4e3||HD.test(e))return null;let t;try{t=JSON.parse(e)}catch{return null}return{contentType:`application/json`,fields:Z(t)?Object.entries(t).map(([e,t])=>({name:e,type:Array.isArray(t)?`array`:t===null?`null`:typeof t,required:!1})):[],example:t}}function WD(e,t){if(!Z(t)||!Z(t.info)||!Array.isArray(t.item))return[];let n=[],r=(t,i)=>{for(let a of t){if(!Z(a))continue;let t=Z(a.auth)&&typeof a.auth.type==`string`?a.auth.type:i;if(Array.isArray(a.item)){r(a.item,t);continue}let o=a.request;if(!Z(o))continue;let s=String(o.method??`GET`).toUpperCase();if(!ED.includes(s))continue;let c=o.url,l=AD((Z(c)&&Array.isArray(c.path)?c.path.map(String):String(Z(c)?c.raw??``:c??``).replace(/^[a-z]+:\/\/[^/]+|^\{\{[^}]+\}\}/i,``).split(`?`)[0]?.split(`/`)??[]).filter(Boolean).join(`/`)),u=Z(o.auth)&&typeof o.auth.type==`string`?o.auth.type:t,d=Z(o.body)?UD(o.body.raw):null,f=(Array.isArray(a.response)?a.response:[]).flatMap(e=>Z(e)&&typeof e.code==`number`?[{status:e.code,description:typeof e.name==`string`?e.name:``,body:UD(e.body)}]:[]);n.push(MD(s,l,e,`postman`,{name:typeof a.name==`string`&&a.name?a.name:`${s} ${l}`,auth:u&&u!==`noauth`?`${u} auth`:null,request:d,responses:f,...typeof o.description==`string`&&o.description.length<500?{description:o.description}:{}}))}};return r(t.item,Z(t.auth)&&typeof t.auth.type==`string`?t.auth.type:null),n}async function GD(e){let t=new Set(e.files.map(e=>e.path)),n=[],r=[],i=[],a=[];for(let o of e.files){if(o.size>5e5)continue;let s=kx(o.path);if(/\.postman_collection\.json$/i.test(s)){let t=await e.readText(o);if(t===null)continue;try{a.push(...WD(o.path,JSON.parse(t)))}catch{e.warnings.push(`${o.path}: Postman collection could not be parsed`)}}else if(!(OD.test(o.path)||kD.test(o.path))){if(DD.test(s)){let r=await e.readText(o);if(r===null)continue;i.push(...LD(o.path,r));let a=ID(o.path,r,t);a&&n.push(a)}else if(s.endsWith(`.py`)){let t=await e.readText(o);if(t===null)continue;let n=zD(o.path,t);n&&r.push(n)}else if(s.endsWith(`.go`)){let t=await e.readText(o);t!==null&&i.push(...VD(o.path,t))}}}i.push(...RD(n),...BD(r));let o=/* @__PURE__ */ new Set,s=[];for(let e of[...a,...i]){let t=ND(e.method,e.path);o.has(t)||(o.add(t),s.push(e))}return s}const KD={200:`OK`,201:`Created`,202:`Accepted`,204:`No content`,400:`Bad request`,401:`Unauthorized`,403:`Forbidden`,404:`Not found`,409:`Conflict`,422:`Invalid input`,429:`Too many requests`,500:`Server error`,502:`Bad gateway`,503:`Unavailable`};function qD(t){try{let n=e(x(t,`noop.js`))(`typescript`);return typeof n?.createProgram==`function`?n:null}catch{return null}}function JD(e,t){for(let n=t;;n=y(n)){let t=x(n,`tsconfig.json`);if(C(t))return t;if(n===e||y(n)===n)return null}}function YD(e,t,n){let r=/* @__PURE__ */ new Map;for(let e of t){if(e.from!==`code`||!/\.[cm]?tsx?$/.test(e.sourcePath))continue;let t=r.get(e.sourcePath)??[];t.push(e),r.set(e.sourcePath,t)}if(r.size===0)return;let i=/* @__PURE__ */ new Map;for(let t of r.keys()){let n=JD(e,y(x(e,t)))??``;i.set(n,[...i.get(n)??[],t])}let a=!1;for(let[t,o]of i){let i=qD(y(x(e,o[0]??``)));if(!i)a=!0;else try{XD(i,e,t,o,r)}catch(r){n.push(`Endpoint types in ${S(e,t)||`the repo`} could not be read: ${r.message}`)}}a&&n.push(`TypeScript isn't installed in this repo (run your package manager's install), so endpoint request and response types weren't read.`)}function XD(e,t,n,r,i){let a=n?e.getParsedCommandLineOfConfigFile(n,{},{...e.sys,onUnRecoverableConfigFileDiagnostic:()=>{}}):null,o=e.createProgram({rootNames:r.map(e=>x(t,e)),options:{...a?.options??{allowJs:!0,strict:!0},noEmit:!0,skipLibCheck:!0}}),s=new ZD(e,o.getTypeChecker());for(let n of r){let r=o.getSourceFile(x(t,n)),a=i.get(n)??[];if(!r)continue;let c=t=>{let n=s.route(t);if(n){let e=a.filter(e=>e.method===n.method&&(e.path===n.path||n.path!==`/`&&e.path.endsWith(n.path)));if(e.length){let t=s.handler(n.handler);for(let n of e)!n.request&&t.request&&(n.request=t.request),n.responses.length||(n.responses=t.responses)}}e.forEachChild(t,c)};c(r)}}var ZD=class{ts;checker;constructor(e,t){this.ts=e,this.checker=t}route(e){let t=this.ts;if(!t.isCallExpression(e))return;let n=e.expression;if(!t.isPropertyAccessExpression(n))return;let r=n.name.text;if(!/^(get|post|put|patch|delete)$/.test(r))return;let[i]=e.arguments;if(!(e.arguments.length<2||!(t.isStringLiteral(i)||t.isNoSubstitutionTemplateLiteral(i))))return{method:r.toUpperCase(),path:AD(i.text),handler:e.arguments[e.arguments.length-1]}}fn(e,t=0){let n=this.ts;if(!(!e||t>4)){if(n.isArrowFunction(e)||n.isFunctionExpression(e)||n.isFunctionDeclaration(e)||n.isMethodDeclaration(e))return e;if(n.isIdentifier(e)||n.isPropertyAccessExpression(e)){let r=this.checker.getSymbolAtLocation(e);r&&r.flags&n.SymbolFlags.Alias&&(r=this.checker.getAliasedSymbol(r));let i=r?.valueDeclaration??r?.declarations?.[0];return i?n.isVariableDeclaration(i)?this.fn(i.initializer,t+1):this.fn(i,t+1):void 0}if(n.isCallExpression(e)){let n=this.fn(e.expression,t+1),r=n&&this.returned(n);if(r)return r;if(e.arguments.length)return this.fn(e.arguments[e.arguments.length-1],t+1)}}}returned(e){let t=this.ts,n=e.body;if(!n)return;if(!t.isBlock(n)){let e=t.isParenthesizedExpression(n)?n.expression:n;return t.isArrowFunction(e)||t.isFunctionExpression(e)?e:void 0}let r,i=e=>{if(!(r||t.isFunctionLike(e))){if(t.isReturnStatement(e)&&e.expression){let n=e.expression;t.isArrowFunction(n)||t.isFunctionExpression(n)?r=n:t.isIdentifier(n)&&(r=this.fn(n,3))}r||t.forEachChild(e,i)}};return t.forEachChild(n,i),r}handler(e){let t=this.ts,n=this.fn(e),r=/* @__PURE__ */ new Map,i=null;if(!n?.body)return{request:i,responses:[]};let a=(e,t)=>{e===void 0||r.has(e)||r.set(e,{status:e,description:KD[e]??``,body:t})},o=/* @__PURE__ */ new Set,s=(e,n,r,c,l,u)=>{if(o.has(e)||u>2)return!1;o.add(e);let d=!1,f=e=>e===void 0?200:t.isNumericLiteral(e)?Number(e.text):t.isIdentifier(e)?l.get(e.text):void 0,p=o=>{if(t.isCallExpression(o)&&t.isPropertyAccessExpression(o.expression)){let s=o.expression.name.text,l=o.expression.expression;!c&&t.isIdentifier(l)&&l.text===n?s===`json`?a(f(o.arguments[1]),this.payload(o.arguments[0])):(s===`body`||s===`text`||s===`html`)&&a(f(o.arguments[1]),null):!c&&t.isPropertyAccessExpression(l)&&t.isIdentifier(l.expression)&&l.expression.text===n&&l.name.text===`req`&&(s===`json`||s===`valid`&&this.isJsonTarget(o))?(d=!0,i??=this.requestAt(o,e)):c&&s===`json`&&(t.isIdentifier(l)&&l.text===r?a(200,this.payload(o.arguments[0])):t.isCallExpression(l)&&t.isPropertyAccessExpression(l.expression)&&l.expression.name.text===`status`&&t.isIdentifier(l.expression.expression)&&l.expression.expression.text===r&&a(f(l.arguments[0]),this.payload(o.arguments[0])))}if(c&&t.isPropertyAccessExpression(o)&&o.name.text===`body`&&t.isIdentifier(o.expression)&&o.expression.text===n&&(d=!0,i??=this.requestAt(o,e)),t.isCallExpression(o)){let a=c?r:n,f=o.arguments.findIndex(e=>t.isIdentifier(e)&&e.text===a);if(f>=0){let n=this.fn(o.expression),r=n?.parameters?.[f];if(n?.body&&r&&t.isIdentifier(r.name)){let a=/* @__PURE__ */ new Map;if(o.arguments.forEach((e,r)=>{let i=n.parameters[r],o=t.isNumericLiteral(e)?Number(e.text):t.isIdentifier(e)?l.get(e.text):void 0;i&&t.isIdentifier(i.name)&&o!==void 0&&a.set(i.name.text,o)}),s(n,c?``:r.name.text,c?r.name.text:``,c,a,u+1)){d=!0;let t=this.declarationOf(o);!i&&t&&(i=this.readFields(t,e))}}}}t.forEachChild(o,p)};return p(e.body),d},c=n.parameters.map(e=>t.isIdentifier(e.name)?e.name.text:``);return s(n,c[0]??``,c[1]??``,c.length>=2,/* @__PURE__ */ new Map,0),{request:i,responses:[...r.values()].sort((e,t)=>e.status-t.status)}}calls(e,t){let n=this.ts,r=!1,i=e=>{n.isCallExpression(e)&&n.isPropertyAccessExpression(e.expression)&&e.expression.name.text===t&&(r=!0),r||n.forEachChild(e,i)};return i(e),r}isJsonTarget(e){let[t]=e.arguments;return t&&this.ts.isStringLiteral(t)&&t.text===`json`}requestAt(e,t){let n=this.ts,r=e;for(;;){let e=r.parent;if(!e)break;if(n.isAwaitExpression(e)||n.isParenthesizedExpression(e)||n.isNonNullExpression(e))r=e;else if(n.isPropertyAccessExpression(e)&&e.name.text===`catch`&&e.parent&&n.isCallExpression(e.parent))r=e.parent;else break}let i=r.parent;return i&&(n.isAsExpression(i)||n.isTypeAssertionExpression(i))?this.request(this.checker.getTypeFromTypeNode(i.type),i):i&&n.isVariableDeclaration(i)?i.type&&!this.isLoose(this.checker.getTypeFromTypeNode(i.type))?this.request(this.checker.getTypeFromTypeNode(i.type),i):this.request(this.checker.getTypeAtLocation(e),e)||(n.isIdentifier(i.name)?this.parsedFrom(i.name.text,t)??this.handedOn(i.name.text,t)??this.readFields(i,t):this.readFields(i,t)):i&&n.isCallExpression(i)&&i.arguments.includes(r)?this.validated(i):this.request(this.checker.getTypeAtLocation(e),e)}parsedFrom(e,t){let n=this.ts,r=null,i=t=>n.isIdentifier(t)&&t.text===e,a=(e,t)=>{r||(t===0&&n.isAsExpression(e)&&i(e.expression)&&(r=this.request(this.checker.getTypeFromTypeNode(e.type),e)),t===1&&n.isCallExpression(e)&&e.arguments.some(i)&&/parse|validat|decode|assert/i.test(n.isPropertyAccessExpression(e.expression)?e.expression.name.text:e.expression.getText())&&(r=this.validated(e)),r||n.forEachChild(e,e=>a(e,t)))};return a(t.body,0),a(t.body,1),r}handedOn(e,t){let n=this.ts,r=this.checker,i=null,a=t=>{if(!i){if(n.isIdentifier(t)&&t.text===e&&t.parent){let e=t.parent;if(n.isCallExpression(e)&&e.arguments.includes(t)){let e=r.getContextualType(t);e&&(i=this.request(e,t))}else if(n.isSpreadAssignment(e)&&n.isObjectLiteralExpression(e.parent)&&n.isCallExpression(e.parent.parent)){let t=e.parent,a=r.getContextualType(t),o=a&&this.request(a,t);if(o){let a=/* @__PURE__ */ new Set;for(let i of t.properties)if(i!==e){if(n.isSpreadAssignment(i))for(let e of r.getPropertiesOfType(r.getTypeAtLocation(i.expression)))a.add(e.name);else i.name&&n.isIdentifier(i.name)&&a.add(i.name.text)}let s=o.fields.filter(e=>!a.has(e.name));s.length&&(i={...o,fields:s,example:Object.fromEntries(Object.entries(o.example??{}).filter(([e])=>!a.has(e)))})}}}i||n.forEachChild(t,a)}};return a(t.body),i}declarationOf(e){let t=this.ts,n=e;for(;n.parent&&(t.isAwaitExpression(n.parent)||t.isParenthesizedExpression(n.parent)||t.isAsExpression(n.parent));)n=n.parent;return n.parent&&t.isVariableDeclaration(n.parent)?n.parent:void 0}readFields(e,t){let n=this.ts,r=/* @__PURE__ */ new Map,i=(e,t)=>{let n=r.get(e);if(n?n.type!==`unknown`:r.size>=60)return;let i=t&&this.usedAs(t);if(n&&!i)return;let a=i?this.literals(i):null;r.set(e,{name:e,type:i?this.typeName(i,0):`unknown`,required:!1,...a?{values:a}:{}})},a=e=>{let r=[],i=t=>{n.isIdentifier(t)&&t.text===e&&t.parent&&!n.isBindingElement(t.parent)&&r.push(t),n.forEachChild(t,i)};return i(t.body),r},o=e=>{for(let t of e.elements){let e=t.propertyName??t.name;if(!n.isIdentifier(e)&&!n.isStringLiteral(e))continue;let r=n.isIdentifier(t.name)?t.name.text:void 0;i(e.text,void 0);for(let t of r?a(r):[])i(e.text,t)}};if(n.isObjectBindingPattern(e.name))o(e.name);else if(n.isIdentifier(e.name))for(let t of a(e.name.text)){let e=t.parent;n.isPropertyAccessExpression(e)&&e.expression===t?i(e.name.text,e):n.isVariableDeclaration(e)&&e.initializer===t&&n.isObjectBindingPattern(e.name)&&o(e.name)}if(r.size===0)return null;let s=[...r.values()];return{contentType:`application/json`,fields:s,example:Object.fromEntries(s.map(e=>[e.name,e.values?.[0]??(e.type===`string`?`string`:e.type===`number`?0:e.type!==`boolean`&&null)]))}}usedAs(e){let t=this.ts,n=this.checker,r=e.parent,i;if(r&&t.isShorthandPropertyAssignment(r)){let e=n.getContextualType(r.parent),t=e&&n.getPropertyOfType(e,r.name.text);i=t&&n.getTypeOfSymbolAtLocation(t,r)}else i=n.getContextualType(e);return i&&!this.isLoose(i)?i:void 0}validated(e){let t=this.checker.getTypeAtLocation(e);if(this.isLoose(t))return null;let n=this.checker.getPropertyOfType(this.checker.getNonNullableType(t.isUnion?.()?t.types.find(e=>e.getProperty(`data`))??t:t),`data`),r=t.isUnion?.()?t.types.some(e=>e.getProperty(`success`)):t.getProperty?.(`success`);if(n&&r){let t=this.checker.getNonNullableType(this.checker.getTypeOfSymbolAtLocation(n,e));return this.request(t,e)}return this.request(t,e)}request(e,t){let n=this.payloadOfType(e,t);return n&&(n.fields.length||Array.isArray(n.example))?n:null}payload(e){return e?this.payloadOfType(this.checker.getTypeAtLocation(e),e):null}isLoose(e){let t=this.ts.TypeFlags;return!e||!!(e.flags&(t.Any|t.Unknown|t.Never|t.Void|t.Undefined|t.TypeParameter))}payloadOfType(e,t){let n=(e&&this.checker.getAwaitedType?.(e))??e;if(this.isLoose(n))return null;let[r,...i]=this.present(n),a=r&&i.length===0?r:n,o=this.element(a)??a;return{contentType:`application/json`,fields:this.isObject(o)?this.fields(o,t):[],example:this.example(n,t,0)}}element(e){let t=this.checker;if(t.isArrayType?.(e)||t.isTupleType?.(e))return t.getTypeArguments(e)[0]}isObject(e){let t=this.ts.TypeFlags;return e.isUnion?.()?e.types.every(e=>this.isObject(e)):!!(e.flags&(t.Object|t.Intersection))&&!this.element(e)&&!this.isDate(e)}isDate(e){return e.symbol?.name===`Date`}fields(e,t){let n=this.ts;return this.checker.getPropertiesOfType(e).slice(0,60).map(e=>{let r=this.checker.getTypeOfSymbolAtLocation(e,t),i=!!(e.flags&n.SymbolFlags.Optional)||r.isUnion?.()&&r.types.some(e=>e.flags&n.TypeFlags.Undefined),a=this.literals(r),o=n.displayPartsToString(e.getDocumentationComment(this.checker)).trim().split(`
380
+ `)[0];return{name:e.name,type:this.typeName(r,0),required:!i,...o?{description:o}:{},...a?{values:a}:{}}})}literals(e){let t=this.present(e),n=t.flatMap(e=>e.isStringLiteral?.()||e.isNumberLiteral?.()?[String(e.value)]:[]);return n.length>1&&n.length===t.length?n:null}present(e){let t=this.ts.TypeFlags;return(e.isUnion?.()?e.types:[e]).filter(e=>!(e.flags&(t.Null|t.Undefined)))}typeName(e,t){let n=this.ts.TypeFlags,r=this.present(e);if(r.length===0)return`null`;if(r.length>1)return r.every(e=>e.flags&n.StringLike)?`string`:r.every(e=>e.flags&n.NumberLike)?`number`:r.every(e=>e.flags&n.BooleanLike)?`boolean`:[...new Set(r.map(e=>this.typeName(e,t+1)))].slice(0,4).join(` | `);let i=r[0];if(i.flags&n.StringLike)return`string`;if(i.flags&n.NumberLike)return`number`;if(i.flags&n.BooleanLike)return`boolean`;if(i.flags&n.BigIntLike)return`integer`;if(this.isDate(i))return`date-time`;let a=this.element(i);if(a)return t>4?`array`:`${this.typeName(a,t+1)}[]`;let o=i.aliasSymbol?.name??i.symbol?.name;return o&&!o.startsWith(`__`)?o:i.flags&n.Object?`object`:this.checker.typeToString(i).slice(0,60)}example(e,t,n){let r=this.ts.TypeFlags,i=this.present(e)[0];if(!i||n>4)return null;if(i.isStringLiteral?.()||i.isNumberLiteral?.())return i.value;if(i.flags&r.StringLike)return`string`;if(i.flags&r.NumberLike)return 0;if(i.flags&r.BooleanLike)return!1;if(this.isDate(i))return`2026-01-01T00:00:00Z`;let a=this.element(i);return a?[this.example(a,t,n+1)]:i.flags&(r.Object|r.Intersection)?Object.fromEntries(this.checker.getPropertiesOfType(i).slice(0,20).map(e=>[e.name,this.example(this.checker.getTypeOfSymbolAtLocation(e,t),t,n+1)])):null}};async function QD(e,{fromDisk:t=!1}={}){let n=_.resolve(e);if(!(await p(n)).isDirectory())throw Error(`${n} is not a folder`);let r=(/* @__PURE__ */ new Date()).toISOString(),i=[],a=t?null:await RS(n);!t&&!a&&C(_.join(n,`.git`))&&i.push(`No main or master branch found: read the files on disk instead`);let o=a?await Ex(n,a.ref):await Tx(n),s=await CS(o),[c,l,u,d,f,m,h,g]=await Promise.all([BS(n,i,a?.ref??null),SD(o),Tw(o),TS(o,s),MS(o),tD(o),TE(o),GD(o)]),v=await ST(o,u),y=await hE(o,v,c.name),b=new Set(v.map(e=>e.provider)),x=kT([...h.tables,...h.objects],[...v,...y.resources.filter(e=>!b.has(e.provider))]).map(e=>{let t=y.projects.get(e.provider);return t?{...e,projects:[...t].sort()}:e}),S=g.filter(e=>!m.some(t=>ND(t.method,t.path)===ND(e.method,e.path)));return YD(n,S,o.warnings),{scannedAt:r,root:n,repo:{...c,languages:_E(o.files),readme:l},dependencies:u,docs:d,agentInstructions:f,contracts:[...m,...S,...h.tables,...h.objects,...y.contracts],resources:x,docsConfig:{alwaysLoad:!!s.alwaysLoad},warnings:[...i,...o.warnings]}}function $D(e){let t=(e,t,n=`${t}s`)=>e?`${e} ${e===1?t:n}`:``;return[t(e.docs,`doc`)+(e.docsChanged&&e.docsChanged<e.docs?` (${e.docsChanged} changed)`:``),t(e.dependencies,`dependency`,`dependencies`),t(e.contracts,`contract`),t(e.resources,`service`)].filter(Boolean).join(` · `)||`nothing to import yet`}function eO(e){let{scannedRef:t,headSha:n}=e.repo;if(!t)return`files on disk`;let r=t.replace(/^origin\//,``);return n?`${r} @ ${n.slice(0,7)}`:r}async function tO(e,t,{quiet:n=!1,source:r=`connector`,name:i,restore:a}={}){await zS(e);let o=await QD(e),s=(i??t.repoName)?.trim();s&&Object.assign(o.repo,{name:s,nameFromConfig:!0}),a&&Object.assign(o.repo,{restore:!0});let c=await new Wr(await ux()).call(`sync_repo`,{p_project:t.projectId,p_snapshot:o,p_source:r});if(!n){Hx(`Synced ${Rx(o.repo.name)} to ${Rx(t.name)} ${Q(`from ${eO(o)}`)}`),Ux(Q($D(c)));for(let e of o.warnings)Ux(Q(`! ${e}`))}return{snapshot:o,result:c}}async function nO(e){return FS(await Tx(e))}const rO=26214400,iO=e=>`${(e/1024/1024).toFixed(1)} MB`;async function aO(e,t,{quiet:n=!1}={}){if(!t.folder)return;let{docs:r,unsupported:i}=await nO(e),a=e=>Buffer.byteLength(e.body),o=r.reduce((e,t)=>e+a(t),0);if(o>rO){let t=/* @__PURE__ */ new Map;for(let e of r){let n=e.path.includes(`/`)?`${e.path.split(`/`)[0]}/`:e.path;t.set(n,(t.get(n)??0)+a(e))}let n=[...t].sort((e,t)=>t[1]-e[1]).slice(0,3).map(([e,t])=>`${e} (${iO(t)})`).join(`, `);throw new qx(`The documents outside the repos add up to ${iO(o)}, over the ${iO(rO)} a sync takes. The biggest: ${n}. List what Quirl should skip in ${x(v(e),`.quirlignore`)}, like .gitignore.`)}let s=new Wr(await ux()),c={p_project:t.projectId,p_folder:t.folder},l=await s.call(`folder_doc_hashes`,c),u=r.filter(e=>l[e.path]!==e.contentHash),d=0;for(let t=0;t<u.length;){let n=[],r=0;for(;t<u.length;){let e=u[t];if(n.length&&r+a(e)>2097152)break;n.push(e),r+=a(e),t++}let i=await s.call(`sync_folder_docs`,{...c,p_folder_name:v(e),p_docs:n});d+=i.docsChanged}let f={...await s.call(`sync_folder_finish`,{...c,p_paths:r.map(e=>e.path)}),docsChanged:d};return n||(Hx(`Synced the documents in ${Rx(`${v(e)}/`)} outside the repos`),Ux(Q(`${f.docs} docs (${f.docsChanged} changed${f.archived?`, ${f.archived} removed`:``})`)),i.length&&Ux(Q(`! ${i.length} PDF/Office files skipped: only markdown and text are read for now`))),f}async function oO(e={}){let t=await mx();if(!t)throw new qx("This folder isn't linked to a Quirl project. Run `quirl init`.");let n=dx(t.link),r=n.length?n.map(e=>({root:x(t.root,e.path),name:e.name})):[{root:t.root,name:void 0}],i=r.length+ +!!t.link.folder,a=0;for(let{root:o,name:s}of r)try{let r=n.length?await mx(o):null,i=s??(r?.root===o?r.link.repoName:void 0);await tO(o,t.link,{...e,name:i})}catch(e){if(a++,i===1)throw e;let n=S(t.root,o)||`.`;console.error(`${Bx(`✗`)} ${n}: ${Mx(e)}`)}if(t.link.folder)try{await aO(t.root,t.link,e)}catch(e){a++,console.error(`${Bx(`✗`)} documents in ${v(t.root)}/: ${Mx(e)}`)}if(a)throw new qx(`${a} of ${i} parts didn't sync.`)}async function sO(e){let t=fx(),n=await tS(t),r=n.length?n:[t],i=r.length>1||r[0]!==t,a=e=>S(t,e)||v(t),o=h(),s=t.startsWith(o)?`~${t.slice(o.length)}`:t;if(console.log(`\n🌀 ${Rx(`Quirl`)} ${Q(`·`)} connecting ${Rx(s)}`),i&&(Wx(`📁`,`Found ${r.length} ${r.length===1?`repo`:`repos`}`),Gx(Q(r.map(a).join(` · `))),!await Yx(` Import all of them into one project?`,!0)))throw new qx("Nothing imported. Run `quirl init` inside the repo you want instead.");let c=!1;if(i&&!n.includes(t)){let{docs:e,unsupported:n}=await nO(t);if(e.length){Wx(`📄`,`Also found ${e.length} ${e.length===1?`document`:`documents`} outside the repos`);for(let t of e.slice(0,8))Gx(Q(t.path));e.length>8&&Gx(Q(`…and ${e.length-8} more`)),n.length&&Gx(Q(`(${n.length} PDF/Office files can't be read yet and are skipped)`)),c=await Yx(` Import them too? Everyone on the project will be able to read them.`,!0)}}await sx()||await hS({quiet:!0});let l=await lO((await new Wr(await ux()).whoami()).projects,e.project??(await mx(t))?.link.project);if(l.role===`stakeholder`)throw new qx(`You're a stakeholder on ${l.name}; ask an admin or dev to run \`quirl init\`.`);let u={project:l.slug,projectId:l.id,name:l.name};Wx(`🔗`,`Linked to ${Rx(l.name)} ${Q(`· ${l.organization}`)}`);let d=e.claude!==!1,f=e.hooks??await Yx(` Sync with Quirl on every git push?`,!0);Wx(`📦`,`Importing docs, dependencies and schemas`);let p=[],m=i?await mx(t):null,g=new Map((m?.root===t?dx(m.link):[]).filter(e=>e.name).map(e=>[e.path,e.name]));for(let e of r){let t=Kx(`Reading ${a(e)}…`);try{let n=await mx(e),r=(n?.root===e?n.link.repoName:void 0)??g.get(a(e));r&&g.set(a(e),r);let i=r?{...u,repoName:r}:u;await hx(e,i);let{snapshot:o,result:s}=await tO(e,i,{quiet:!0,restore:!0});d&&await cO(e,l.name),f&&await mS(e),t.stop(),Gx(`${zx(`✓`)} ${Rx(a(e))} ${Q(`(${eO(o)})`)} ${Q($D(s))}`);for(let e of o.warnings)Gx(Q(` ! ${e}`));p.push(e)}catch(n){t.stop(),Gx(`${Bx(`✗`)} ${Rx(a(e))} ${Mx(n)}`)}}if(!p.length)throw new qx(`No repo was imported.`);if(i){let e=p.map(e=>{let t=g.get(a(e));return t?{path:a(e),name:t}:a(e)}),n=m,r={...u,repos:e,folder:c?n?.root===t&&n.link.folder||ee():void 0};if(await hx(t,r),c)try{let e=await aO(t,r,{quiet:!0});Gx(`${zx(`✓`)} ${Rx(`documents outside the repos`)} ${Q(`${e?.docs??0} docs`)}`)}catch(e){Gx(`${Bx(`✗`)} ${Rx(`documents outside the repos`)} ${Mx(e)}`)}d&&!p.includes(t)&&await cO(t,l.name,p.map(a))}let _=aS().portable;d&&(Wx(`🤖`,`Connected Claude Code`),Gx(Q(`.mcp.json the quirl tools`)),Gx(Q(`.claude/settings.json the briefing, loaded as each session starts`)),Gx(Q(`CLAUDE.md when to use Quirl`))),f&&Wx(`🪝`,`Quirl syncs on every ${Rx(`git push`)}`);let y=r.length-p.length,b=`.quirl .mcp.json .claude/settings.json CLAUDE.md`;Wx(y?`⚠️ `:`🎉`,y?`Done, but ${y} of ${r.length} repos failed. Fix them and run ${Rx(`quirl init`)} again.`:Rx(`All set!`)),Gx(d&&!_?Q(`Don't commit ${b} yet: they point at this checkout until the CLI is installed.`):`${Q(`1.`)} Commit what was added${i?` in each repo`:``}: ${Vx(`git add ${b}`)}`),Gx(`${Q(d&&!_?`→`:`2.`)} Start Claude Code here and approve the ${Rx(`quirl`)} server when it asks.`),i&&!p.includes(t)&&Gx(Q("Run `quirl sync` here to sync every repo at once.")),console.log(``)}async function cO(e,t,n=[]){await dS(e),await fS(e),await pS(e,t,n)}async function lO(e,t){if(!e.length)throw new qx(`You aren't on any Quirl project yet. Ask an admin to invite you.`);if(t){let n=e.find(e=>e.slug===t||e.id===t);if(!n)throw new qx(`No project "${t}" among yours: ${e.map(e=>e.slug).join(`, `)}.`);return n}if(e.length===1)return e[0];Wx(`🗂️ `,`Which project is this part of?`);for(let[t,n]of e.entries())Gx(`${Vx(String(t+1))} ${n.name} ${Q(`· ${n.organization} · ${n.role}`)}`);let n=e[Number(await Jx(` Project [1-${e.length}]: `))-1];if(!n)throw new qx("No project picked. Run `quirl init --project <slug>`.");return n}const uO=`${Rx(`quirl`)} ${Q(tx)}: connect a repo to Quirl
379
381
 
380
382
  quirl init [--project <slug>] [--hooks|--no-hooks] [--no-claude]
381
383
  Link this repo, import it, and connect Claude Code
@@ -388,4 +390,4 @@ n?this.stack.push(n):(yield*this.pop(),yield*this.step())}else{let t=this.peek(2
388
390
  quirl logout Forget this machine's key
389
391
  quirl whoami Show who you're signed in as
390
392
  quirl mcp Run the MCP server (used by Claude Code)
391
- `;async function $D(){let[e,...n]=process.argv.slice(2),{values:r,positionals:i}=t({args:n,allowNegative:!0,allowPositionals:!0,options:{all:{type:`boolean`},project:{type:`string`},hooks:{type:`boolean`},claude:{type:`boolean`},quiet:{type:`boolean`},hook:{type:`boolean`},source:{type:`string`}}});switch(e){case`init`:return YD({project:r.project,hooks:r.hooks,claude:r.claude});case`sync`:return JD({quiet:r.quiet,source:r.source});case`export`:return eS({dir:i[0],all:r.all});case`context`:return Fx({hook:r.hook});case`login`:await hS();return;case`logout`:return await lx(),Hx(`Signed out on this machine.`),Ux(Q(`The key still exists until you revoke it under Organization > Access keys in Quirl (${rx().appUrl}).`));case`whoami`:{if(!await sx())throw new qx("Not signed in. Run `quirl login`.");let e=await new Wr(await ux()).whoami();console.log(Rx(e.email));for(let t of e.projects)Ux(`${t.name} ${Q(`${t.slug} · ${t.organization} · ${t.role}`)}`);let t=await mx();t&&Ux(Q(`This folder: ${t.link.name}`));return}case`mcp`:{let e=await mx();if(!e)throw new qx("This folder isn't linked to a Quirl project. Run `quirl init`.");return ex({...await ux(),project:e.link.projectId,version:tx})}case void 0:case`help`:case`--help`:case`-h`:process.stdout.write(QD);return;case`--version`:case`-v`:return console.log(tx);default:throw new qx(`Unknown command "${e}".\n\n${QD}`)}}$D().catch(e=>{let t=e instanceof qx?e.message:Mx(e);console.error(`${Bx(`✗`)} ${t}`),process.exit(1)});export{};
393
+ `;async function dO(){let[e,...n]=process.argv.slice(2),{values:r,positionals:i}=t({args:n,allowNegative:!0,allowPositionals:!0,options:{all:{type:`boolean`},project:{type:`string`},hooks:{type:`boolean`},claude:{type:`boolean`},quiet:{type:`boolean`},hook:{type:`boolean`},source:{type:`string`}}});switch(e){case`init`:return sO({project:r.project,hooks:r.hooks,claude:r.claude});case`sync`:return oO({quiet:r.quiet,source:r.source});case`export`:return eS({dir:i[0],all:r.all});case`context`:return Fx({hook:r.hook});case`login`:await hS();return;case`logout`:return await lx(),Hx(`Signed out on this machine.`),Ux(Q(`The key still exists until you revoke it under Organization > Access keys in Quirl (${rx().appUrl}).`));case`whoami`:{if(!await sx())throw new qx("Not signed in. Run `quirl login`.");let e=await new Wr(await ux()).whoami();console.log(Rx(e.email));for(let t of e.projects)Ux(`${t.name} ${Q(`${t.slug} · ${t.organization} · ${t.role}`)}`);let t=await mx();t&&Ux(Q(`This folder: ${t.link.name}`));return}case`mcp`:{let e=await mx();if(!e)throw new qx("This folder isn't linked to a Quirl project. Run `quirl init`.");return ex({...await ux(),project:e.link.projectId,version:tx})}case void 0:case`help`:case`--help`:case`-h`:process.stdout.write(uO);return;case`--version`:case`-v`:return console.log(tx);default:throw new qx(`Unknown command "${e}".\n\n${uO}`)}}dO().catch(e=>{let t=e instanceof qx?e.message:Mx(e);console.error(`${Bx(`✗`)} ${t}`),process.exit(1)});export{};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quirl-cli",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "Connect a repo to Quirl, the team's source of truth for what the product does.",
5
5
  "license": "UNLICENSED",
6
6
  "homepage": "https://quirl.io",