Compare commits

..

1 Commits

Author SHA1 Message Date
George He defb9e3ecb Surface parse errors 2025-08-26 12:16:31 -07:00
29 changed files with 2397 additions and 4302 deletions
+2
View File
@@ -19,6 +19,8 @@ jobs:
uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
with:
version: 10
- name: Setup Node.js
uses: actions/setup-node@v4
@@ -1,4 +1,4 @@
name: Lint
name: Lint - Python
on:
push:
@@ -29,18 +29,7 @@ jobs:
- name: Set up Python
run: uv python install ${{ matrix.python-version }}
- uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: "ts/llama_cloud_services/.nvmrc"
- name: Install dependencies
run: pnpm install --no-frozen-lockfile
- name: Run linter
shell: bash
working-directory: py
run: uv run -- pre-commit run -a
# the js checks are run roundaboutly through lint-staged, and -a doesn't run it. Run them directly.
- run: pnpm -w --filter llama-cloud-services run lint
- run: pnpm -w --filter llama-cloud-services run format:check
+37
View File
@@ -0,0 +1,37 @@
name: Lint - TypeScript
on:
push:
branches:
- main
paths:
- "ts/**"
pull_request:
paths:
- "ts/**"
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_REMOTE_ONLY: true
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
with:
version: 10
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: "ts/llama_cloud_services/.nvmrc"
- name: Install dependencies
run: pnpm install --no-frozen-lockfile
- name: Run lint
working-directory: ts/llama_cloud_services/
run: pnpm run lint
- name: Run Prettier
working-directory: ts/llama_cloud_services/
run: pnpm run format
+4 -2
View File
@@ -13,6 +13,8 @@ jobs:
uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
with:
version: 10
- name: Setup Node.js
uses: actions/setup-node@v4
@@ -47,6 +49,6 @@ jobs:
uses: ncipollo/release-action@v1
with:
artifacts: "ts/llama_cloud_services/llama-cloud-services*.tgz"
name: Release ${{ github.ref_name }} - LlamaCloud Services TS
generateReleaseNotes: true
name: Release ${{ github.ref }} - LlamaCloud Services TS
bodyFile: "ts/llama_cloud_services/CHANGELOG.md"
token: ${{ secrets.GITHUB_TOKEN }}
+7 -4
View File
@@ -1,4 +1,4 @@
name: Test - TypeScript
name: Lint - TypeScript
on:
push:
@@ -23,14 +23,17 @@ jobs:
steps:
- uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
with:
version: 10
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: "ts/llama_cloud_services/.nvmrc"
- name: Install dependencies
run: pnpm -r install --no-frozen-lockfile
- name: Build package
run: pnpm --filter llama-cloud-services build
run: pnpm install --no-frozen-lockfile
- name: Run Build
working-directory: ts/llama_cloud_services/
run: pnpm build
- name: Run Tests
working-directory: ts/llama_cloud_services/
run: pnpm test
+4 -6
View File
@@ -60,13 +60,11 @@ repos:
additional_dependencies: [black==23.10.1]
# Using PEP 8's line length in docs prevents excess left/right scrolling
args: [--line-length=79]
- repo: local
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.0.3
hooks:
- id: lint-staged
name: Run lint-staged for TS files
entry: pnpm -w exec lint-staged
language: system
pass_filenames: false
- id: prettier
exclude: ^(uv.lock|ts/llama_cloud_services/pnpm-lock.yaml|ts/e2e-tests)
- repo: https://github.com/codespell-project/codespell
rev: v2.2.6
hooks:
+1 -1
View File
@@ -18,7 +18,7 @@ versions need to be kept consistent to sidecar it with `llama_cloud_services`. B
You can also do this with `./scripts/version-bump.py set 0.x.x` if you have `uv` installed.
Once the change is merged, push a tag `git tag -a v0.x.x -m 0.x.x` and `git push origin v0.x.x`.
Once the change is merged, push a tag `git tag -a v0.x.x -m 0.x.x` and `git push origin 0.x.x`.
This tagging step can be done with `./scripts/version-bump tag`.
-1
View File
@@ -5,6 +5,5 @@ In this folder you will find several python notebooks that contain examples rega
- [LlamaParse](./parse/)
- [LlamaExtract](./extract/)
- [LlamaReport](./report/)
- [LlamaCloudIndex](./index/)
Follow the instructions in each notebook to get started!
@@ -1,404 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Inline Citations with LlamaCloud with Streaming\n",
"In this notebook we show you how to perform inline citations with LlamaCloud. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Setup\n",
"\n",
"Install core packages, download files. You will need to upload these documents to LlamaCloud."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%pip install llama-index-core llama-cloud-services llama-index-llms-openai"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# download Apple\n",
"!wget \"https://s2.q4cdn.com/470004039/files/doc_earnings/2023/q4/filing/_10-K-Q4-2023-As-Filed.pdf\" -O data/apple_2023.pdf\n",
"!wget \"https://s2.q4cdn.com/470004039/files/doc_financials/2022/q4/_10-K-2022-(As-Filed).pdf\" -O data/apple_2022.pdf\n",
"!wget \"https://s2.q4cdn.com/470004039/files/doc_financials/2021/q4/_10-K-2021-(As-Filed).pdf\" -O data/apple_2021.pdf\n",
"!wget \"https://s2.q4cdn.com/470004039/files/doc_financials/2020/ar/_10-K-2020-(As-Filed).pdf\" -O data/apple_2020.pdf\n",
"!wget \"https://www.dropbox.com/scl/fi/i6vk884ggtq382mu3whfz/apple_2019_10k.pdf?rlkey=eudxh3muxh7kop43ov4bgaj5i&dl=1\" -O data/apple_2019.pdf\n",
"\n",
"# download Tesla\n",
"!wget \"https://ir.tesla.com/_flysystem/s3/sec/000162828024002390/tsla-20231231-gen.pdf\" -O data/tesla_2023.pdf\n",
"!wget \"https://ir.tesla.com/_flysystem/s3/sec/000095017023001409/tsla-20221231-gen.pdf\" -O data/tesla_2022.pdf\n",
"!wget \"https://www.dropbox.com/scl/fi/ptk83fmye7lqr7pz9r6dm/tesla_2021_10k.pdf?rlkey=24kxixeajbw9nru1sd6tg3bye&dl=1\" -O data/tesla_2021.pdf\n",
"!wget \"https://ir.tesla.com/_flysystem/s3/sec/000156459021004599/tsla-10k_20201231-gen.pdf\" -O data/tesla_2020.pdf\n",
"!wget \"https://ir.tesla.com/_flysystem/s3/sec/000156459020004475/tsla-10k_20191231-gen_0.pdf\" -O data/tesla_2019.pdf"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Some OpenAI and LlamaParse details. The OpenAI LLM is used for response synthesis."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# llama-parse is async-first, running the async code in a notebook requires the use of nest_asyncio\n",
"import nest_asyncio\n",
"\n",
"nest_asyncio.apply()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"\n",
"# API access to llama-cloud\n",
"os.environ[\"LLAMA_CLOUD_API_KEY\"] = \"\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Using OpenAI API for embeddings/llms\n",
"os.environ[\"OPENAI_API_KEY\"] = \"\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Load Documents into LlamaCloud\n",
"\n",
"The first order of business is to download the 5 Apple and Tesla 10Ks and upload them into LlamaCloud.\n",
"\n",
"You can easily do this by creating a pipeline and uploading docs via the \"Files\" mode.\n",
"\n",
"After this is done, proceed to the next section."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Define NodeCitationPostProcessor\n",
"Add node id to metadata to match the citation links"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from typing import List, Optional\n",
"\n",
"from llama_index.core import QueryBundle\n",
"from llama_index.core.postprocessor.types import BaseNodePostprocessor\n",
"from llama_index.core.schema import NodeWithScore\n",
"\n",
"\n",
"class NodeCitationProcessor(BaseNodePostprocessor):\n",
" \"\"\"\n",
" Append node_id into metadata for citation purpose.\n",
" Config SYSTEM_CITATION_PROMPT in your runtime environment variable to enable this feature.\n",
" \"\"\"\n",
"\n",
" def _postprocess_nodes(\n",
" self,\n",
" nodes: List[NodeWithScore],\n",
" query_bundle: Optional[QueryBundle] = None,\n",
" ) -> List[NodeWithScore]:\n",
" for node_score in nodes:\n",
" node_score.node.metadata[\"node_id\"] = node_score.node.node_id\n",
" return nodes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Define System Citation Prompt\n",
"Modify the system prompt to add the citation links based on the metadata"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"SYSTEM_CITATION_PROMPT = \"\"\"You have provided information from a knowledge base that has been passed to you in nodes of information.\n",
"Each node has useful metadata such as node ID, file name, page, etc.\n",
"Please add the citation to the data node for each sentence or paragraph that you reference in the provided information.\n",
"The citation format is: . [citation:<node_id>]()\n",
"Where the <node_id> is the unique identifier of the data node.\n",
"\n",
"Example:\n",
"We have two nodes:\n",
" node_id: xyz\n",
" file_name: llama.pdf\n",
" \n",
" node_id: abc\n",
" file_name: animal.pdf\n",
"\n",
"User question: Tell me a fun fact about Llama.\n",
"Your answer:\n",
"A baby llama is called \"Cria\" [citation:xyz]().\n",
"It often live in desert [citation:abc]().\n",
"It\\\\'s cute animal.\"\"\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Define LlamaCloud Retriever over Documents\n",
"\n",
"In this section we define LlamaCloud Retriever over these documents."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from llama_cloud_services import LlamaCloudIndex\n",
"import os\n",
"\n",
"index = LlamaCloudIndex(\n",
" name=\"apple_demo\",\n",
" project_name=\"llamacloud_demo\",\n",
" api_key=os.environ[\"LLAMA_CLOUD_API_KEY\"],\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Define chunk retriever\n",
"\n",
"The chunk-level retriever does vector search with a final reranked set of `rerank_top_n=5`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"chunk_retriever = index.as_retriever(retrieval_mode=\"chunks\", rerank_top_n=5)\n",
"from llama_index.core.query_engine import RetrieverQueryEngine\n",
"from llama_index.llms.openai import OpenAI\n",
"\n",
"llm = OpenAI(model=\"gpt-4o-mini\", system_prompt=SYSTEM_CITATION_PROMPT)\n",
"query_engine = RetrieverQueryEngine.from_args(\n",
" chunk_retriever,\n",
" llm=llm,\n",
" response_mode=\"tree_summarize\",\n",
" node_postprocessors=[NodeCitationProcessor()],\n",
" streaming=True,\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Generate final output matching citations with page labela\n",
"Given the found nodes, match the page assigned and build a final url"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import re\n",
"from typing import Generator\n",
"\n",
"# Accepts [citation:ID] and [citation:ID]() (spaces/newlines allowed, case-insensitive)\n",
"_CITATION_RX = re.compile(\n",
" r\"\\[\\s*citation\\s*:\\s*([^\\]]+?)\\s*\\]\\s*(?:\\(\\s*\\))?\", re.IGNORECASE\n",
")\n",
"# Detects a trailing, incomplete \"[citation:\" at the END of a string\n",
"_INCOMPLETE_RX = re.compile(r\"\\[\\s*citation\\s*:\\s*[^\\]]*$\", re.IGNORECASE)\n",
"\n",
"\n",
"def stream_citations_with_sources(\n",
" resp, check_every: int = 64\n",
") -> Generator[str, None, None]:\n",
" \"\"\"\n",
" Incrementally replace [citation:ID] / [citation:ID]() with:\n",
" [n](https://fake.url/SampleFile#page=<page_label>)\n",
" Emits only the *new* safe prefix each time; never flushes partial tags.\n",
" \"\"\"\n",
"\n",
" # Build id -> page_label now (OK if empty; we'll use 'unknown')\n",
" nodes = getattr(resp, \"source_nodes\", []) or []\n",
" id_to_label = {str(n.id_): n.metadata.get(\"page_label\", \"unknown\") for n in nodes}\n",
"\n",
" order: dict[str, int] = {}\n",
" counter = [1] # mutable to avoid nonlocal\n",
"\n",
" def _link_for(cid: str) -> str:\n",
" cid = cid.strip()\n",
" if cid not in order:\n",
" order[cid] = counter[0]\n",
" counter[0] += 1\n",
" n = order[cid]\n",
" page = id_to_label.get(cid, \"unknown\")\n",
" # TODO: replace fake URL with node.metadata[\"web_url\"] when available\n",
" return f\"[{n}](https://fake.url/SampleFile#page={page})\"\n",
"\n",
" def _replace_complete(text: str) -> str:\n",
" def _repl(m: re.Match) -> str:\n",
" return _link_for(m.group(1))\n",
"\n",
" # Replace only complete tags; do NOT strip any incomplete tail here\n",
" return _CITATION_RX.sub(_repl, text)\n",
"\n",
" acc = \"\" # full accumulated text so far\n",
" emitted_upto = 0 # index in acc we've already emitted\n",
" since = 0\n",
"\n",
" for chunk in resp.response_gen:\n",
" acc += chunk\n",
" acc = _replace_complete(acc) # replace anywhere tags became complete\n",
" since += len(chunk)\n",
"\n",
" # Find safe end: don't include a trailing incomplete \"[citation:\"\n",
" safe_end = len(acc)\n",
" m = _INCOMPLETE_RX.search(acc)\n",
" if m and m.end() == len(acc):\n",
" safe_end = m.start()\n",
"\n",
" # Emit only the newly available safe prefix\n",
" if safe_end > emitted_upto and (\n",
" \"]\" in chunk or \")\" in chunk or since >= check_every\n",
" ):\n",
" yield acc[emitted_upto:safe_end]\n",
" emitted_upto = safe_end\n",
" since = 0\n",
"\n",
" # End of stream: drop any dangling start, replace once more, emit the rest\n",
" tail = acc[emitted_upto:]\n",
" if tail:\n",
" # Remove trailing incomplete start if present\n",
" m = _INCOMPLETE_RX.search(tail)\n",
" if m and m.end() == len(tail):\n",
" tail = tail[: m.start()]\n",
" tail = _replace_complete(tail)\n",
" if tail:\n",
" yield tail"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Query it"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"query = \"What are the tiny risks for apple\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<pre>The Company faces several risks that could be considered \"tiny\" or less significant in the broader context of its operations. These include:\n",
"\n",
"1. **Credit Risk**: The Company is exposed to credit risk on its trade accounts receivable and vendor non-trade receivables, particularly during periods of economic downturns. This risk is heightened when economic conditions worsen, which could lead to difficulties in collecting receivables [1](https://fake.url/SampleFile#page=19).\n",
"\n",
"2. **Dependence on Outsourcing Partners**: The Company relies on outsourcing partners for manufacturing and logistics. While this can lower operating costs, it also reduces direct control over production and distribution, which could lead to quality issues or supply disruptions [2](https://fake.url/SampleFile#page=11).\n",
"\n",
"3. **Single-Source Suppliers**: The Company depends on single-source suppliers for many components, which exposes it to supply and pricing risks. Any failure of these suppliers to perform can negatively impact the Company's operations [2](https://fake.url/SampleFile#page=11).\n",
"\n",
"4. **Volatility in Stock Price**: The Company's stock price has experienced significant volatility in the past and may continue to do so. This volatility can be influenced by factors unrelated to the Company's operating performance, which could affect investor confidence [3](https://fake.url/SampleFile#page=8).\n",
"\n",
"5. **Impact of Political and Economic Conditions**: The Companys operations can be affected by political events, trade disputes, and other international issues, which could disrupt commerce and impact its business [3](https://fake.url/SampleFile#page=8).\n",
"\n",
"While these risks may not be the most significant compared to larger operational or financial risks, they still represent areas where the Company must maintain vigilance to mitigate potential impacts.</pre>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from IPython.display import display, HTML\n",
"\n",
"resp = query_engine.query(query)\n",
"\n",
"buf = []\n",
"handle = display(HTML(\"<pre></pre>\"), display_id=True)\n",
"\n",
"for part in stream_citations_with_sources(resp):\n",
" buf.append(part)\n",
" html = \"<pre>\" + \"\".join(buf) + \"</pre>\"\n",
" handle.update(HTML(html))"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -43,7 +43,7 @@
"source": [
"from llama_cloud_services import LlamaParse\n",
"\n",
"api_key = \"llx-...\" # get from cloud.llamaindex.ai"
"api_key = \"llx-jwAQZL8T38onyL9hKBOXyRtnuCU0Fk3z7tmDhIT3L0GEfohJ\" # get from cloud.llamaindex.ai"
]
},
{
+1
View File
@@ -75,6 +75,7 @@
" adaptive_long_table=True,\n",
" outlined_table_extraction=True,\n",
" output_tables_as_HTML=True,\n",
" api_key=\"llx-jwAQZL8T38onyL9hKBOXyRtnuCU0Fk3z7tmDhIT3L0GEfohJ\",\n",
")\n",
"\n",
"result = await parser.aparse(\"./dcf_template.xlsx\")\n",
-19
View File
@@ -1,19 +0,0 @@
{
"name": "llama-cloud-services-workspace",
"version": "0.0.1",
"description": "",
"private": true,
"keywords": [],
"author": "",
"devDependencies": {
"prettier": "^3.6.2",
"lint-staged": "^15.4.2"
},
"lint-staged": {
"ts/llama_cloud_services/src/**/*.{ts,tsx,js,jsx}": [
"pnpm --filter llama-cloud-services exec eslint --fix",
"pnpm --filter llama-cloud-services exec prettier --write"
]
},
"packageManager": "pnpm@10.11.1+sha512.e519b9f7639869dc8d5c3c5dfef73b3f091094b0a006d7317353c72b124e80e1afd429732e28705ad6bfa1ee879c1fce46c128ccebd3192101f43dd67c667912"
}
-245
View File
@@ -6,15 +6,6 @@ settings:
importers:
.:
devDependencies:
lint-staged:
specifier: ^15.4.2
version: 15.5.2
prettier:
specifier: ^3.6.2
version: 3.6.2
ts/e2e-tests:
devDependencies:
'@types/node':
@@ -838,10 +829,6 @@ packages:
ajv@8.17.1:
resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==}
ansi-escapes@7.0.0:
resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==}
engines: {node: '>=18'}
ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
@@ -946,10 +933,6 @@ packages:
resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
engines: {node: '>=6'}
cli-truncate@4.0.0:
resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==}
engines: {node: '>=18'}
cliui@8.0.1:
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
engines: {node: '>=12'}
@@ -961,17 +944,10 @@ packages:
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
colorette@2.0.20:
resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
commander@13.0.0:
resolution: {integrity: sha512-oPYleIY8wmTVzkvQq10AEok6YcTC4sRUBl8F9gVuwchGVUCTbl/vhLTaQqutuuySYOsu8YTgV+OxKc/8Yvx+mQ==}
engines: {node: '>=18'}
commander@13.1.0:
resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==}
engines: {node: '>=18'}
commondir@1.0.1:
resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==}
@@ -1031,10 +1007,6 @@ packages:
emoji-regex@9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
environment@1.1.0:
resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==}
engines: {node: '>=18'}
es-module-lexer@1.7.0:
resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
@@ -1099,13 +1071,6 @@ packages:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'}
eventemitter3@5.0.1:
resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
execa@8.0.1:
resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
engines: {node: '>=16.17'}
expect-type@1.2.2:
resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==}
engines: {node: '>=12.0.0'}
@@ -1187,14 +1152,6 @@ packages:
resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==}
engines: {node: '>=18'}
get-east-asian-width@1.3.1:
resolution: {integrity: sha512-R1QfovbPsKmosqTnPoRFiJ7CF9MLRgb53ChvMZm+r4p76/+8yKDy17qLL2PKInORy2RkZZekuK0efYgmzTkXyQ==}
engines: {node: '>=18'}
get-stream@8.0.1:
resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==}
engines: {node: '>=16'}
get-tsconfig@4.10.1:
resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==}
@@ -1241,10 +1198,6 @@ packages:
html-escaper@2.0.2:
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
human-signals@5.0.0:
resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
engines: {node: '>=16.17.0'}
ieee754@1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
@@ -1276,14 +1229,6 @@ packages:
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
engines: {node: '>=8'}
is-fullwidth-code-point@4.0.0:
resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==}
engines: {node: '>=12'}
is-fullwidth-code-point@5.1.0:
resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==}
engines: {node: '>=18'}
is-glob@4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
@@ -1306,10 +1251,6 @@ packages:
is-reference@1.2.1:
resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==}
is-stream@3.0.0:
resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
is-unicode-supported@1.3.0:
resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==}
engines: {node: '>=12'}
@@ -1373,19 +1314,6 @@ packages:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'}
lilconfig@3.1.3:
resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
engines: {node: '>=14'}
lint-staged@15.5.2:
resolution: {integrity: sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==}
engines: {node: '>=18.12.0'}
hasBin: true
listr2@8.3.3:
resolution: {integrity: sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==}
engines: {node: '>=18.0.0'}
locate-path@6.0.0:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
@@ -1400,10 +1328,6 @@ packages:
resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==}
engines: {node: '>=18'}
log-update@6.1.0:
resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==}
engines: {node: '>=18'}
loupe@3.2.0:
resolution: {integrity: sha512-2NCfZcT5VGVNX9mSZIxLRkEAegDGBpuQZBy13desuHeVORmBDyAET4TkJr4SjqQy3A8JDofMN6LpkK8Xcm/dlw==}
@@ -1423,9 +1347,6 @@ packages:
resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
engines: {node: '>=10'}
merge-stream@2.0.0:
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
merge2@1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
@@ -1434,10 +1355,6 @@ packages:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
mimic-fn@4.0.0:
resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
engines: {node: '>=12'}
mimic-function@5.0.1:
resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==}
engines: {node: '>=18'}
@@ -1497,10 +1414,6 @@ packages:
node-fetch-native@1.6.7:
resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==}
npm-run-path@5.3.0:
resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
nypm@0.5.4:
resolution: {integrity: sha512-X0SNNrZiGU8/e/zAB7sCTtdxWTMSIO73q+xuKgglm2Yvzwlo8UoC5FNySQFCvl84uPaeADkqHUZUkWy4aH4xOA==}
engines: {node: ^14.16.0 || >=16.10.0}
@@ -1509,10 +1422,6 @@ packages:
ohash@1.1.6:
resolution: {integrity: sha512-TBu7PtV8YkAZn0tSxobKY2n2aAQva936lhRrj6957aDaCf9IEtqsKbgMzXE/F/sjqYOwmrukeORHNLe5glk7Cg==}
onetime@6.0.0:
resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
engines: {node: '>=12'}
onetime@7.0.0:
resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==}
engines: {node: '>=18'}
@@ -1552,10 +1461,6 @@ packages:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'}
path-key@4.0.0:
resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==}
engines: {node: '>=12'}
path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
@@ -1587,11 +1492,6 @@ packages:
resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
engines: {node: '>=12'}
pidtree@0.6.0:
resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==}
engines: {node: '>=0.10'}
hasBin: true
pkg-types@1.3.1:
resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==}
@@ -1658,9 +1558,6 @@ packages:
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
rfdc@1.4.1:
resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
rollup-plugin-dts@6.2.1:
resolution: {integrity: sha512-sR3CxYUl7i2CHa0O7bA45mCrgADyAQ0tVtGSqi3yvH28M+eg1+g5d7kQ9hLvEz5dorK3XVsH5L2jwHLQf72DzA==}
engines: {node: '>=16'}
@@ -1712,14 +1609,6 @@ packages:
resolution: {integrity: sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==}
engines: {node: '>=18'}
slice-ansi@5.0.0:
resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==}
engines: {node: '>=12'}
slice-ansi@7.1.0:
resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==}
engines: {node: '>=18'}
source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
@@ -1738,10 +1627,6 @@ packages:
resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==}
engines: {node: '>=18'}
string-argv@0.3.2:
resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==}
engines: {node: '>=0.6.19'}
string-width@4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'}
@@ -1762,10 +1647,6 @@ packages:
resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
engines: {node: '>=12'}
strip-final-newline@3.0.0:
resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==}
engines: {node: '>=12'}
strip-json-comments@3.1.1:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
@@ -1990,10 +1871,6 @@ packages:
resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
engines: {node: '>=12'}
wrap-ansi@9.0.0:
resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==}
engines: {node: '>=18'}
y18n@5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
@@ -2001,11 +1878,6 @@ packages:
yallist@4.0.0:
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
yaml@2.8.1:
resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==}
engines: {node: '>= 14.6'}
hasBin: true
yargs-parser@21.1.1:
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
engines: {node: '>=12'}
@@ -2679,10 +2551,6 @@ snapshots:
json-schema-traverse: 1.0.0
require-from-string: 2.0.2
ansi-escapes@7.0.0:
dependencies:
environment: 1.1.0
ansi-regex@5.0.1: {}
ansi-regex@6.1.0: {}
@@ -2797,11 +2665,6 @@ snapshots:
cli-spinners@2.9.2: {}
cli-truncate@4.0.0:
dependencies:
slice-ansi: 5.0.0
string-width: 7.2.0
cliui@8.0.1:
dependencies:
string-width: 4.2.3
@@ -2814,12 +2677,8 @@ snapshots:
color-name@1.1.4: {}
colorette@2.0.20: {}
commander@13.0.0: {}
commander@13.1.0: {}
commondir@1.0.1: {}
concat-map@0.0.1: {}
@@ -2858,8 +2717,6 @@ snapshots:
emoji-regex@9.2.2: {}
environment@1.1.0: {}
es-module-lexer@1.7.0: {}
esbuild@0.21.5:
@@ -2967,20 +2824,6 @@ snapshots:
esutils@2.0.3: {}
eventemitter3@5.0.1: {}
execa@8.0.1:
dependencies:
cross-spawn: 7.0.6
get-stream: 8.0.1
human-signals: 5.0.0
is-stream: 3.0.0
merge-stream: 2.0.0
npm-run-path: 5.3.0
onetime: 6.0.0
signal-exit: 4.1.0
strip-final-newline: 3.0.0
expect-type@1.2.2: {}
fast-deep-equal@3.1.3: {}
@@ -3056,10 +2899,6 @@ snapshots:
get-east-asian-width@1.3.0: {}
get-east-asian-width@1.3.1: {}
get-stream@8.0.1: {}
get-tsconfig@4.10.1:
dependencies:
resolve-pkg-maps: 1.0.0
@@ -3114,8 +2953,6 @@ snapshots:
html-escaper@2.0.2: {}
human-signals@5.0.0: {}
ieee754@1.2.1: {}
ignore@5.3.2: {}
@@ -3137,12 +2974,6 @@ snapshots:
is-fullwidth-code-point@3.0.0: {}
is-fullwidth-code-point@4.0.0: {}
is-fullwidth-code-point@5.1.0:
dependencies:
get-east-asian-width: 1.3.1
is-glob@4.0.3:
dependencies:
is-extglob: 2.1.1
@@ -3159,8 +2990,6 @@ snapshots:
dependencies:
'@types/estree': 1.0.8
is-stream@3.0.0: {}
is-unicode-supported@1.3.0: {}
is-unicode-supported@2.1.0: {}
@@ -3224,32 +3053,6 @@ snapshots:
prelude-ls: 1.2.1
type-check: 0.4.0
lilconfig@3.1.3: {}
lint-staged@15.5.2:
dependencies:
chalk: 5.5.0
commander: 13.1.0
debug: 4.4.1
execa: 8.0.1
lilconfig: 3.1.3
listr2: 8.3.3
micromatch: 4.0.8
pidtree: 0.6.0
string-argv: 0.3.2
yaml: 2.8.1
transitivePeerDependencies:
- supports-color
listr2@8.3.3:
dependencies:
cli-truncate: 4.0.0
colorette: 2.0.20
eventemitter3: 5.0.1
log-update: 6.1.0
rfdc: 1.4.1
wrap-ansi: 9.0.0
locate-path@6.0.0:
dependencies:
p-locate: 5.0.0
@@ -3263,14 +3066,6 @@ snapshots:
chalk: 5.5.0
is-unicode-supported: 1.3.0
log-update@6.1.0:
dependencies:
ansi-escapes: 7.0.0
cli-cursor: 5.0.0
slice-ansi: 7.1.0
strip-ansi: 7.1.0
wrap-ansi: 9.0.0
loupe@3.2.0: {}
lru-cache@10.4.3: {}
@@ -3291,8 +3086,6 @@ snapshots:
dependencies:
semver: 7.7.2
merge-stream@2.0.0: {}
merge2@1.4.1: {}
micromatch@4.0.8:
@@ -3300,8 +3093,6 @@ snapshots:
braces: 3.0.3
picomatch: 2.3.1
mimic-fn@4.0.0: {}
mimic-function@5.0.1: {}
minimatch@3.1.2:
@@ -3348,10 +3139,6 @@ snapshots:
node-fetch-native@1.6.7: {}
npm-run-path@5.3.0:
dependencies:
path-key: 4.0.0
nypm@0.5.4:
dependencies:
citty: 0.1.6
@@ -3363,10 +3150,6 @@ snapshots:
ohash@1.1.6: {}
onetime@6.0.0:
dependencies:
mimic-fn: 4.0.0
onetime@7.0.0:
dependencies:
mimic-function: 5.0.1
@@ -3416,8 +3199,6 @@ snapshots:
path-key@3.1.1: {}
path-key@4.0.0: {}
path-parse@1.0.7: {}
path-scurry@1.11.1:
@@ -3439,8 +3220,6 @@ snapshots:
picomatch@4.0.3: {}
pidtree@0.6.0: {}
pkg-types@1.3.1:
dependencies:
confbox: 0.1.8
@@ -3493,8 +3272,6 @@ snapshots:
reusify@1.1.0: {}
rfdc@1.4.1: {}
rollup-plugin-dts@6.2.1(rollup@4.46.2)(typescript@5.9.2):
dependencies:
magic-string: 0.30.17
@@ -3565,16 +3342,6 @@ snapshots:
mrmime: 2.0.1
totalist: 3.0.1
slice-ansi@5.0.0:
dependencies:
ansi-styles: 6.2.1
is-fullwidth-code-point: 4.0.0
slice-ansi@7.1.0:
dependencies:
ansi-styles: 6.2.1
is-fullwidth-code-point: 5.1.0
source-map-js@1.2.1: {}
source-map@0.6.1: {}
@@ -3585,8 +3352,6 @@ snapshots:
stdin-discarder@0.2.2: {}
string-argv@0.3.2: {}
string-width@4.2.3:
dependencies:
emoji-regex: 8.0.0
@@ -3613,8 +3378,6 @@ snapshots:
dependencies:
ansi-regex: 6.1.0
strip-final-newline@3.0.0: {}
strip-json-comments@3.1.1: {}
strtok3@10.3.4:
@@ -3821,18 +3584,10 @@ snapshots:
string-width: 5.1.2
strip-ansi: 7.1.0
wrap-ansi@9.0.0:
dependencies:
ansi-styles: 6.2.1
string-width: 7.2.0
strip-ansi: 7.1.0
y18n@5.0.8: {}
yallist@4.0.0: {}
yaml@2.8.1: {}
yargs-parser@21.1.1: {}
yargs@17.7.2:
+1 -2
View File
@@ -1,6 +1,6 @@
from llama_cloud_services.parse import LlamaParse
from llama_cloud_services.report import ReportClient, LlamaReport
from llama_cloud_services.extract import LlamaExtract, ExtractionAgent, SourceText
from llama_cloud_services.extract import LlamaExtract, ExtractionAgent
from llama_cloud_services.constants import EU_BASE_URL
from llama_cloud_services.index import (
LlamaCloudCompositeRetriever,
@@ -14,7 +14,6 @@ __all__ = [
"LlamaReport",
"LlamaExtract",
"ExtractionAgent",
"SourceText",
"EU_BASE_URL",
"LlamaCloudIndex",
"LlamaCloudRetriever",
@@ -17,9 +17,6 @@ from llama_cloud_services.files.client import FileClient
from llama_cloud_services.constants import POLLING_TIMEOUT_SECONDS
from llama_cloud_services.utils import is_terminal_status, augment_async_errors
from llama_index.core.async_utils import DEFAULT_NUM_WORKERS, run_jobs
from llama_cloud_services.beta.classifier.types import (
ClassifyJobResultsWithFiles,
)
class ClassificationOutput(BaseModel):
@@ -55,24 +52,6 @@ class ClassifyClient:
self.file_client = FileClient(client, project_id, organization_id)
self.polling_timeout = polling_timeout
@classmethod
def from_api_key(
cls,
api_key: str,
project_id: Optional[str] = None,
organization_id: Optional[str] = None,
base_url: Optional[str] = None,
) -> "ClassifyClient":
"""
Create a classify client from an API key.
"""
client = AsyncLlamaCloud(token=api_key, base_url=base_url)
return cls(
client,
project_id,
organization_id,
)
async def acreate_classify_job(
self,
rules: list[ClassifierRule],
@@ -173,12 +152,11 @@ class ClassifyClient:
file_input_path: str,
parsing_configuration: Optional[ClassifyParsingConfiguration] = None,
raise_on_error: bool = True,
) -> ClassifyJobResultsWithFiles:
) -> ClassifyJobResults:
file = await self.file_client.upload_file(file_input_path)
results = await self.aclassify_file_ids(
return await self.aclassify_file_ids(
rules, [file.id], parsing_configuration, raise_on_error
)
return ClassifyJobResultsWithFiles.from_classify_job_results(results, [file])
def classify_file_path(
self,
@@ -186,7 +164,7 @@ class ClassifyClient:
file_input_path: str,
parsing_configuration: Optional[ClassifyParsingConfiguration] = None,
raise_on_error: bool = True,
) -> ClassifyJobResultsWithFiles:
) -> ClassifyJobResults:
with augment_async_errors():
return asyncio.run(
self.aclassify_file_path(
@@ -202,7 +180,7 @@ class ClassifyClient:
raise_on_error: bool = True,
workers: int = DEFAULT_NUM_WORKERS,
show_progress: bool = False,
) -> ClassifyJobResultsWithFiles:
) -> ClassifyJobResults:
coroutines = [self.file_client.upload_file(path) for path in file_input_paths]
files: list[File] = await run_jobs(
coroutines,
@@ -210,10 +188,9 @@ class ClassifyClient:
workers=workers,
desc="Uploading files for classification",
)
results = await self.aclassify_file_ids(
return await self.aclassify_file_ids(
rules, [file.id for file in files], parsing_configuration, raise_on_error
)
return ClassifyJobResultsWithFiles.from_classify_job_results(results, files)
def classify_file_paths(
self,
@@ -221,7 +198,7 @@ class ClassifyClient:
file_input_paths: list[str],
parsing_configuration: Optional[ClassifyParsingConfiguration] = None,
raise_on_error: bool = True,
) -> ClassifyJobResultsWithFiles:
) -> ClassifyJobResults:
with augment_async_errors():
return asyncio.run(
self.aclassify_file_paths(
@@ -1,59 +0,0 @@
from llama_cloud.types.classify_job_results import ClassifyJobResults
from llama_cloud.types.file_classification import FileClassification
from llama_cloud.types.file import File
class FileClassificationWithFile(FileClassification):
"""
File classification with file object.
"""
file: File
@classmethod
def from_file_classification(
cls, file_classification: FileClassification, file: File
) -> "FileClassificationWithFile":
if file_classification.file_id != file.id:
raise ValueError(
f"File classification ID {file_classification.id} does not match file ID {file.id}"
)
ctor_args = {
**file_classification.dict(),
"file": file,
}
return cls(**ctor_args)
class ClassifyJobResultsWithFiles(ClassifyJobResults):
"""
Classify job results with file objects.
"""
items: list[FileClassificationWithFile]
@classmethod
def from_classify_job_results(
cls, classify_job_results: ClassifyJobResults, files: list[File]
) -> "ClassifyJobResultsWithFiles":
if len(classify_job_results.items) != len(files):
raise ValueError(
f"Number of classify job results {len(classify_job_results.items)} does not match number of files {len(files)}"
)
# create mapping of file classification result to file object
file_id_to_file: dict[str, File] = {file.id: file for file in files}
file_classification_to_file: list[tuple[FileClassification, File]] = []
for item in classify_job_results.items:
if item.file_id not in file_id_to_file:
raise ValueError(
f"File classification result {item.id} has file ID {item.file_id} that does not match any provided file ID"
)
file_classification_to_file.append((item, file_id_to_file[item.file_id]))
# create a list of file classification with file objects
ctor_args = classify_job_results.dict()
ctor_args["items"] = [
FileClassificationWithFile.from_file_classification(item, file)
for item, file in file_classification_to_file
]
return cls(**ctor_args)
+13 -4
View File
@@ -1015,11 +1015,20 @@ class LlamaParse(BasePydanticReader):
try:
url = build_url(JOB_UPLOAD_ROUTE, self.organization_id, self.project_id)
resp = await make_api_request(self.aclient, "POST", url, timeout=self.max_timeout, files=files, data=data) # type: ignore
resp.raise_for_status() # this raises if status is not 2xx
# Note: make_api_request already calls raise_for_status(), so no need to call it again
return resp.json()["id"]
except httpx.HTTPStatusError as err: # this catches it
except httpx.HTTPStatusError as err: # this catches HTTP status errors
msg = f"Failed to parse the file: {err.response.text}"
raise Exception(msg) from err # this preserves the exception context
except Exception as err: # this catches other exceptions like RetryError, ValueError, etc.
# Try to extract meaningful error message from the exception chain
if hasattr(err, '__cause__') and isinstance(err.__cause__, httpx.HTTPStatusError):
# If the exception was caused by an HTTPStatusError, extract the response text
msg = f"Failed to parse the file: {err.__cause__.response.text}"
else:
# For other exceptions, use the string representation
msg = f"Failed to parse the file: {str(err)}"
raise Exception(msg) from err
finally:
if file_handle is not None:
file_handle.close()
@@ -1578,7 +1587,7 @@ class LlamaParse(BasePydanticReader):
resp = await make_api_request(
client, "GET", asset_url, timeout=self.max_timeout
)
resp.raise_for_status()
# Note: make_api_request already calls raise_for_status()
f.write(resp.content)
assets.append(asset)
return assets
@@ -1676,7 +1685,7 @@ class LlamaParse(BasePydanticReader):
res = await make_api_request(
client, "GET", xlsx_url, timeout=self.max_timeout
)
res.raise_for_status()
# Note: make_api_request already calls raise_for_status()
f.write(res.content)
xlsx_list.append(xlsx)
return xlsx_list
-3
View File
@@ -159,9 +159,6 @@ class Page(BaseModel):
durationInSeconds: Optional[float] = Field(
default=None, description="The duration of the audio transcript in seconds."
)
slideSpeakerNotes: Optional[str] = Field(
default=None, description="The speaker notes for the slide."
)
class JobResult(BaseModel):
+12 -1
View File
@@ -11,6 +11,7 @@ from tenacity import (
wait_exponential,
retry_if_exception,
before_sleep_log,
RetryError,
)
from typing import Any, Iterable, Iterator, Optional, List, cast
@@ -300,7 +301,17 @@ async def make_api_request(
response.raise_for_status()
return response
return await _make_request(url, **httpx_kwargs)
try:
return await _make_request(url, **httpx_kwargs)
except RetryError as retry_err:
# Extract the last exception from the retry error to preserve the original error details
if retry_err.last_attempt and retry_err.last_attempt.exception():
last_exception = retry_err.last_attempt.exception()
# Re-raise the original exception to preserve error details like response.text
raise last_exception from retry_err
else:
# Fallback if we can't extract the original exception
raise retry_err
def expand_target_pages(target_pages: str) -> Iterator[int]:
+2 -2
View File
@@ -11,13 +11,13 @@ dev = [
[project]
name = "llama-parse"
version = "0.6.63"
version = "0.6.62"
description = "Parse files into RAG-Optimized formats."
authors = [{name = "Logan Markewich", email = "logan@llamaindex.ai"}]
requires-python = ">=3.9,<4.0"
readme = "README.md"
license = "MIT"
dependencies = ["llama-cloud-services>=0.6.63"]
dependencies = ["llama-cloud-services>=0.6.62"]
[project.scripts]
llama-parse = "llama_parse.cli.main:parse"
+1 -1
View File
@@ -19,7 +19,7 @@ dev = [
[project]
name = "llama-cloud-services"
version = "0.6.63"
version = "0.6.62"
description = "Tailored SDK clients for LlamaCloud services."
authors = [{name = "Logan Markewich", email = "logan@runllama.ai"}]
requires-python = ">=3.9,<4.0"
+4 -42
View File
@@ -2,7 +2,6 @@ import os
import pytest
from llama_cloud.client import AsyncLlamaCloud
from llama_cloud.types import Project, ClassifierRule, ClassifyJobResults
from llama_cloud_services.beta.classifier.types import ClassifyJobResultsWithFiles
from llama_cloud_services.beta.classifier.client import ClassifyClient
from llama_cloud_services.files.client import FileClient
from llama_cloud.errors.unprocessable_entity_error import UnprocessableEntityError
@@ -131,44 +130,6 @@ async def test_classify_file_ids(
assert item.result.type == expected_type
@pytest.mark.asyncio
async def test_classify_file_ids_from_api_key(
e2e_test_settings: EndToEndTestSettings,
file_client: FileClient,
simple_pdf_file_path: str,
research_paper_path: str,
classification_rules: list[ClassifierRule],
):
"""Test classifying files by their IDs"""
# Upload test files first to get their IDs
pdf_file = await file_client.upload_file(simple_pdf_file_path)
research_paper_file = await file_client.upload_file(research_paper_path)
classify_client = ClassifyClient.from_api_key(
api_key=e2e_test_settings.LLAMA_CLOUD_API_KEY.get_secret_value(),
base_url=e2e_test_settings.LLAMA_CLOUD_BASE_URL,
project_id=pdf_file.project_id,
organization_id=e2e_test_settings.LLAMA_CLOUD_ORGANIZATION_ID,
)
# Classify the uploaded files
results = await classify_client.aclassify_file_ids(
rules=classification_rules, file_ids=[pdf_file.id, research_paper_file.id]
)
assert isinstance(results, ClassifyJobResults)
assert len(results.items) == 2
file_id_to_expected_type = {
pdf_file.id: "number",
research_paper_file.id: "research_paper",
}
# Verify each file got classified
for item in results.items:
expected_type = file_id_to_expected_type[item.file_id]
assert item.result.type == expected_type
@parameterize_sync_and_async
@pytest.mark.asyncio
async def test_classify_file_path(
@@ -188,7 +149,7 @@ async def test_classify_file_path(
rules=classification_rules, file_input_path=simple_pdf_file_path
)
assert isinstance(results, ClassifyJobResultsWithFiles)
assert isinstance(results, ClassifyJobResults)
assert len(results.items) == 1
# Verify the file got classified
@@ -219,7 +180,7 @@ async def test_classify_file_paths(
file_input_paths=[simple_pdf_file_path, research_paper_path],
)
assert isinstance(results, ClassifyJobResultsWithFiles)
assert isinstance(results, ClassifyJobResults)
assert len(results.items) == 2
file_name_to_expected_type = {
@@ -228,7 +189,8 @@ async def test_classify_file_paths(
}
# Verify each file got classified
for item in results.items:
expected_type = file_name_to_expected_type[item.file.name]
file = await file_client.get_file(item.file_id)
expected_type = file_name_to_expected_type[file.name]
assert item.result.type == expected_type
Generated
+2256 -2256
View File
File diff suppressed because it is too large Load Diff
+14 -61
View File
@@ -8,11 +8,10 @@ import subprocess
import sys
import tomlkit
from pathlib import Path
import json
def get_current_versions() -> tuple[str, str, str, str | None]:
"""Get current versions from both pyproject.toml files and TS package.json."""
def get_current_versions() -> tuple[str, str, str]:
"""Get current versions from both pyproject.toml files."""
# Read main pyproject.toml
main_content = Path("py/pyproject.toml").read_text()
main_doc = tomlkit.parse(main_content)
@@ -35,21 +34,11 @@ def get_current_versions() -> tuple[str, str, str, str | None]:
)
break
# Read TypeScript package.json version via helper
ts_version: str = get_ts_version()
return (
str(main_version),
str(llama_parse_version),
str(dependency_version),
str(ts_version) if ts_version is not None else None,
)
return str(main_version), str(llama_parse_version), str(dependency_version)
def validate_versions(
main_version: str,
llama_parse_version: str,
dependency_version: str,
main_version: str, llama_parse_version: str, dependency_version: str
) -> list[str]:
"""Validate that versions are consistent and return warnings."""
warnings = []
@@ -71,7 +60,7 @@ def validate_versions(
def set_version(version: str) -> None:
"""Set version across Python projects (no TS change)."""
"""Set version across all pyproject.toml files using tomlkit to preserve formatting."""
# Update main pyproject.toml
main_content = Path("py/pyproject.toml").read_text()
main_doc = tomlkit.parse(main_content)
@@ -90,26 +79,7 @@ def set_version(version: str) -> None:
break
Path("py/llama_parse/pyproject.toml").write_text(tomlkit.dumps(llama_parse_doc))
click.echo(f"Updated Python versions to {version}")
def get_ts_version() -> str:
"""Read TypeScript package.json version (if present)."""
ts_package_path = Path("ts/llama_cloud_services/package.json")
package_data = json.loads(ts_package_path.read_text())
data = package_data.get("version")
if data is None:
raise RuntimeError("TypeScript package.json version not found")
return data
def set_ts_version(version: str) -> None:
"""Set TypeScript package.json version only."""
ts_package_path = Path("ts/llama_cloud_services/package.json")
package_data = json.loads(ts_package_path.read_text())
package_data["version"] = version
ts_package_path.write_text(json.dumps(package_data, indent=2) + "\n")
click.echo(f"Updated TypeScript package.json version to {version}")
click.echo(f"Updated all versions to {version}")
def get_current_branch() -> str:
@@ -129,7 +99,7 @@ def create_if_not_exists(version: str) -> None:
)
sys.exit(1)
tag_name = f"v{version}" if version[0].isdigit() else version
tag_name = f"v{version}"
if not tag_exists(version):
# Create tag
subprocess.run(["git", "tag", tag_name], check=True)
@@ -163,18 +133,12 @@ def cli() -> None:
@cli.command()
def get() -> None:
"""Get current versions and show validation warnings."""
(
main_version,
llama_parse_version,
dependency_version,
ts_version,
) = get_current_versions()
main_version, llama_parse_version, dependency_version = get_current_versions()
click.echo("Current versions:")
click.echo(f" llama-cloud-services: {main_version}")
click.echo(f" llama-parse: {llama_parse_version}")
click.echo(f" dependency reference: {dependency_version}")
click.echo(f" typescript package: {ts_version}")
warnings = validate_versions(main_version, llama_parse_version, dependency_version)
if warnings:
@@ -187,15 +151,9 @@ def get() -> None:
@cli.command()
@click.argument("version")
@click.option("--js", is_flag=True, help="Update TypeScript package.json only")
def set(version: str, js: bool) -> None:
"""Set version for Python, TypeScript, or both (default: Python only)."""
if js:
set_ts_version(version)
return
else:
set_version(version)
def set(version: str) -> None:
"""Set version across all pyproject.toml files."""
set_version(version)
@cli.command()
@@ -207,16 +165,11 @@ def set(version: str, js: bool) -> None:
is_flag=True,
help="Push the tag to the remote repository",
)
@click.option(
"--js",
is_flag=True,
help="tag TypeScript package.json only",
)
def tag(version: str | None = None, push: bool = False, js: bool = False) -> None:
def tag(version: str | None = None, push: bool = False) -> None:
"""Create and push a git tag for the current version."""
if not version:
main_version, _, _, js_version = get_current_versions()
version = f"llama-cloud-services@{js_version}" if js else main_version
main_version, _, _ = get_current_versions()
version = main_version
create_if_not_exists(version)
if push:
+1 -2
View File
@@ -1,6 +1,6 @@
{
"name": "llama-cloud-services",
"version": "0.3.4",
"version": "0.3.3",
"type": "module",
"license": "MIT",
"scripts": {
@@ -9,7 +9,6 @@
"dev": "bunchee --watch",
"lint": "eslint src/ --ignore-pattern client/*.ts --no-warn-ignored",
"format": "prettier --write ./src/",
"format:check": "prettier --check ./src/",
"test": "vitest run --testTimeout=60000",
"test:watch": "vitest --watch",
"test:ui": "vitest --ui",
@@ -1,5 +1,5 @@
import { createClient } from "@hey-api/client-fetch";
import { client as defaultClient } from "../../api";
import { createClient, createConfig } from "@hey-api/client-fetch";
import { getEnv } from "@llamaindex/env";
import {
aggregateAgentDataApiV1BetaAgentDataAggregatePost,
createAgentDataApiV1BetaAgentDataPost,
@@ -24,19 +24,36 @@ import type {
*/
export class AgentClient<T = unknown> {
private client: ReturnType<typeof createClient>;
private baseUrl: string;
private headers: Record<string, string>;
private collection: string;
private agentUrlId: string;
constructor({
client = defaultClient,
apiKey = getEnv("LLAMA_CLOUD_API_KEY"),
baseUrl = "https://api.cloud.llamaindex.ai/",
collection = "default",
agentUrlId = "_public",
}: {
client?: ReturnType<typeof createClient>;
apiKey?: string;
baseUrl?: string;
collection?: string;
agentUrlId?: string;
}) {
this.client = client;
this.baseUrl = baseUrl;
this.headers = {
"X-SDK-Name": "llamaindex-ts",
...(apiKey && { Authorization: `Bearer ${apiKey}` }),
};
this.client = createClient(
createConfig({
baseUrl: this.baseUrl,
headers: this.headers,
}),
);
this.collection = collection;
this.agentUrlId = agentUrlId;
}
@@ -264,13 +281,15 @@ export interface AgentDataClientOptions {
* @returns A new AgentClient instance
*/
export function createAgentDataClient<T = unknown>({
client = defaultClient,
apiKey,
baseUrl,
windowUrl,
env,
agentUrlId,
collection = "default",
}: {
client?: ReturnType<typeof createClient>;
apiKey?: string;
baseUrl?: string;
windowUrl?: string;
env?: Record<string, string>;
agentUrlId?: string;
@@ -302,8 +321,9 @@ export function createAgentDataClient<T = unknown>({
}
return new AgentClient({
...(apiKey && { apiKey }),
...(baseUrl && { baseUrl }),
...(agentUrlId && { agentUrlId }),
collection,
client,
});
}
+1 -1
View File
@@ -194,7 +194,7 @@ export class LlamaParseReader extends FileReader {
? this.language
: [this.language];
this.stdout =
(params.stdout ?? typeof process !== "undefined")
params.stdout ?? typeof process !== "undefined"
? process!.stdout
: undefined;
const apiKey = params.apiKey ?? getEnv("LLAMA_CLOUD_API_KEY");
@@ -1,80 +0,0 @@
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
import { listProjectsApiV1ProjectsGet, client } from "../src/api.js";
describe("Global client configuration", () => {
const originalFetch = globalThis.fetch;
beforeEach(() => {
vi.restoreAllMocks();
});
afterEach(() => {
globalThis.fetch = originalFetch;
});
it("adds X-SDK-Name header from global client config", async () => {
const fetchSpy = vi
.spyOn(globalThis, "fetch")
.mockImplementation(async (input, init) => {
// Validate the header is present on the outgoing request
let headers: Headers;
if (input && typeof input === "object" && "headers" in (input as any)) {
headers = (input as Request).headers;
} else {
headers = new Headers((init && init.headers) || {});
}
expect(headers.get("X-SDK-Name")).toBe("llamaindex-ts");
return new Response(JSON.stringify([]), {
status: 200,
headers: { "Content-Type": "application/json" },
});
});
// Trigger any request via the generated SDK (imported through src/api.ts)
await listProjectsApiV1ProjectsGet({ throwOnError: false });
expect(fetchSpy).toHaveBeenCalledOnce();
});
it("respects additional custom headers set via setConfig", async () => {
const prevConfig = client.getConfig();
try {
client.setConfig({
...prevConfig,
headers: {
...(prevConfig.headers || {}),
"X-Custom-Header": "custom-value",
},
});
const fetchSpy = vi
.spyOn(globalThis, "fetch")
.mockImplementation(async (input, init) => {
let headers: Headers;
if (
input &&
typeof input === "object" &&
"headers" in (input as any)
) {
headers = (input as Request).headers;
} else {
headers = new Headers((init && init.headers) || {});
}
expect(headers.get("X-SDK-Name")).toBe("llamaindex-ts");
expect(headers.get("X-Custom-Header")).toBe("custom-value");
return new Response(JSON.stringify([]), {
status: 200,
headers: { "Content-Type": "application/json" },
});
});
await listProjectsApiV1ProjectsGet({ throwOnError: false });
expect(fetchSpy).toHaveBeenCalledOnce();
} finally {
// Restore original configuration to avoid test cross-talk
client.setConfig(prevConfig);
}
});
});