From 7420dd66cb0b8f07b4fd90306c9390fb5846b8b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Sep 2026 22:07:26 +0000 Subject: [PATCH 01/22] Bump elysia from 1.4.27 to 1.4.29 Bumps [elysia](https://github.com/elysiajs/elysia) from 1.4.27 to 1.4.29. - [Release notes](https://github.com/elysiajs/elysia/releases) - [Changelog](https://github.com/elysiajs/elysia/blob/main/CHANGELOG.md) - [Commits](https://github.com/elysiajs/elysia/compare/1.4.27...1.4.29) --- updated-dependencies: - dependency-name: elysia dependency-version: 1.4.29 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7dc082eb..93f2ca02 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "@elysiajs/html": "^1.4.0", "@openfn/adaptor-apis": "^0.3.0", "@sentry/bun": "^10.60.0", - "elysia": "1.4.27", + "elysia": "1.4.29", "jsdoc-babel": "^0.5.0" }, "nodemonConfig": { From 377dc26f78f599d4b5eb019cfe8126d4295f728c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Oct 2026 10:28:17 +0000 Subject: [PATCH 02/22] Bump urllib3 from 2.7.0 to 2.8.0 Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.7.0 to 2.8.0. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/2.7.0...2.8.0) --- updated-dependencies: - dependency-name: urllib3 dependency-version: 2.8.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- poetry.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/poetry.lock b/poetry.lock index 6ea8d960..fbf407a4 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.4.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.5.1 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" @@ -1042,7 +1042,7 @@ pydantic-settings = ">=2.10.1,<3.0.0" pyyaml = ">=5.3.0,<7.0.0" requests = ">=2.32.5,<3.0.0" sqlalchemy = ">=1.4.0,<3.0.0" -tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<10.0.0" +tenacity = ">=8.1.0,!=8.4.0,<10.0.0" [[package]] name = "langchain-core" @@ -1064,7 +1064,7 @@ langsmith = ">=0.3.45,<1.0.0" packaging = ">=23.2.0" pydantic = ">=2.7.4,<3.0.0" pyyaml = ">=5.3.0,<7.0.0" -tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<10.0.0" +tenacity = ">=8.1.0,!=8.4.0,<10.0.0" typing-extensions = ">=4.7.0,<5.0.0" uuid-utils = ">=0.12.0,<1.0" @@ -1102,7 +1102,7 @@ files = [ httpx = ">=0.28.0" langchain-core = ">=0.3.34,<2.0.0" langchain-openai = ">=0.3.11" -numpy = ">=1.26.4,<2.0.2 || >2.0.2" +numpy = ">=1.26.4,!=2.0.2" pinecone = {version = ">=6.0.0,<8.0.0", extras = ["asyncio"]} pydantic = ">=2.11.1" simsimd = ">=5.9.11" @@ -3095,14 +3095,14 @@ files = [ [[package]] name = "urllib3" -version = "2.7.0" +version = "2.8.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897"}, - {file = "urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c"}, + {file = "urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3"}, + {file = "urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63"}, ] [package.extras] From 7644450c6fae937a76333908c30be4da22a1ba12 Mon Sep 17 00:00:00 2001 From: doc-han Date: Fri, 2 Oct 2026 09:58:32 +0000 Subject: [PATCH 03/22] feat: forked python process --- platform/src/bridge.ts | 200 +++++++++++++++++++++++++++++++++++++++- services/entry.py | 69 ++++++++------ services/fork_server.py | 109 ++++++++++++++++++++++ 3 files changed, 347 insertions(+), 31 deletions(-) create mode 100644 services/fork_server.py diff --git a/platform/src/bridge.ts b/platform/src/bridge.ts index 240e9ade..edceebec 100644 --- a/platform/src/bridge.ts +++ b/platform/src/bridge.ts @@ -1,6 +1,7 @@ import readline from "node:readline"; +import net from "node:net"; import path from "node:path"; -import { spawn } from "node:child_process"; +import { spawn, type ChildProcess } from "node:child_process"; import { chmod, rm } from "node:fs/promises"; import { getInternalToken } from "./auth/internal-token"; import { @@ -17,6 +18,199 @@ import pkg from "../../package.json"; // stream. Only these are forwarded to the caller. const LOG_LINE = /^(INFO|DEBUG|ERROR|WARNING):/; +const USE_FORK_SERVER = ["1", "true", "yes"].includes( + (process.env.APOLLO_FORK_SERVER ?? "").toLowerCase() +); + +interface ForkMaster { + proc: ChildProcess; + socketPath: string; +} +let forkMaster: Promise | null = null; +let forkMasterProc: ChildProcess | null = null; + +function startForkMaster(): Promise { + const socketPath = path.resolve(`tmp/fork_server-${process.pid}.sock`); + const proc = spawn( + "poetry", + ["run", "python", "services/fork_server.py", "--socket", socketPath], + { + env: { + ...process.env, + APOLLO_INTERNAL_TOKEN: getInternalToken(), + APOLLO_VERSION: pkg.version, + OBJC_DISABLE_INITIALIZE_FORK_SAFETY: "YES", + }, + } + ); + forkMasterProc = proc; + + return new Promise((resolve, reject) => { + const timeout = setTimeout( + () => reject(subprocessSpawnFailed("fork_server", new Error("not READY in time"))), + 60_000 + ); + readline.createInterface({ input: proc.stdout!, crlfDelay: Infinity }).on("line", (line) => { + console.log(`fork-server: ${line}`); + if (line.startsWith("READY")) { + clearTimeout(timeout); + resolve({ proc, socketPath }); + } + }); + readline + .createInterface({ input: proc.stderr!, crlfDelay: Infinity }) + .on("line", (line) => console.error(`fork-server: ${line}`)); + + proc.on("error", (err) => { + clearTimeout(timeout); + reject(subprocessSpawnFailed("fork_server", err)); + }); + proc.on("exit", (code, sig) => { + clearTimeout(timeout); + console.error(`fork-server exited (code=${code} signal=${sig})`); + forkMaster = null; // next request starts a fresh master + forkMasterProc = null; + rm(socketPath).catch(() => {}); + }); + }); +} + +function getForkMaster(): Promise { + if (!forkMaster) { + forkMaster = startForkMaster().catch((err) => { + forkMaster = null; + throw err; + }); + } + return forkMaster; +} + +process.once("exit", () => forkMasterProc?.kill("SIGTERM")); + +function runForked( + scriptName: string, + port: number, + inputPath: string, + outputPath: string, + onLog?: (str: string) => void, + onEvent?: (type: string, payload: any) => void, + signal?: AbortSignal +): Promise { + return getForkMaster().then( + (master) => + new Promise((resolve, reject) => { + let childPid: number | null = null; + let exitCode: number | null = null; + let cancelled = false; + let hardKill: ReturnType | undefined; + + const cleanupFiles = async () => { + try { + await rm(inputPath); + await rm(outputPath); + } catch (e) { + console.error("Error removing temporary files"); + console.error(e); + } + }; + + const killChild = () => { + if (childPid == null) return; // killed once the PID: line arrives + try { + process.kill(childPid, "SIGTERM"); + } catch {} + hardKill = setTimeout(() => { + try { + process.kill(childPid!, "SIGKILL"); + } catch {} + }, 5_000); + hardKill.unref?.(); + }; + + const onAbort = () => { + cancelled = true; + console.warn(`cancelling ${scriptName}: client went away`); + killChild(); + conn.destroy(); + }; + + const conn = net.createConnection({ path: master.socketPath }); + conn.on("connect", () => { + conn.write( + JSON.stringify({ service: scriptName, input: inputPath, output: outputPath, port }) + "\n" + ); + }); + + // The child's stream: the service's own stdout, wrapped in PID:/EXIT:. + const rl = readline.createInterface({ input: conn, crlfDelay: Infinity }); + rl.on("line", (line) => { + if (line.startsWith("PID:")) { + childPid = Number(line.slice(4)) || null; + if (cancelled) killChild(); + } else if (line.startsWith("EXIT:")) { + exitCode = Number(line.slice(5)); + } else if (LOG_LINE.test(line)) { + console.log(line); + onLog?.(line); + } else if (/^(EVENT)\:/.test(line)) { + const [_prefix, type, ...payload] = line.split(":"); + let processedPayload: any = payload.join(":"); + try { + processedPayload = JSON.parse(processedPayload); + } catch (e) { + // No json, no problem + } + onEvent?.(type, processedPayload); + } + }); + + if (signal) { + if (signal.aborted) onAbort(); + else signal.addEventListener("abort", onAbort, { once: true }); + } + + conn.on("error", async (err) => { + if (hardKill) clearTimeout(hardKill); + signal?.removeEventListener("abort", onAbort); + await cleanupFiles(); + reject(subprocessSpawnFailed(scriptName, err)); + }); + + conn.on("close", async () => { + rl.close(); + if (hardKill) clearTimeout(hardKill); + signal?.removeEventListener("abort", onAbort); + + const text = await Bun.file(outputPath) + .text() + .catch(() => ""); + await cleanupFiles(); + + if (cancelled) return reject(subprocessCancelled(scriptName, "SIGTERM")); + if (exitCode && exitCode !== 0) return reject(subprocessFailed(scriptName, exitCode)); + // No EXIT line => the child died mid-flight (crash/OOM/signal). + if (exitCode === null) return reject(subprocessKilled(scriptName, "UNKNOWN")); + if (text) { + try { + return resolve(JSON.parse(text)); + } catch (e) { + console.error(`Unreadable output from ${scriptName}`); + console.error(e); + return reject(malformedResult(scriptName)); + } + } + console.warn("No data returned from pythonland"); + return reject(emptyResult(scriptName)); + }); + }), + async (err) => { + await rm(inputPath).catch(() => {}); + await rm(outputPath).catch(() => {}); + throw err; + } + ); +} + /** Run a python script Each script will be run in its own thread because @@ -61,6 +255,10 @@ export const run = async ( throw subprocessSpawnFailed(scriptName, error); } + if (USE_FORK_SERVER) { + return runForked(scriptName, port, inputPath, outputPath, onLog, onEvent, signal); + } + return new Promise((resolve, reject) => { const proc = spawn( "poetry", diff --git a/services/entry.py b/services/entry.py index 238f476e..daf8f597 100644 --- a/services/entry.py +++ b/services/entry.py @@ -9,17 +9,15 @@ load_dotenv() -# Langfuse: init after load_dotenv so env vars are available, before any Anthropic client is created from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor from opentelemetry.instrumentation.threading import ThreadingInstrumentor -AnthropicInstrumentor().instrument() -ThreadingInstrumentor().instrument() - from langfuse import Langfuse from langfuse.span_filter import is_default_export_span from langfuse_util import mask_secrets +langfuse = None # set by bootstrap() + def _should_export_span(span): """Drop spans marked as tracing-disabled (user has not opted in).""" @@ -29,20 +27,6 @@ def _should_export_span(span): return is_default_export_span(span) -langfuse = Langfuse( - should_export_span=_should_export_span, - mask=mask_secrets, - release=os.getenv("APOLLO_VERSION", "unknown"), -) - -env = os.getenv('ENVIRONMENT', 'unknown') -trace_rates = { - 'development': 1, - 'staging': 0.05, - 'production': 0.03, - 'unknown': 0.0, - } - def _scrub_event(event: dict, _hint: dict) -> dict: """Mask keys in what Sentry is about to send. @@ -54,17 +38,41 @@ def _scrub_event(event: dict, _hint: dict) -> dict: return mask_secrets(event) -sentry_sdk.init( - dsn=os.getenv('SENTRY_DSN'), - environment=env, - sample_rate=1.0, - traces_sample_rate=trace_rates.get(env, 0.0), - enable_tracing=True, - auto_enabling_integrations=False, - before_send=_scrub_event, - # before_send covers error events only, and tracing is on. - before_send_transaction=_scrub_event, -) +def bootstrap() -> None: + global langfuse + + AnthropicInstrumentor().instrument() + ThreadingInstrumentor().instrument() + + langfuse = Langfuse( + should_export_span=_should_export_span, + mask=mask_secrets, + release=os.getenv("APOLLO_VERSION", "unknown"), + ) + + env = os.getenv("ENVIRONMENT", "unknown") + trace_rates = { + "development": 1, + "staging": 0.05, + "production": 0.03, + "unknown": 0.0, + } + + sentry_sdk.init( + dsn=os.getenv("SENTRY_DSN"), + environment=env, + sample_rate=1.0, + traces_sample_rate=trace_rates.get(env, 0.0), + enable_tracing=True, + auto_enabling_integrations=False, + before_send=_scrub_event, + # before_send covers error events only, and tracing is on. + before_send_transaction=_scrub_event, + ) + + +if os.environ.get("APOLLO_FORK_PRELOAD") != "1": + bootstrap() # At or above this the failure is ours; below it the caller sent something we # correctly refused. @@ -156,7 +164,8 @@ def call( code=500, message=str(e), type="INTERNAL_ERROR", ).to_dict() - langfuse.flush() + if langfuse is not None: + langfuse.flush() return _finish(result, output_path) diff --git a/services/fork_server.py b/services/fork_server.py new file mode 100644 index 00000000..9aecdce7 --- /dev/null +++ b/services/fork_server.py @@ -0,0 +1,109 @@ +import os +import sys + +# macOS aborts a forked child that touches an objc framework unless this is set +# before interpreter start, so re-exec once with it in the env. No-op on Linux. +# [To be removed] +if sys.platform == "darwin" and os.environ.get("OBJC_DISABLE_INITIALIZE_FORK_SAFETY") != "YES": + os.environ["OBJC_DISABLE_INITIALIZE_FORK_SAFETY"] = "YES" + os.execvpe(sys.executable, [sys.executable, *sys.argv], os.environ) + +# Tell entry.py to import its heavy modules but defer bootstrap() to each child. +os.environ["APOLLO_FORK_PRELOAD"] = "1" + +import argparse # noqa: E402 +import importlib # noqa: E402 +import json # noqa: E402 +import signal # noqa: E402 +import socket # noqa: E402 +import traceback # noqa: E402 + +import entry # noqa: E402 + + +def _preload_services() -> list[str]: + """Import an opt-in allowlist (APOLLO_FORK_PRELOAD_SERVICES) so children + inherit their deps. Not every service: some do I/O at import and would hang + the parent; entry.call() imports the rest on demand in the child.""" + names = [n.strip() for n in os.environ.get("APOLLO_FORK_PRELOAD_SERVICES", "").split(",") if n.strip()] + loaded = [] + for name in names: + try: + importlib.import_module(f"{name}.{name}") + loaded.append(name) + except Exception as e: + print(f"fork_server: could not preload {name}: {e}", file=sys.stderr, flush=True) + return loaded + + +def _run_child(conn: socket.socket, req: dict) -> None: + os.dup2(conn.fileno(), 1) + os.dup2(conn.fileno(), 2) + sys.stdout = os.fdopen(1, "w", buffering=1) + sys.stderr = os.fdopen(2, "w", buffering=1) + + sys.stdout.write(f"PID:{os.getpid()}\n") # first, so the bridge can cancel this child + sys.stdout.flush() + + code = 0 + try: + entry.bootstrap() + entry.call( + service=req["service"], + input_path=req.get("input"), + output_path=req.get("output"), + apollo_port=req.get("port"), + ) + except Exception: + traceback.print_exc() + code = 1 + finally: + sys.stdout.write(f"EXIT:{code}\n") + sys.stdout.flush() + os._exit(code) + + +def main() -> None: + ap = argparse.ArgumentParser() + ap.add_argument("--socket", required=True) + args = ap.parse_args() + + signal.signal(signal.SIGCHLD, signal.SIG_IGN) # auto-reap children + + loaded = _preload_services() + + if os.path.exists(args.socket): + os.unlink(args.socket) + srv = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + srv.bind(args.socket) + srv.listen(128) + print(f"READY services={len(loaded)}", flush=True) # handshake the bridge waits for + + while True: + try: + conn, _ = srv.accept() + except InterruptedError: + continue + line = b"" + while not line.endswith(b"\n"): + chunk = conn.recv(65536) + if not chunk: + break + line += chunk + if not line: + conn.close() + continue + try: + req = json.loads(line) + except json.JSONDecodeError: + conn.close() + continue + + if os.fork() == 0: + srv.close() # the child must not hold the listening socket + _run_child(conn, req) # never returns + conn.close() # parent drops its copy; the child owns the reply + + +if __name__ == "__main__": + main() From 9b141bcdcfc4734f8fefaeecd218913cd5077e25 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Oct 2026 14:36:53 +0000 Subject: [PATCH 04/22] Bump the python-minor-patch group with 7 updates Bumps the python-minor-patch group with 7 updates: | Package | From | To | | --- | --- | --- | | [langchain-core](https://github.com/langchain-ai/langchain) | `1.6.4` | `1.6.5` | | [langchain-openai](https://github.com/langchain-ai/langchain) | `1.6.3` | `1.6.6` | | [sentry-sdk](https://github.com/getsentry/sentry-python) | `2.70.0` | `2.71.0` | | [langfuse](https://github.com/langfuse/langfuse) | `4.15.4` | `4.15.6` | | [opentelemetry-instrumentation-anthropic](https://github.com/traceloop/openllmetry) | `0.62.3` | `0.62.4` | | [opentelemetry-instrumentation-threading](https://github.com/open-telemetry/opentelemetry-python-contrib) | `0.65b0` | `0.66b0` | | [ruff](https://github.com/astral-sh/ruff) | `0.16.8` | `0.16.9` | Updates `langchain-core` from 1.6.4 to 1.6.5 - [Release notes](https://github.com/langchain-ai/langchain/releases) - [Commits](https://github.com/langchain-ai/langchain/compare/langchain-core==1.6.4...langchain-core==1.6.5) Updates `langchain-openai` from 1.6.3 to 1.6.6 - [Release notes](https://github.com/langchain-ai/langchain/releases) - [Commits](https://github.com/langchain-ai/langchain/compare/langchain-openai==1.6.3...langchain-openai==1.6.6) Updates `sentry-sdk` from 2.70.0 to 2.71.0 - [Release notes](https://github.com/getsentry/sentry-python/releases) - [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md) - [Commits](https://github.com/getsentry/sentry-python/compare/2.70.0...2.71.0) Updates `langfuse` from 4.15.4 to 4.15.6 - [Release notes](https://github.com/langfuse/langfuse/releases) - [Commits](https://github.com/langfuse/langfuse/commits) Updates `opentelemetry-instrumentation-anthropic` from 0.62.3 to 0.62.4 - [Release notes](https://github.com/traceloop/openllmetry/releases) - [Changelog](https://github.com/traceloop/openllmetry/blob/main/CHANGELOG.md) - [Commits](https://github.com/traceloop/openllmetry/compare/0.62.3...0.62.4) Updates `opentelemetry-instrumentation-threading` from 0.65b0 to 0.66b0 - [Release notes](https://github.com/open-telemetry/opentelemetry-python-contrib/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python-contrib/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-python-contrib/commits) Updates `ruff` from 0.16.8 to 0.16.9 - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md) - [Commits](https://github.com/astral-sh/ruff/compare/0.16.8...0.16.9) --- updated-dependencies: - dependency-name: langchain-core dependency-version: 1.6.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: python-minor-patch - dependency-name: langchain-openai dependency-version: 1.6.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: python-minor-patch - dependency-name: sentry-sdk dependency-version: 2.71.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: python-minor-patch - dependency-name: langfuse dependency-version: 4.15.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: python-minor-patch - dependency-name: opentelemetry-instrumentation-anthropic dependency-version: 0.62.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: python-minor-patch - dependency-name: opentelemetry-instrumentation-threading dependency-version: 0.66b0 dependency-type: direct:production dependency-group: python-minor-patch - dependency-name: ruff dependency-version: 0.16.9 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: python-minor-patch ... Signed-off-by: dependabot[bot] --- poetry.lock | 188 ++++++++++++++++++++++++++++++------------------- pyproject.toml | 10 +-- 2 files changed, 119 insertions(+), 79 deletions(-) diff --git a/poetry.lock b/poetry.lock index 6ea8d960..45944aed 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.4.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.5.1 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" @@ -1042,18 +1042,18 @@ pydantic-settings = ">=2.10.1,<3.0.0" pyyaml = ">=5.3.0,<7.0.0" requests = ">=2.32.5,<3.0.0" sqlalchemy = ">=1.4.0,<3.0.0" -tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<10.0.0" +tenacity = ">=8.1.0,!=8.4.0,<10.0.0" [[package]] name = "langchain-core" -version = "1.6.4" +version = "1.6.5" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0.0,>=3.10.0" groups = ["main"] files = [ - {file = "langchain_core-1.6.4-py3-none-any.whl", hash = "sha256:2f940c83f787676ad4dc651d49d053c7ec34bda5a6afcd224da2863ff53a0b84"}, - {file = "langchain_core-1.6.4.tar.gz", hash = "sha256:c1caae770d991bb6f2376bad791970bf77bb29abd1f15823fa9ea7dbac080fa0"}, + {file = "langchain_core-1.6.5-py3-none-any.whl", hash = "sha256:54c7b0e9314b9084fb04405bb33dc5d32986d512d92b7b8863899cd5f6267556"}, + {file = "langchain_core-1.6.5.tar.gz", hash = "sha256:bdb059fef65473fd444558dbb18f50901657402c43ceed9dc0fdc7b76a393c6b"}, ] [package.dependencies] @@ -1064,20 +1064,20 @@ langsmith = ">=0.3.45,<1.0.0" packaging = ">=23.2.0" pydantic = ">=2.7.4,<3.0.0" pyyaml = ">=5.3.0,<7.0.0" -tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<10.0.0" +tenacity = ">=8.1.0,!=8.4.0,<10.0.0" typing-extensions = ">=4.7.0,<5.0.0" uuid-utils = ">=0.12.0,<1.0" [[package]] name = "langchain-openai" -version = "1.6.3" +version = "1.6.6" description = "An integration package connecting OpenAI and LangChain" optional = false python-versions = "<4.0.0,>=3.10.0" groups = ["main"] files = [ - {file = "langchain_openai-1.6.3-py3-none-any.whl", hash = "sha256:c4529e694512e8058219998574b58aa8307d8cd3a13f4b1fc682dd31883f63ef"}, - {file = "langchain_openai-1.6.3.tar.gz", hash = "sha256:906953395f50a896159b7bac83a5de7ef627160056b69946b22b8cad8f39bbfc"}, + {file = "langchain_openai-1.6.6-py3-none-any.whl", hash = "sha256:60dcaa443ddfdf1559feaf1d25916f394c7dda809aebe22a769fc39f02705be7"}, + {file = "langchain_openai-1.6.6.tar.gz", hash = "sha256:7b3848f42825aca40165463aa37757051165eb292ba7f24658a2f58f9bb221f9"}, ] [package.dependencies] @@ -1102,7 +1102,7 @@ files = [ httpx = ">=0.28.0" langchain-core = ">=0.3.34,<2.0.0" langchain-openai = ">=0.3.11" -numpy = ">=1.26.4,<2.0.2 || >2.0.2" +numpy = ">=1.26.4,!=2.0.2" pinecone = {version = ">=6.0.0,<8.0.0", extras = ["asyncio"]} pydantic = ">=2.11.1" simsimd = ">=5.9.11" @@ -1139,14 +1139,14 @@ langchain-core = ">=1.2.31,<2.0.0" [[package]] name = "langfuse" -version = "4.15.4" +version = "4.15.6" description = "Langfuse Python SDK - LLM observability/tracing, datasets, experiments, LLM-as-a-judge evaluation, and prompt management" optional = false python-versions = "<4.0,>=3.10" groups = ["main"] files = [ - {file = "langfuse-4.15.4-py3-none-any.whl", hash = "sha256:8e75c70b1522a722a11ab6c7d88e27534a5d0c3844a1a464ac5eb548b014e9c3"}, - {file = "langfuse-4.15.4.tar.gz", hash = "sha256:b9a36194f4e968206d919313c24ea71c6ea68e21286370b01de752d20b26e7a3"}, + {file = "langfuse-4.15.6-py3-none-any.whl", hash = "sha256:2364d5f17342301a8651ef166abb5bb260aaadd94d1ac72aa30c298b3a395d85"}, + {file = "langfuse-4.15.6.tar.gz", hash = "sha256:af80ed1199e57c2641c9f228066bf9dc324657c06ce6e68660118fa46b237e35"}, ] [package.dependencies] @@ -1455,86 +1455,126 @@ voice-helpers = ["numpy (>=2.0.2)", "sounddevice (>=0.5.1)"] [[package]] name = "opentelemetry-api" -version = "1.44.0" +version = "1.45.0" description = "OpenTelemetry Python API" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "opentelemetry_api-1.44.0-py3-none-any.whl", hash = "sha256:94b98c893a91b88657eaac1e3ba89618cdb85be6918196705354f34728b2cdef"}, - {file = "opentelemetry_api-1.44.0.tar.gz", hash = "sha256:67647e5e9566edcf421166fdf022b3537f818635daa852b289e34604dc6fb33a"}, + {file = "opentelemetry_api-1.45.0-py3-none-any.whl", hash = "sha256:80e068aba7cd56c8b58512d6a36f8d25cb1dfaa0c0a4cc1c938ccf9f362d9cb3"}, + {file = "opentelemetry_api-1.45.0.tar.gz", hash = "sha256:711ede81773c8025c2c03dac0450bc89f3d30aea6eabcc815c570d4e35a963f7"}, ] [package.dependencies] typing-extensions = ">=4.5.0" +[[package]] +name = "opentelemetry-exporter-http-transport" +version = "0.66b0" +description = "OpenTelemetry Exporters HTTP transport" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "opentelemetry_exporter_http_transport-0.66b0-py3-none-any.whl", hash = "sha256:c82689928a11505a2a0a26a04afe0ce06d270d3db984bc16c1a80ffa902db00e"}, + {file = "opentelemetry_exporter_http_transport-0.66b0.tar.gz", hash = "sha256:2c229b6593eaa22c86d9b8a15843dc23b406dbda00fb138339189aab07923b4e"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.15,<2.0" +urllib3 = {version = ">=1.26", optional = true, markers = "extra == \"urllib3\""} + +[package.extras] +requests = ["requests (>=2.25,<3.0)"] +urllib3 = ["urllib3 (>=1.26)"] + +[[package]] +name = "opentelemetry-exporter-otlp-common" +version = "0.66b0" +description = "OpenTelemetry OTLP HTTP export utilities" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "opentelemetry_exporter_otlp_common-0.66b0-py3-none-any.whl", hash = "sha256:35d24c867310f4713a9738b0202b6bade77955418fccb9e2f7eea01b76263916"}, + {file = "opentelemetry_exporter_otlp_common-0.66b0.tar.gz", hash = "sha256:362268ec6aa705e183776ff938539df1e8ce45bc5509d242538b1d40c26fe6a6"}, +] + +[package.dependencies] +opentelemetry-sdk = ">=1.45.0,<1.46.0" + +[package.extras] +http = ["opentelemetry-exporter-http-transport (==0.66b0)"] + [[package]] name = "opentelemetry-exporter-otlp-proto-common" -version = "1.44.0" +version = "1.45.0" description = "OpenTelemetry Protobuf encoding" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "opentelemetry_exporter_otlp_proto_common-1.44.0-py3-none-any.whl", hash = "sha256:9a9fe61bba73d802904bc989f1d6b4a7b1ee40f06c40e98d6f85af65aaebb694"}, - {file = "opentelemetry_exporter_otlp_proto_common-1.44.0.tar.gz", hash = "sha256:dc87a5a5bc58f149a56d1547e4691588fa12994cdc3bc039a694ccb3375862ac"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.45.0-py3-none-any.whl", hash = "sha256:7e1410ae6d3ed301f7a74bec96467d519d3f37e52f9d95b309ae125e5a1af863"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.45.0.tar.gz", hash = "sha256:36495115a0c6a7aa946cfda9d59b6ed4e917b6ab0f75cdaf66bc1b176ec1be1f"}, ] [package.dependencies] -opentelemetry-proto = "1.44.0" +opentelemetry-proto = "1.45.0" [[package]] name = "opentelemetry-exporter-otlp-proto-http" -version = "1.44.0" +version = "1.45.0" description = "OpenTelemetry Collector Protobuf over HTTP Exporter" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "opentelemetry_exporter_otlp_proto_http-1.44.0-py3-none-any.whl", hash = "sha256:838592fce774c1c8bb7b9a0a7facbfa82e17be5a8a4e94cef10cb84ae026bae3"}, - {file = "opentelemetry_exporter_otlp_proto_http-1.44.0.tar.gz", hash = "sha256:c633d7270ad6b57cd4cfbe8b0007a9e2e7c0cb50bd6c50fe2a7b245f721a09d8"}, + {file = "opentelemetry_exporter_otlp_proto_http-1.45.0-py3-none-any.whl", hash = "sha256:74385f99266dafdefff41f3da4b76f6dba79d237a9d4487e6ff1ee653c74a0a3"}, + {file = "opentelemetry_exporter_otlp_proto_http-1.45.0.tar.gz", hash = "sha256:2f35496d96809f946f41b8805e6b93aec6c9b71b5fd759b75b6af4c084d992ae"}, ] [package.dependencies] googleapis-common-protos = ">=1.52,<2.0" opentelemetry-api = ">=1.15,<2.0" -opentelemetry-exporter-otlp-proto-common = "1.44.0" -opentelemetry-proto = "1.44.0" -opentelemetry-sdk = ">=1.44.0,<1.45.0" -requests = ">=2.7,<3.0" +opentelemetry-exporter-http-transport = {version = "0.66b0", extras = ["urllib3"]} +opentelemetry-exporter-otlp-common = "0.66b0" +opentelemetry-exporter-otlp-proto-common = "1.45.0" +opentelemetry-proto = "1.45.0" +opentelemetry-sdk = ">=1.45.0,<1.46.0" typing-extensions = ">=4.5.0" [package.extras] gcp-auth = ["opentelemetry-exporter-credential-provider-gcp (>=0.59b0)"] +requests = ["opentelemetry-exporter-http-transport[requests] (==0.66b0)", "requests (>=2.7,<3.0)"] [[package]] name = "opentelemetry-instrumentation" -version = "0.65b0" +version = "0.66b0" description = "Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "opentelemetry_instrumentation-0.65b0-py3-none-any.whl", hash = "sha256:ea967a72b9939b5fcfdad572753b4306c59dcb99e3f382d95dae04286805e137"}, - {file = "opentelemetry_instrumentation-0.65b0.tar.gz", hash = "sha256:071d9d9eced9bd6460444ec3b0c77229870ed05a881c22c84fdede58e4eed09b"}, + {file = "opentelemetry_instrumentation-0.66b0-py3-none-any.whl", hash = "sha256:0b32e2fcfec1e4bd48511a3b77ce32bfb1c16dcd5479396b21f9086a4b06c0c9"}, + {file = "opentelemetry_instrumentation-0.66b0.tar.gz", hash = "sha256:316715ed7b33a12530c0ae3e8d4cdf26d70e1aad358d7ba256e5dea2d4ceed71"}, ] [package.dependencies] opentelemetry-api = ">=1.4,<2.0" -opentelemetry-semantic-conventions = "0.65b0" +opentelemetry-semantic-conventions = "0.66b0" packaging = ">=18.0" wrapt = ">=1.0.0,<3.0.0" [[package]] name = "opentelemetry-instrumentation-anthropic" -version = "0.62.3" +version = "0.62.4" description = "OpenTelemetry Anthropic instrumentation" optional = false python-versions = "<4,>=3.10" groups = ["main"] files = [ - {file = "opentelemetry_instrumentation_anthropic-0.62.3-py3-none-any.whl", hash = "sha256:c6613d44a31b528716c99c5e94213d83401d7b31a2865bf395d992521b49623c"}, - {file = "opentelemetry_instrumentation_anthropic-0.62.3.tar.gz", hash = "sha256:54246ab1208aa33e1dd79d4aff1621e73ebc14cd98762798af029e1fc53c0266"}, + {file = "opentelemetry_instrumentation_anthropic-0.62.4-py3-none-any.whl", hash = "sha256:90fc6cc948f3f1b4bff762859ac54b82b5f99e9444538dee3690d73803508db4"}, + {file = "opentelemetry_instrumentation_anthropic-0.62.4.tar.gz", hash = "sha256:861d893c0e20022fa5bee6134cc36c1b5bf847cf831ec0d8b78b0a8267e2a21b"}, ] [package.dependencies] @@ -1548,31 +1588,31 @@ instruments = ["anthropic"] [[package]] name = "opentelemetry-instrumentation-threading" -version = "0.65b0" +version = "0.66b0" description = "Thread context propagation support for OpenTelemetry" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "opentelemetry_instrumentation_threading-0.65b0-py3-none-any.whl", hash = "sha256:d8a1a1f35418a32769d469ef2d7e8401935e097a8553abcfba833da9c74736ce"}, - {file = "opentelemetry_instrumentation_threading-0.65b0.tar.gz", hash = "sha256:aefd23eb16c5e7a7c6c6eacdcb6c6f269ed8ed3a1b458bf5dd555b878bf58937"}, + {file = "opentelemetry_instrumentation_threading-0.66b0-py3-none-any.whl", hash = "sha256:4aaf38b96b47a04319b8d96bee4f1daa04e0d6c697525595746aeb61618c002d"}, + {file = "opentelemetry_instrumentation_threading-0.66b0.tar.gz", hash = "sha256:4c1c9adf42b83b6f44ca4bb99799e066ccfb1869c2029bc73d862c40a8ef932e"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.65b0" +opentelemetry-instrumentation = "0.66b0" wrapt = ">=1.0.0,<3.0.0" [[package]] name = "opentelemetry-proto" -version = "1.44.0" +version = "1.45.0" description = "OpenTelemetry Python Proto" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "opentelemetry_proto-1.44.0-py3-none-any.whl", hash = "sha256:898b155a0e1557afd867478fb6158e8122a46329ca0bb8dc53cc55e98f017f56"}, - {file = "opentelemetry_proto-1.44.0.tar.gz", hash = "sha256:c547a79c2f8c0c515d31509154682e5921c7cfd5ca67b70e1f9266e2c3e103f3"}, + {file = "opentelemetry_proto-1.45.0-py3-none-any.whl", hash = "sha256:9731566359d7b8e1ee1e149d8e4ad6865bab965e657ad3387ec2784d16927666"}, + {file = "opentelemetry_proto-1.45.0.tar.gz", hash = "sha256:96ee414f24bc3f61ea8e17dc56b4348d4049d73db3eb17c6b3edf75b5b403300"}, ] [package.dependencies] @@ -1580,38 +1620,38 @@ protobuf = ">=5.0,<8.0" [[package]] name = "opentelemetry-sdk" -version = "1.44.0" +version = "1.45.0" description = "OpenTelemetry Python SDK" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "opentelemetry_sdk-1.44.0-py3-none-any.whl", hash = "sha256:df081c4c6bcfdb1211e3e86140376792643128a25f8d72d1d27675936e7e96ad"}, - {file = "opentelemetry_sdk-1.44.0.tar.gz", hash = "sha256:cebe7f65dc12f26ead75c6064de12fd2a9052e5060c0272d402cfa203aae123b"}, + {file = "opentelemetry_sdk-1.45.0-py3-none-any.whl", hash = "sha256:5dc634c946546f61b757c5b1781f9fd1a10e96ffaf7357c797e508fe9c57e75e"}, + {file = "opentelemetry_sdk-1.45.0.tar.gz", hash = "sha256:20caa5130505e386c67c3da1c76e446c842698ced54c76c6148679539aa97972"}, ] [package.dependencies] -opentelemetry-api = "1.44.0" -opentelemetry-semantic-conventions = "0.65b0" +opentelemetry-api = "1.45.0" +opentelemetry-semantic-conventions = "0.66b0" typing-extensions = ">=4.5.0" [package.extras] -file-configuration = ["opentelemetry-configuration (==0.65b0)"] +file-configuration = ["opentelemetry-configuration (==0.66b0)"] [[package]] name = "opentelemetry-semantic-conventions" -version = "0.65b0" +version = "0.66b0" description = "OpenTelemetry Semantic Conventions" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "opentelemetry_semantic_conventions-0.65b0-py3-none-any.whl", hash = "sha256:1cacde7b0ad306f84c5ef08c3dbe1bbaf20165bba6f8bff43b670e555a086bcb"}, - {file = "opentelemetry_semantic_conventions-0.65b0.tar.gz", hash = "sha256:f9b2b81e9d5b64f11bc952075e7e9c7fb0aab075c7fd1c46d597f1b919852d60"}, + {file = "opentelemetry_semantic_conventions-0.66b0-py3-none-any.whl", hash = "sha256:175b19dd98c4473f4f43a2b1df59186fd7b4a48cd3f77cbe03438b6d6fda230a"}, + {file = "opentelemetry_semantic_conventions-0.66b0.tar.gz", hash = "sha256:97a77dce484c54861e7eeff7651fd8a806dd3c30e501dc316730215ec36890e6"}, ] [package.dependencies] -opentelemetry-api = "1.44.0" +opentelemetry-api = "1.45.0" typing-extensions = ">=4.5.0" [[package]] @@ -2638,42 +2678,42 @@ requests = ">=2.0.1,<3.0.0" [[package]] name = "ruff" -version = "0.16.8" +version = "0.16.9" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "ruff-0.16.8-py3-none-linux_armv6l.whl", hash = "sha256:6ffbd6d87383c1edf5f6fa890f10200950240d7c1a16052a19a09d3a2307dd38"}, - {file = "ruff-0.16.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:42ed6b878ed61e3acca92f2730a17acff39286944ea82398544696366a6f925e"}, - {file = "ruff-0.16.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:7ea781c7f2afba8c6a505ea0fb3f994020249e0c450635f5381286fea6b46170"}, - {file = "ruff-0.16.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8efeae3bbe414a5efefda11a792dfb51ef90ac48d50c4830de2f644caf3e8659"}, - {file = "ruff-0.16.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a79b795469fef7fc6e908b218eed2eb17332afd85031db6480dc864560e69b2"}, - {file = "ruff-0.16.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fdc5563cdc50555e6fba39322850860e9267c1b3d12c26a74729d8604c3c812"}, - {file = "ruff-0.16.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:34508983c70665578dab88f5223d8e6228307e1135398ca8bfc8b7e9501e282b"}, - {file = "ruff-0.16.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:644bb578569e0ffc575741232bd385dacdd6fbe123f1a729e7a225f54aa3957f"}, - {file = "ruff-0.16.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15e7d226246961db9235098333caa13063906d3851136b84c2900b82f5daa1df"}, - {file = "ruff-0.16.8-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:a2bf6bc3e9ebdd4449abc6f06cf64b98051a2c61cf94d2fe9596518c881f1a1e"}, - {file = "ruff-0.16.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6ca111ba0849539165e9e59d2b442542f3c1e8060ebbdea82494f1ffbccb1e1f"}, - {file = "ruff-0.16.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:359a1e5b495448ee1e91018064382ebc86f90e8aac2fed222c7d0e4e8df85fd2"}, - {file = "ruff-0.16.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:59e8f5681349474110b24d62e93cfda6593f5fa3473446ca3705200cac1a08b9"}, - {file = "ruff-0.16.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:efa3e7a16d1baaa79957888dfdf8be9ef2e44db81cb032af06d76632ab59e773"}, - {file = "ruff-0.16.8-py3-none-win32.whl", hash = "sha256:55793ba85c69921e89be061426d91a78652d6e50317c962240922747a4eb713f"}, - {file = "ruff-0.16.8-py3-none-win_amd64.whl", hash = "sha256:a6b85621fd3c81e31fc5f5add09c9c078b430db3595ca632efafdec9e64ebfaa"}, - {file = "ruff-0.16.8-py3-none-win_arm64.whl", hash = "sha256:d075e820af612102ce217f07cc93e69f9490b10ec13ea85fa87bd03d996cef8a"}, - {file = "ruff-0.16.8.tar.gz", hash = "sha256:9247bf92b5f04d825c8639a4fe423ec2e4222acd9222e58412b0dab7e442798b"}, + {file = "ruff-0.16.9-py3-none-linux_armv6l.whl", hash = "sha256:95e6f022090368ab3b824c36276839c53b2adf1a3f4c09fefc33dfc400f6da96"}, + {file = "ruff-0.16.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a5f27be168556594a86d2f415db0cf43f5291917849318f873c7e2791f7a8c67"}, + {file = "ruff-0.16.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1632eb1d6197f33bd00b1acbc5b71009e89a8895c158e2d2b03a834fac964ab6"}, + {file = "ruff-0.16.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3f951b14d865d5952c89d40a5ca07e87abe24fa5453299878411e127748fb1c"}, + {file = "ruff-0.16.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:447fc07e1573afff7cb02803462b12b6c8ece7cf10e2cd78565fa6d7a1c0bf8d"}, + {file = "ruff-0.16.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a3e039a6a40ed976c491722b60e0ae4a4aa1a86057f540ee7a37a5d19ae9120"}, + {file = "ruff-0.16.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4684dded7db60aa57cb118fa158630f5feade4af5782903b6053484bdf9bd129"}, + {file = "ruff-0.16.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d29c934357e45642fda2f34c0b1f4025b4a6c01e15e4bf0016879d60078a142c"}, + {file = "ruff-0.16.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a21713e629d3e5bdb2f5c2def1cc7f04f47fa8e1a7eb0571b4a28e1da64bc728"}, + {file = "ruff-0.16.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:7baa24ef5fc8e77aa93879e1d3f43754a01ae488e869f1ae30cf431afd4d2452"}, + {file = "ruff-0.16.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a41aac6230aadfaa133bdfa1614488531ffa3e0837567ae04c0da2058a9c0f9e"}, + {file = "ruff-0.16.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:c2529fb5896d49115b0e9aa8f887490b34bbe76baf879ec2264ac59406869ce7"}, + {file = "ruff-0.16.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:41e3870277694177429b56406d65dfbdb2c2802c52b715edaf6a0b829c69d4ee"}, + {file = "ruff-0.16.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8adbe4e58af167f767d7b2ba5e83c42e878350796cf78c2f5e14ab9903a92588"}, + {file = "ruff-0.16.9-py3-none-win32.whl", hash = "sha256:0e1dbc2073624dee6618d41d0098690a7244654af746704b64759e12b6b6b385"}, + {file = "ruff-0.16.9-py3-none-win_amd64.whl", hash = "sha256:6bd40fec8cd4c8a3d4dd589bd8ad4e6320c13c29234159bfd959a40d529d597b"}, + {file = "ruff-0.16.9-py3-none-win_arm64.whl", hash = "sha256:ed1a252039200f57a59eebc063b54beabea67bfbaaca0eeaa7f54b5fbcda2284"}, + {file = "ruff-0.16.9.tar.gz", hash = "sha256:12b625c6cfba78d285d9f48eda5f053374f1e53cb10ef17342a383750db99161"}, ] [[package]] name = "sentry-sdk" -version = "2.70.0" +version = "2.71.0" description = "Python client for Sentry (https://sentry.io)" optional = false python-versions = ">=3.6" groups = ["main"] files = [ - {file = "sentry_sdk-2.70.0-py3-none-any.whl", hash = "sha256:89600e8bb5fc5239cad5c4434217f453204f2207ad29399ea58947460b37a62e"}, - {file = "sentry_sdk-2.70.0.tar.gz", hash = "sha256:27e4b512f47be93136645dbe8f02d430473ee73a389ce430b2b7104baa66cf75"}, + {file = "sentry_sdk-2.71.0-py3-none-any.whl", hash = "sha256:9ed36b4c206048aa67b5ddba0a6e28d59fc55cf10d60f5f7aea2c3917184bf4a"}, + {file = "sentry_sdk-2.71.0.tar.gz", hash = "sha256:7beb27a22f06396f3a05510c3da6ea10e1c79e02e859993c27ce4ff074e296d6"}, ] [package.dependencies] @@ -3760,4 +3800,4 @@ cffi = ["cffi (>=1.17,<2.0) ; platform_python_implementation != \"PyPy\" and pyt [metadata] lock-version = "2.1" python-versions = "3.11.*" -content-hash = "8886c2739952046692045906293b67f982abb2f848864097d8f667304f50bf8f" +content-hash = "b44e2453e8cd62420e08581f70ddf177b81810ffe12935ff6f92f17db2d104d1" diff --git a/pyproject.toml b/pyproject.toml index b80f6797..4600779a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,11 +21,11 @@ langchain-openai = "^1.6" langchain-text-splitters = "^1.1" nltk = "^3.10.3" pytest = "^9.1.1" -sentry-sdk = "^2.70.0" +sentry-sdk = "^2.71.0" psycopg2-binary = "^2.9.13" -langfuse = "^4.15.4" -opentelemetry-instrumentation-anthropic = "^0.62.3" -opentelemetry-instrumentation-threading = "0.65b0" +langfuse = "^4.15.6" +opentelemetry-instrumentation-anthropic = "^0.62.4" +opentelemetry-instrumentation-threading = "0.66b0" pandas = "^2.2" pgvector = "^0.5.0" @@ -34,7 +34,7 @@ optional = false [tool.poetry.group.dev.dependencies] pytest = "^9.1.1" -ruff = "^0.16.8" +ruff = "^0.16.9" [build-system] requires = ["poetry-core"] From dffc653d1aa199a161c24f0f031446167846f053 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Oct 2026 14:37:15 +0000 Subject: [PATCH 05/22] Bump openai from 2.48.0 to 3.20.0 Bumps [openai](https://github.com/openai/openai-python) from 2.48.0 to 3.20.0. - [Release notes](https://github.com/openai/openai-python/releases) - [Changelog](https://github.com/openai/openai-python/blob/main/CHANGELOG.md) - [Commits](https://github.com/openai/openai-python/compare/v2.48.0...v3.20.0) --- updated-dependencies: - dependency-name: openai dependency-version: 3.20.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- poetry.lock | 340 +++++++++++++++++++++++++++++-------------------- pyproject.toml | 2 +- 2 files changed, 206 insertions(+), 136 deletions(-) diff --git a/poetry.lock b/poetry.lock index 6ea8d960..03316a1b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.4.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.5.1 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" @@ -757,6 +757,29 @@ http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] trio = ["trio (>=0.22.0,<1.0)"] +[[package]] +name = "httpcore2" +version = "2.13.1" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.10" +groups = ["main"] +markers = "sys_platform != \"emscripten\"" +files = [ + {file = "httpcore2-2.13.1-py3-none-any.whl", hash = "sha256:e1e05d4f25f7d7d496bfb96748f6f4b67657b03da069b3a68c36069f3db73d0a"}, + {file = "httpcore2-2.13.1.tar.gz", hash = "sha256:e0aa977abe17e69a3b820a24542a6fa88702676d83880b8d194dcd18408e5103"}, +] + +[package.dependencies] +h11 = ">=0.16" +truststore = ">=0.10" + +[package.extras] +asyncio = ["anyio (>=4.5.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.34.0,<1.0)"] + [[package]] name = "httpx" version = "0.28.1" @@ -794,20 +817,47 @@ files = [ {file = "httpx_sse-0.4.3.tar.gz", hash = "sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d"}, ] +[[package]] +name = "httpx2" +version = "2.13.1" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "httpx2-2.13.1-py3-none-any.whl", hash = "sha256:6dff50fabc270ee5fd25d845d0b078ed20564579744d6d962850975996d2f9a4"}, + {file = "httpx2-2.13.1.tar.gz", hash = "sha256:e48744a19e3af5ee48313d0ce5fe941d5422fae5705ea922a4aabf94d7800dfa"}, +] + +[package.dependencies] +anyio = {version = ">=4.10", markers = "sys_platform != \"emscripten\""} +httpcore2 = {version = "2.13.1", markers = "sys_platform != \"emscripten\""} +idna = ">=3.18" +truststore = {version = ">=0.10", markers = "sys_platform != \"emscripten\""} +typing-extensions = {version = ">=4.5.0", markers = "python_version < \"3.13\""} + +[package.extras] +brotli = ["brotli (>=1.2.0) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=1.2.0.2) ; platform_python_implementation != \"CPython\""] +cli = ["click (>=8.4.2)", "pygments (==2.*)", "rich (>=10,<16)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +ws = ["wsproto (>=1.2)"] +zstd = ["backports-zstd (>=1.0.0) ; python_version <= \"3.13\""] + [[package]] name = "idna" -version = "3.15" +version = "3.20" description = "Internationalized Domain Names in Applications (IDNA)" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main"] files = [ - {file = "idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8"}, - {file = "idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc"}, + {file = "idna-3.20-py3-none-any.whl", hash = "sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c"}, + {file = "idna-3.20.tar.gz", hash = "sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44"}, ] [package.extras] -all = ["mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] +all = ["coverage (>=7.10.0)", "hypothesis (>=6.141.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.16.0)", "ty (>=0.0.37)"] [[package]] name = "iniconfig" @@ -823,121 +873,131 @@ files = [ [[package]] name = "jiter" -version = "0.14.0" +version = "0.17.0" description = "Fast iterable JSON parser." optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main"] files = [ - {file = "jiter-0.14.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:02f36a5c700f105ac04a6556fe664a59037a2c200db3b7e88784fac2ddf02531"}, - {file = "jiter-0.14.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41eab6c09ceffb6f0fe25e214b3068146edb1eda3649ca2aee2a061029c7ba2e"}, - {file = "jiter-0.14.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cf4d4c109641f9cfaf4a7b6aebd51654e405cd00fa9ebbf87163b8b97b325aa"}, - {file = "jiter-0.14.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b80c7b41a628e6be2213ad0ece763c5f88aa5ee003fa394d58acaaee1f4b8342"}, - {file = "jiter-0.14.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fb3dbf7cc0d4dbe73cce307ebe7eefa7f73a7d3d854dd119ea0c243f03e40927"}, - {file = "jiter-0.14.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7054adcdeb06b46efd17b5734f75817a44a2d06d3748e36c3a023a1bb52af9ec"}, - {file = "jiter-0.14.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d597cd1bf6790376f3fffc7c708766e57301d99a19314824ea0ccc9c3c70e1e2"}, - {file = "jiter-0.14.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:df63a14878da754427926281626fd3ee249424a186e25a274e78176d42945264"}, - {file = "jiter-0.14.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4ea73187627bcc5810e085df715e8a99da8bdfd96a7eb36b4b4df700ba6d4c9c"}, - {file = "jiter-0.14.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9f541eaf7bb8382367a1a23d6fc3d6aad57f8dd8c18c3c17f838bee20f217220"}, - {file = "jiter-0.14.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:107465250de4fce00fdb47166bcd51df8e634e049541174fe3c71848e44f52ce"}, - {file = "jiter-0.14.0-cp310-cp310-win32.whl", hash = "sha256:ffb2a08a406465bb076b7cc1df41d833106d3cf7905076cc73f0cb90078c7d10"}, - {file = "jiter-0.14.0-cp310-cp310-win_amd64.whl", hash = "sha256:cb8b682d10cb0cce7ff4c1af7244af7022c9b01ae16d46c357bdd0df13afb25d"}, - {file = "jiter-0.14.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7e791e247b8044512e070bd1f3633dc08350d32776d2d6e7473309d0edf256a2"}, - {file = "jiter-0.14.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:71527ce13fd5a0c4e40ad37331f8c547177dbb2dd0a93e5278b6a5eecf748804"}, - {file = "jiter-0.14.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02c4a7ab56f746014874f2c525584c0daca1dec37f66fd707ecef3b7e5c2228c"}, - {file = "jiter-0.14.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:376e9dafff914253bb9d46cdc5f7965607fbe7feb0a491c34e35f92b2770702e"}, - {file = "jiter-0.14.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23ad2a7a9da1935575c820428dd8d2490ce4d23189691ce33da1fc0a58e14e1c"}, - {file = "jiter-0.14.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:54b3ddf5786bc7732d293bba3411ac637ecfa200a39983166d1df86a59a43c9f"}, - {file = "jiter-0.14.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c001d5a646c2a50dc055dd526dad5d5245969e8234d2b1131d0451e81f3a373"}, - {file = "jiter-0.14.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:834bb5bdabca2e91592a03d373838a8d0a1b8bbde7077ae6913fd2fc51812d00"}, - {file = "jiter-0.14.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4e9178be60e229b1b2b0710f61b9e24d1f4f8556985a83ff4c4f95920eea7314"}, - {file = "jiter-0.14.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a7e4ccff04ec03614e62c613e976a3a5860dc9714ce8266f44328bdc8b1cab2c"}, - {file = "jiter-0.14.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:69539d936fb5d55caf6ecd33e2e884de083ff0ea28579780d56c4403094bb8d9"}, - {file = "jiter-0.14.0-cp311-cp311-win32.whl", hash = "sha256:4927d09b3e572787cc5e0a5318601448e1ab9391bcef95677f5840c2d00eaa6d"}, - {file = "jiter-0.14.0-cp311-cp311-win_amd64.whl", hash = "sha256:42d6ed359ac49eb922fdd565f209c57340aa06d589c84c8413e42a0f9ae1b842"}, - {file = "jiter-0.14.0-cp311-cp311-win_arm64.whl", hash = "sha256:6dd689f5f4a5a33747b28686e051095beb214fe28cfda5e9fe58a295a788f593"}, - {file = "jiter-0.14.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:2fb2ce3a7bc331256dfb14cefc34832366bb28a9aca81deaf43bbf2a5659e607"}, - {file = "jiter-0.14.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5252a7ca23785cef5d02d4ece6077a1b556a410c591b379f82091c3001e14844"}, - {file = "jiter-0.14.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c409578cbd77c338975670ada777add4efd53379667edf0aceea730cabede6fb"}, - {file = "jiter-0.14.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7ede4331a1899d604463369c730dbb961ffdc5312bc7f16c41c2896415b1304a"}, - {file = "jiter-0.14.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92cd8b6025981a041f5310430310b55b25ca593972c16407af8837d3d7d2ca01"}, - {file = "jiter-0.14.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:351bf6eda4e3a7ceb876377840c702e9a3e4ecc4624dbfb2d6463c67ae52637d"}, - {file = "jiter-0.14.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1dcfbeb93d9ecd9ca128bbf8910120367777973fa193fb9a39c31237d8df165"}, - {file = "jiter-0.14.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:ae039aaef8de3f8157ecc1fdd4d85043ac4f57538c245a0afaecb8321ec951c3"}, - {file = "jiter-0.14.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7d9d51eb96c82a9652933bd769fe6de66877d6eb2b2440e281f2938c51b5643e"}, - {file = "jiter-0.14.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d824ca4148b705970bf4e120924a212fdfca9859a73e42bd7889a63a4ea6bb98"}, - {file = "jiter-0.14.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff3a6465b3a0f54b1a430f45c3c0ba7d61ceb45cbc3e33f9e1a7f638d690baf3"}, - {file = "jiter-0.14.0-cp312-cp312-win32.whl", hash = "sha256:5dec7c0a3e98d2a3f8a2e67382d0d7c3ac60c69103a4b271da889b4e8bb1e129"}, - {file = "jiter-0.14.0-cp312-cp312-win_amd64.whl", hash = "sha256:fc7e37b4b8bc7e80a63ad6cfa5fc11fab27dbfea4cc4ae644b1ab3f273dc348f"}, - {file = "jiter-0.14.0-cp312-cp312-win_arm64.whl", hash = "sha256:ee4a72f12847ef29b072aee9ad5474041ab2924106bdca9fcf5d7d965853e057"}, - {file = "jiter-0.14.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:af72f204cf4d44258e5b4c1745130ac45ddab0e71a06333b01de660ab4187a94"}, - {file = "jiter-0.14.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4b77da71f6e819be5fbcec11a453fde5b1d0267ef6ed487e2a392fd8e14e4e3a"}, - {file = "jiter-0.14.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f4ea612fe8b84b8b04e51d0e78029ecf3466348e25973f953de6e6a59aa4c1"}, - {file = "jiter-0.14.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:62fe2451f8fcc0240261e6a4df18ecbcd58327857e61e625b2393ea3b468aac9"}, - {file = "jiter-0.14.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6112f26f5afc75bcb475787d29da3aa92f9d09c7858f632f4be6ffe607be82e9"}, - {file = "jiter-0.14.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:215a6cb8fb7dc702aa35d475cc00ddc7f970e5c0b1417fb4b4ac5d82fa2a29db"}, - {file = "jiter-0.14.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4ab96a30fb3cb2c7e0cd33f7616c8860da5f5674438988a54ac717caccdbaa"}, - {file = "jiter-0.14.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:3a99c1387b1f2928f799a9de899193484d66206a50e98233b6b088a7f0c1edb2"}, - {file = "jiter-0.14.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ab18d11074485438695f8d34a1b6da61db9754248f96d51341956607a8f39985"}, - {file = "jiter-0.14.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:801028dcfc26ac0895e4964cbc0fd62c73be9fd4a7d7b1aaf6e5790033a719b7"}, - {file = "jiter-0.14.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ad425b087aafb4a1c7e1e98a279200743b9aaf30c3e0ba723aec93f061bd9bc8"}, - {file = "jiter-0.14.0-cp313-cp313-win32.whl", hash = "sha256:882bcb9b334318e233950b8be366fe5f92c86b66a7e449e76975dfd6d776a01f"}, - {file = "jiter-0.14.0-cp313-cp313-win_amd64.whl", hash = "sha256:9b8c571a5dba09b98bd3462b5a53f27209a5cbbe85670391692ede71974e979f"}, - {file = "jiter-0.14.0-cp313-cp313-win_arm64.whl", hash = "sha256:34f19dcc35cb1abe7c369b3756babf8c7f04595c0807a848df8f26ef8298ef92"}, - {file = "jiter-0.14.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e89bcd7d426a75bb4952c696b267075790d854a07aad4c9894551a82c5b574ab"}, - {file = "jiter-0.14.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b25beaa0d4447ea8c7ae0c18c688905d34840d7d0b937f2f7bdd52162c98a40"}, - {file = "jiter-0.14.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:651a8758dd413c51e3b7f6557cdc6921faf70b14106f45f969f091f5cda990ea"}, - {file = "jiter-0.14.0-cp313-cp313t-win_amd64.whl", hash = "sha256:e1a7eead856a5038a8d291f1447176ab0b525c77a279a058121b5fccee257f6f"}, - {file = "jiter-0.14.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2e692633a12cda97e352fdcd1c4acc971b1c28707e1e33aeef782b0cbf051975"}, - {file = "jiter-0.14.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:6f396837fc7577871ca8c12edaf239ed9ccef3bbe39904ae9b8b63ce0a48b140"}, - {file = "jiter-0.14.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a4d50ea3d8ba4176f79754333bd35f1bbcd28e91adc13eb9b7ca91bc52a6cef9"}, - {file = "jiter-0.14.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce17f8a050447d1b4153bda4fb7d26e6a9e74eb4f4a41913f30934c5075bf615"}, - {file = "jiter-0.14.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f4f1c4b125e1652aefbc2e2c1617b60a160ab789d180e3d423c41439e5f32850"}, - {file = "jiter-0.14.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be808176a6a3a14321d18c603f2d40741858a7c4fc982f83232842689fe86dd9"}, - {file = "jiter-0.14.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26679d58ba816f88c3849306dd58cb863a90a1cf352cdd4ef67e30ccf8a77994"}, - {file = "jiter-0.14.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80381f5a19af8fa9aef743f080e34f6b25ebd89656475f8cf0470ec6157052aa"}, - {file = "jiter-0.14.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:004df5fdb8ecbd6d99f3227df18ba1a259254c4359736a2e6f036c944e02d7c5"}, - {file = "jiter-0.14.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cff5708f7ed0fa098f2b53446c6fa74c48469118e5cd7497b4f1cd569ab06928"}, - {file = "jiter-0.14.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:2492e5f06c36a976d25c7cc347a60e26d5470178d44cde1b9b75e60b4e519f28"}, - {file = "jiter-0.14.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:7609cfbe3a03d37bfdbf5052012d5a879e72b83168a363deae7b3a26564d57de"}, - {file = "jiter-0.14.0-cp314-cp314-win32.whl", hash = "sha256:7282342d32e357543565286b6450378c3cd402eea333fc1ebe146f1fabb306fc"}, - {file = "jiter-0.14.0-cp314-cp314-win_amd64.whl", hash = "sha256:bd77945f38866a448e73b0b7637366afa814d4617790ecd88a18ca74377e6c02"}, - {file = "jiter-0.14.0-cp314-cp314-win_arm64.whl", hash = "sha256:f2d4c61da0821ee42e0cdf5489da60a6d074306313a377c2b35af464955a3611"}, - {file = "jiter-0.14.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1bf7ff85517dd2f20a5750081d2b75083c1b269cf75afc7511bdf1f9548beb3b"}, - {file = "jiter-0.14.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8ef8791c3e78d6c6b157c6d360fbb5c715bebb8113bc6a9303c5caff012754a"}, - {file = "jiter-0.14.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e74663b8b10da1fe0f4e4703fd7980d24ad17174b6bb35d8498d6e3ebce2ae6a"}, - {file = "jiter-0.14.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1aca29ba52913f78362ec9c2da62f22cdc4c3083313403f90c15460979b84d9b"}, - {file = "jiter-0.14.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8b39b7d87a952b79949af5fef44d2544e58c21a28da7f1bae3ef166455c61746"}, - {file = "jiter-0.14.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78d918a68b26e9fab068c2b5453577ef04943ab2807b9a6275df2a812599a310"}, - {file = "jiter-0.14.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:b08997c35aee1201c1a5361466a8fb9162d03ae7bf6568df70b6c859f1e654a4"}, - {file = "jiter-0.14.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:260bf7ca20704d58d41f669e5e9fe7fe2fa72901a6b324e79056f5d52e9c9be2"}, - {file = "jiter-0.14.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:37826e3df29e60f30a382f9294348d0238ef127f4b5d7f5f8da78b5b9e050560"}, - {file = "jiter-0.14.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:645be49c46f2900937ba0eaf871ad5183c96858c0af74b6becc7f4e367e36e06"}, - {file = "jiter-0.14.0-cp314-cp314t-win32.whl", hash = "sha256:2f7877ed45118de283786178eceaf877110abacd04fde31efff3940ae9672674"}, - {file = "jiter-0.14.0-cp314-cp314t-win_amd64.whl", hash = "sha256:14c0cb10337c49f5eafe8e7364daca5e29a020ea03580b8f8e6c597fed4e1588"}, - {file = "jiter-0.14.0-cp314-cp314t-win_arm64.whl", hash = "sha256:5419d4aa2024961da9fe12a9cfe7484996735dca99e8e090b5c88595ef1951ff"}, - {file = "jiter-0.14.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:85581c4c3e4060fe3424cdfd7f3aa610f2dc5e9dde8b6863358eb68560018472"}, - {file = "jiter-0.14.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c6279c63849444a4fe9b9abf82e5df0fc7d13dea07f53f084b362485bd1f2bbe"}, - {file = "jiter-0.14.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59940ef6ac9f8b34c800838416f105f0503485fa8d71cae99f71d44a7285b01e"}, - {file = "jiter-0.14.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:55bee2b6a2657434984d9144c20cf27ba3b6acd495539539953e447778515efd"}, - {file = "jiter-0.14.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2d45fc7ea86a46bd9b5bceb9e8d43e5d10a392378713fb32cf1ce851b4b0d1f8"}, - {file = "jiter-0.14.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:758d19dae7ea4c4da3cbc463dc323d1660e7353144ef17509ff43beab6da5a47"}, - {file = "jiter-0.14.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32959d7285d1d0deb5a8c913349e476ad9271b384f3e54cca1931c4075f54c6e"}, - {file = "jiter-0.14.0-cp39-cp39-manylinux_2_31_riscv64.whl", hash = "sha256:78a4c677fe5689e0e129b39f5affe9210a500b6620ebb0386ebccf5922bee9a6"}, - {file = "jiter-0.14.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ae66782ecffb1a266e1a07f5abbfc3832afdd260fc9b478982c3f8e01eba5fa"}, - {file = "jiter-0.14.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:155dab67beac8d66cec9479c93ee2cbe7bfbc67509e5c2860e02ec2d9b0ecca1"}, - {file = "jiter-0.14.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f16b76d7d6aadbbaf7f79a76ff3a51dae14b7ebaaf9c1ba61607784ef51c537c"}, - {file = "jiter-0.14.0-cp39-cp39-win32.whl", hash = "sha256:0fbad7aa06f87e8215d660fc6f05a9b07b58751a29967bbd9c81ff22d21dbe8c"}, - {file = "jiter-0.14.0-cp39-cp39-win_amd64.whl", hash = "sha256:e1765c3ef3ea31fe6e282376a16def1a96f5f11a0235055696c18d9d23ff30cb"}, - {file = "jiter-0.14.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:a25ffa2dbbdf8721855612f6dca15c108224b12d0c4024d0ac3d7902132b4211"}, - {file = "jiter-0.14.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ac9cbaa86c10996b92bd12c91659b60f939f8e28fcfa6bc11a0e90a774ce95b"}, - {file = "jiter-0.14.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:844e73b6c56b505e9e169234ea3bdea2ea43f769f847f47ac559ba1d2361ebea"}, - {file = "jiter-0.14.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e52c076f187405fc21523c746c04399c9af8ece566077ed147b2126f2bcba577"}, - {file = "jiter-0.14.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:fbd9e482663ca9d005d051330e4d2d8150bb208a209409c10f7e7dfdf7c49da9"}, - {file = "jiter-0.14.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:33a20d838b91ef376b3a56896d5b04e725c7df5bc4864cc6569cf046a8d73b6d"}, - {file = "jiter-0.14.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:432c4db5255d86a259efde91e55cb4c8d18c0521d844c9e2e7efcce3899fb016"}, - {file = "jiter-0.14.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67f00d94b281174144d6532a04b66a12cb866cbdc47c3af3bfe2973677f9861a"}, - {file = "jiter-0.14.0.tar.gz", hash = "sha256:e8a39e66dac7153cf3f964a12aad515afa8d74938ec5cc0018adcdae5367c79e"}, + {file = "jiter-0.17.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:ed1a24005daac667d577402d75a2922f9775a165b146b883ff1ad3602d8be689"}, + {file = "jiter-0.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b847b18d066c46b3b7ae49d6c94a7634c5e4a8983146ee25562a092000f5e3ad"}, + {file = "jiter-0.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b68d3495d95da120651a5628c7ebadee84ed001a1b76e6afc325c42482f15b5"}, + {file = "jiter-0.17.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c1a5336c04a41b1f1cf9572e294aec27cc569767ff73de7bf87a91f0bea7cb9"}, + {file = "jiter-0.17.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b75f85660108965a94be77911a25a253429307294d9415b3c597118977a614de"}, + {file = "jiter-0.17.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:32aaaa764604496610a3ad2d98503ae88ccb2fbe769e892ff4533e778e85f708"}, + {file = "jiter-0.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:826871c42cebaae22f0a2b5673a4a1a75c851bb2d13b3c17764a630a6b298984"}, + {file = "jiter-0.17.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:00b5a98df3e3a3e8cf7b619f4ac2f8bf975bbf3d95d02c5d17b8dbfe5c8b8245"}, + {file = "jiter-0.17.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6af5b74073bd25bae695e6d00919f6a9be7ed5a9f8836d981eb1ffe84139e6fb"}, + {file = "jiter-0.17.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:16dd0c1baf098ae70b8f3616574eb3fedf34e26670b89e16a7e67561f737ed2d"}, + {file = "jiter-0.17.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:545c36a0f3b2238c242cc9785439d3242a871b7bc39fe3f441bcaa07bf3aa83e"}, + {file = "jiter-0.17.0-cp310-cp310-win32.whl", hash = "sha256:155be7355bdb7ca76ab0961be8982c225f964a5c073a83984183f22391cc29fc"}, + {file = "jiter-0.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:37150a9e02e869475854fa20b7d0d5e26d18d0f8bc17293999973ff27e99ae7a"}, + {file = "jiter-0.17.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:cfafd7be8b16ceadd298db542cead37cddc211c4c49e04ad2596924df18625b1"}, + {file = "jiter-0.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8adca2e793288e5f1bb29279bb439d0d3cfbb50eddca7e7e6ffd42ff4f482406"}, + {file = "jiter-0.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30c692d567ba206c7cca38c9d1d0ccc70c9786290173c184d871ca12e9981ed7"}, + {file = "jiter-0.17.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:81c83c0abe614446a283d994d2c07c4f58632dea2cdf66ba9e2921bb8ccd593e"}, + {file = "jiter-0.17.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:073dc68c1a700c8fc480e877864a6b6ffc887533e261f4380c08c16bf09d057a"}, + {file = "jiter-0.17.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:492f37230bbf9581ab2c17bcda862c249afb9ae2e3ab2dd6db59943bc4cc3153"}, + {file = "jiter-0.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5888fe5abc1ca2fa834a3e1b4c7ef0dcece286a7d7e95a609ef0934b777b9fc9"}, + {file = "jiter-0.17.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:84ac78df457e1ee3f7e733bd114823302ae8c5ad5542d7e6647d92ffaa090a04"}, + {file = "jiter-0.17.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7573e80232c5bcf80c24c038cf7e53a463f5c3b1dd1dd4109d66304f4dccc233"}, + {file = "jiter-0.17.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:11902505d401691720f5785c15b02204248526edee11b635cd6c40cd52b81599"}, + {file = "jiter-0.17.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:64846211a2debe7c071d2146d2283d2b0c1c93dc8fd5fb7794faac2ca6061b5c"}, + {file = "jiter-0.17.0-cp311-cp311-win32.whl", hash = "sha256:c19b9357309b8cc6de8a48fca8e44a8c9c2feaaa2f5896d037fa505d48fcab80"}, + {file = "jiter-0.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:e654b6b04e39c9cb19cb8b04c6ddf1f2db07751fa14156413969fd78bad0e5cb"}, + {file = "jiter-0.17.0-cp311-cp311-win_arm64.whl", hash = "sha256:3ad556afc289f15d2b181b941982d01f06190863c07440185b9f354e1bd2def3"}, + {file = "jiter-0.17.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ebf918dfd6a74adc1b9ad71f63c4ab00902fcd3b7fd39f2e24d871db8d713b91"}, + {file = "jiter-0.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:61aed66ee042b3b49ef85fdf75714234d055d89d8496ac1c6e47f89e7a30d5e4"}, + {file = "jiter-0.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76eb4a5c20e86f9f848286f167024890f2862258a965d254774deb7fc1545ca1"}, + {file = "jiter-0.17.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bcc064f99183a9cbe7f26ed648c352031a74145cd61ed75d34632c73eb46a5a8"}, + {file = "jiter-0.17.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73b64e69c4150748e020356d958af94bec33c70a0a93d665cfa8f6d580fe1a63"}, + {file = "jiter-0.17.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0bc7f684b65bcda9c20434267577db71bf9905ceddd32b60d1d93278d8c8d3a"}, + {file = "jiter-0.17.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c21265b251d99bbb40080d178a8953e35601d3a1564e05c4de4c0d2ca616797"}, + {file = "jiter-0.17.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:f3d7f7b34114f7ddc6d72a8e882d49de636b35d9fd12b4d420d3c5729f6c9812"}, + {file = "jiter-0.17.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5078ab00664307fab2019b522a93aeb191122789f085daf5fd9e362154021d4a"}, + {file = "jiter-0.17.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:470e1b1e4c42f1ead2189166a299691871a2df5056c976e7fb96feafaf5f9d44"}, + {file = "jiter-0.17.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:6eb6aedeb7352b8f3b6af9cbd67983840165c00428e63f1b420a85885128ea31"}, + {file = "jiter-0.17.0-cp312-cp312-win32.whl", hash = "sha256:362bb47423886d45a9f705d2d9d4008c6eedd4e41eb1bab4e96fb6daa06b33fd"}, + {file = "jiter-0.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:9bd3caac219df476dd0cc3fe01d2f1581ed588906feac767abd9614c1c12f8b3"}, + {file = "jiter-0.17.0-cp312-cp312-win_arm64.whl", hash = "sha256:36ee6e69027396664e59995b9a635a947a5304ee9837279584a0bb8145c8f6b8"}, + {file = "jiter-0.17.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1b18434638228c0c184281609bf3d9459026a0f1ea48fb76c205e3ef72069caa"}, + {file = "jiter-0.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ec89771f4272b989487a6364e519db6bbaba323e8bbf949ac89a45ea9c18b7a3"}, + {file = "jiter-0.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e3f052c671d5f425cca5ea5901cf11a831369fba4a55a3862cab93c323b4c3b"}, + {file = "jiter-0.17.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:785a216bbaf8f15fc974e964ced7322cd3d774bb0e86949edd78c6bffd6ba35b"}, + {file = "jiter-0.17.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d85c558c9f8532bba287a990ac63767c7daf756f0d8c030219f62499b1fa228a"}, + {file = "jiter-0.17.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c23849235d2142ce444b2b8c6eceee9f82f4cc0bd5c9081602e4155c6197807"}, + {file = "jiter-0.17.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58df29268a95e910f17db7ec9178eb7f15aa8619aaca3575275c4e6b3f4fe4c5"}, + {file = "jiter-0.17.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:a277f97eba7d66b1ee27eb5dab5b774ff46a10c78d89a1d3dcce04ce1357c8ca"}, + {file = "jiter-0.17.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe15ddf316f1f1f643347d3a474e74ce61880c79a11ec5dca53df20c071bd3e8"}, + {file = "jiter-0.17.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:02adebb7ce6413c44d40af9ad59d1c1cd79630ccdcb6f7bdd2d461e48c03d8f9"}, + {file = "jiter-0.17.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:55d0e0e613a3f9ad600cf436e0e2b8057d1b52bcf1d91b2d36ac53451231e6a8"}, + {file = "jiter-0.17.0-cp313-cp313-win32.whl", hash = "sha256:2c45ad7c973ef33fe5114a953377b35a95240f4542c0724d9f781e47dc24bac7"}, + {file = "jiter-0.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:a3cebb1fe4a1abb00465f3f8a17e09112603e8b7c59e5c3adbcd9f7815a64acd"}, + {file = "jiter-0.17.0-cp313-cp313-win_arm64.whl", hash = "sha256:96b8b0c6dc5d78682f54a450785e075aa929cde768304cad363cd4efba5a82ac"}, + {file = "jiter-0.17.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:00d783a779c5664e16dbad5e3a3c3a75e128b07dd5f4765159658d9210a50ca5"}, + {file = "jiter-0.17.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0619d806e260ecf0c2a64521942c94af5d547c9ec99b55ae4f51b538b5576a76"}, + {file = "jiter-0.17.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc0288ce39190ee33fe6e4ec73161eed34e7e2da509b525546ca061778d62b64"}, + {file = "jiter-0.17.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5a52a430d04225ffde633e6840bf2381d34c019ff98526b5929755b9052fb199"}, + {file = "jiter-0.17.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:37f33d327900bf2879613b3363fd48df97b4232d0c41f54bcf2e790c2fc40a71"}, + {file = "jiter-0.17.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6cf564d43c4388149ca58ee571d0f5ccf875e20d1fd4662fd94cc0d1ea3b10ef"}, + {file = "jiter-0.17.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:523c499235fb65add25d4bb01b1c4709ce695efdc7deb6c0a7bc515b5c44e0fb"}, + {file = "jiter-0.17.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:455e4ab35cb2a4a91a8404e08fd3c621bae433922e59bf1c494fe20a426b013b"}, + {file = "jiter-0.17.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6871973bfbd4408f7f1c632b30bbb5bbd9671c1bc8650af6823e24b7be13709b"}, + {file = "jiter-0.17.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:77f6aac0137309b31448c1bdcda4c6c77077664a6d018ece8d94019c68a5a5b9"}, + {file = "jiter-0.17.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:93946d89fa04d5ba64dd323a8dd8d901676cb8a3c81d99ae4f6c051a9b4c3f2f"}, + {file = "jiter-0.17.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:70f19a2ca8429f91e82eeffb2f51cb87bc2d6e953b009b91a92d29c3a16ccb03"}, + {file = "jiter-0.17.0-cp314-cp314-win32.whl", hash = "sha256:71dbd74314c5df52a1bccf7b8bca46d14e943af7a2012e73b23f49977ef194c8"}, + {file = "jiter-0.17.0-cp314-cp314-win_amd64.whl", hash = "sha256:ac3c6ee3264d6f5c44c617f90bc7e8b9e1587e7d6708c9d8f811cb65582ee312"}, + {file = "jiter-0.17.0-cp314-cp314-win_arm64.whl", hash = "sha256:6219adaf59711ba7063a52496e8ec6d3fa3e209d7827d83eee3b2abc780a1744"}, + {file = "jiter-0.17.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:59bddbe6f9ffecc68d641e1e2d619ce64cf8a9e9eeb74e5c518f74fc87abf1b0"}, + {file = "jiter-0.17.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6cb41cd1432f1dc19a231cf70b54d42b2c9f05085155859263fce06fa4d41388"}, + {file = "jiter-0.17.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fd7790aa79c8b518e512ebcdfce9f11d8ef5f30efd43720c8a19a548b39fa489"}, + {file = "jiter-0.17.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dbbfe4e3c21c8166980cddc5bee1a315df082454f007947dfb6fb73800768165"}, + {file = "jiter-0.17.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c286860abfe8b100cac1c02e225e5776eb9216edd71ba17cdb237da4af32bc9"}, + {file = "jiter-0.17.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f753eb70b1474a29e635e7542ff7312e6d6b951e0b25e8a2e8c34eeb1ddcd478"}, + {file = "jiter-0.17.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:eae86b1f027031e39db2e0e9c4842221edb7b8cd474d23f87a79b3bd4b651768"}, + {file = "jiter-0.17.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5bf350452a43173e69e1fc74847c57a60e3d7515807287f29849baa2a85d8718"}, + {file = "jiter-0.17.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:da139721f4b7cafdbff580a4f511ea24cb91f4909330c6b926a1ca53836c0a59"}, + {file = "jiter-0.17.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:8079849db9a1371bfd90bad088458a8fb836261879df2233cc9632464ecf64e1"}, + {file = "jiter-0.17.0-cp314-cp314t-win32.whl", hash = "sha256:8f770b0c77e5fac482e1ba03ca1a7e18286bfb213d749932a00a7e4cd5de5e06"}, + {file = "jiter-0.17.0-cp314-cp314t-win_amd64.whl", hash = "sha256:c4289293e5278d9314b00f15c37f2120fa51d3d68565292e715524c750e775a9"}, + {file = "jiter-0.17.0-cp314-cp314t-win_arm64.whl", hash = "sha256:4dfbfe5a6e1e80a7082af559f66386405025ec278833e0c649f69cbc6e1004cc"}, + {file = "jiter-0.17.0-cp315-cp315-macosx_10_12_x86_64.whl", hash = "sha256:84963d3f395ef5e9a32ce47155e08a7962fa292c159a10cb98b931cef1416925"}, + {file = "jiter-0.17.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:ffa0380ad091de7d3fc33e17a97ff479851ee18a0a2a3ee56ff3215cdc886656"}, + {file = "jiter-0.17.0-cp315-cp315-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:755079792868ce5d4938e83b91a0939b34fb858a1ca65a104f2d771bea57faa1"}, + {file = "jiter-0.17.0-cp315-cp315-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3bf4dc2b84a464117fb097d15a25c58d100d2692888e3b0d92df5b48ed16b7c0"}, + {file = "jiter-0.17.0-cp315-cp315-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02a360707033d8cef53f7f3480817a1489177a259ec6ec01e98c37e0b922ddca"}, + {file = "jiter-0.17.0-cp315-cp315-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:300ce01ab0215e3dea4d00090143c909aedc65c0f809b3c07983e1d038f291b9"}, + {file = "jiter-0.17.0-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:746243a080b4ca790b8499af3d7cf9825d5f5987933950cd818e767ee353d826"}, + {file = "jiter-0.17.0-cp315-cp315-manylinux_2_31_riscv64.whl", hash = "sha256:b550585523339b71cb852b811aae49d08d7601ad8ffe9f5dc1562f4c3d22fd87"}, + {file = "jiter-0.17.0-cp315-cp315-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0239520085cac678e77a606fd7e3f1c60c371d719790c5e3807388d3da4354c2"}, + {file = "jiter-0.17.0-cp315-cp315-musllinux_1_1_aarch64.whl", hash = "sha256:eb2295da7c3769f6719b227a237aa6a5cfa6550e478bc838001b592c57e16575"}, + {file = "jiter-0.17.0-cp315-cp315-musllinux_1_1_x86_64.whl", hash = "sha256:e088612ff90ebc9247e1a43074b72835804261c47e6a6c01cb3ddcb55360d688"}, + {file = "jiter-0.17.0-cp315-cp315-win32.whl", hash = "sha256:0b52d52035b3907c5b1f6277857b29c1cbfc965e24e0f27330dbed83edb591ec"}, + {file = "jiter-0.17.0-cp315-cp315-win_amd64.whl", hash = "sha256:10f5558eed511b830488003449d942bd75829ad6257dc58cb9a03e596a7777b1"}, + {file = "jiter-0.17.0-cp315-cp315-win_arm64.whl", hash = "sha256:fa13acf1046f95df808c64b1310705e143fab87aee73ae00cc42d640867fd2c1"}, + {file = "jiter-0.17.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:af2f7501580f274b63c4b2283bc425f5df7edf06ae5b171e5f87d912ff359a20"}, + {file = "jiter-0.17.0-cp315-cp315t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10c5349312e5cb02b7a21e123a57665afa895953f05bf252a9dd4c13a572b7ab"}, + {file = "jiter-0.17.0-cp315-cp315t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:86f3f9343a288eb85a81ef20a752b2f84564296636db54a9fff0b5c8deaf1df2"}, + {file = "jiter-0.17.0-cp315-cp315t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4607ec7d93355fbc25b8dc5189153cf21d66063b9f9cd04dd2774e6e783f9b6a"}, + {file = "jiter-0.17.0-cp315-cp315t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10cd64a5720ad7f809ac5466ff1705813f1b6b510f195a73acafba0ac0e1f675"}, + {file = "jiter-0.17.0-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efe9f61bb30174d2f5c8396445c360c96c44e78164d0815dfe627ccf57849574"}, + {file = "jiter-0.17.0-cp315-cp315t-manylinux_2_31_riscv64.whl", hash = "sha256:370d8fe5bf201dc6925e8a84c81ac7291f74d9fd1778234fc79d517064a5c76b"}, + {file = "jiter-0.17.0-cp315-cp315t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6b303d88e6a0bda789ec4b7801c7bad68e27230ba1fe4baffc756d1fbd32dc9d"}, + {file = "jiter-0.17.0-cp315-cp315t-musllinux_1_1_aarch64.whl", hash = "sha256:30793a24a31e968969757c9e08d830cbb15a2cd3c4959b4498b38f4b1c2258eb"}, + {file = "jiter-0.17.0-cp315-cp315t-musllinux_1_1_x86_64.whl", hash = "sha256:686c93d86f2b426c803024b805bd161a6cd10e9627c23e901640eab646c0ad8a"}, + {file = "jiter-0.17.0-cp315-cp315t-win32.whl", hash = "sha256:86d703d9faa1ffc8ae4e9de0fa007712ed2171b5c0d93811a8e2e105ac729b0d"}, + {file = "jiter-0.17.0-cp315-cp315t-win_amd64.whl", hash = "sha256:42b0260445251b1bc520a63baa94a32d88e0f931fba234f1764db7feb7c72174"}, + {file = "jiter-0.17.0-cp315-cp315t-win_arm64.whl", hash = "sha256:d47687806f9c54c84ea38733507081337922beca90ce819c7d852dd485bc0f23"}, + {file = "jiter-0.17.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:eaba834b72d573547b9d966465b3394b749d5e14208cc70acb63aca37619ab33"}, + {file = "jiter-0.17.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:51e1519d676a9f14dad9c2a411170d43b022ddb7989562df4e849b261ce127b2"}, + {file = "jiter-0.17.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0ce4feb52493e3513335b2accdcd75605652e4632772d3c8c2f7b86954d7f39"}, + {file = "jiter-0.17.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29f49b325e0234e4ad9ecca5b861ffbd09b95ccac9bd46fa55841b6e56eea5fe"}, + {file = "jiter-0.17.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:454c4997d73cc466c71fd565d91e603b0274e48ea0c6b0b7a7aee6967e4ceb7c"}, + {file = "jiter-0.17.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:40d2c240f8f80b5b0f201b29f0ae129c81448c60c772227a41747b5e0026f6a2"}, + {file = "jiter-0.17.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e05f5adbf68c4bd11e1610f394034d984152988e84be6f8314235ce6f2139e5"}, + {file = "jiter-0.17.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2c0bf24c72fd0491405dce5d40194f2070e9021ce648c1a1d46234b93d848ff"}, + {file = "jiter-0.17.0.tar.gz", hash = "sha256:03e432f226a453851079fb84cd17c6da9991eab723e28d716f14ae3d906e0c12"}, ] [[package]] @@ -1042,7 +1102,7 @@ pydantic-settings = ">=2.10.1,<3.0.0" pyyaml = ">=5.3.0,<7.0.0" requests = ">=2.32.5,<3.0.0" sqlalchemy = ">=1.4.0,<3.0.0" -tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<10.0.0" +tenacity = ">=8.1.0,!=8.4.0,<10.0.0" [[package]] name = "langchain-core" @@ -1064,7 +1124,7 @@ langsmith = ">=0.3.45,<1.0.0" packaging = ">=23.2.0" pydantic = ">=2.7.4,<3.0.0" pyyaml = ">=5.3.0,<7.0.0" -tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<10.0.0" +tenacity = ">=8.1.0,!=8.4.0,<10.0.0" typing-extensions = ">=4.7.0,<5.0.0" uuid-utils = ">=0.12.0,<1.0" @@ -1102,7 +1162,7 @@ files = [ httpx = ">=0.28.0" langchain-core = ">=0.3.34,<2.0.0" langchain-openai = ">=0.3.11" -numpy = ">=1.26.4,<2.0.2 || >2.0.2" +numpy = ">=1.26.4,!=2.0.2" pinecone = {version = ">=6.0.0,<8.0.0", extras = ["asyncio"]} pydantic = ">=2.11.1" simsimd = ">=5.9.11" @@ -1425,31 +1485,28 @@ files = [ [[package]] name = "openai" -version = "2.48.0" +version = "3.20.0" description = "The official Python library for the openai API" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main"] files = [ - {file = "openai-2.48.0-py3-none-any.whl", hash = "sha256:c98df30aaaf93c51979f64d3e7c5b76464f8be0173368266229eb8fe6bd30f2c"}, - {file = "openai-2.48.0.tar.gz", hash = "sha256:231b1e7661dda14574986c2f71451e9d584b7fe69e0ee6480e12ed090b48fc16"}, + {file = "openai-3.20.0-py3-none-any.whl", hash = "sha256:fb1b109e3423ed51c6ade96bbb0fffddae39c8e64bb9b6e501659bcbaa5ad30c"}, + {file = "openai-3.20.0.tar.gz", hash = "sha256:5e5dc0a3c0a9362e69cd35a65d04580a73a66eb39d5abeb78881b6190ca5d98c"}, ] [package.dependencies] -anyio = ">=3.5.0,<5" -distro = ">=1.7.0,<2" -httpx = ">=0.23.0,<1" -jiter = ">=0.10.0,<1" -pydantic = ">=1.9.0,<3" +anyio = ">=4.10.0,<5" +httpx2 = ">=2.12.0,<3" +jiter = ">=0.16.0,<1" +pydantic = ">=1.10.13,<2.0 || >=2.4.dev0,<3" sniffio = "*" -tqdm = ">4" typing-extensions = ">=4.14,<5" [package.extras] -aiohttp = ["aiohttp (>=3.14.1) ; python_version >= \"3.10\"", "httpx-aiohttp (>=0.1.9) ; python_version >= \"3.10\""] -bedrock = ["botocore (>=1.40.0,<1.43) ; python_version < \"3.10\"", "botocore (>=1.40.0,<2) ; python_version >= \"3.10\""] -datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] -httpx2 = ["anyio (>=4.10.0,<5) ; python_version >= \"3.10\"", "httpx (>=0.25.1,<1) ; python_version >= \"3.10\"", "httpx2 (>=2.7.0,<3) ; python_version >= \"3.10\""] +aiohttp = ["aiohttp (>=3.14.3)"] +bedrock = ["botocore (>=1.40.0,<2)", "urllib3 (>=2.7.0,<3)"] +datalib = ["numpy (>=1)", "pandas (>=1.2.3)"] realtime = ["websockets (>=13,<16)"] voice-helpers = ["numpy (>=2.0.2)", "sounddevice (>=0.5.1)"] @@ -3054,6 +3111,19 @@ notebook = ["ipywidgets (>=6)"] slack = ["slack-sdk"] telegram = ["requests"] +[[package]] +name = "truststore" +version = "0.10.4" +description = "Verify certificates using native system trust stores" +optional = false +python-versions = ">=3.10" +groups = ["main"] +markers = "sys_platform != \"emscripten\"" +files = [ + {file = "truststore-0.10.4-py3-none-any.whl", hash = "sha256:adaeaecf1cbb5f4de3b1959b42d41f6fab57b2b1666adb59e89cb0b53361d981"}, + {file = "truststore-0.10.4.tar.gz", hash = "sha256:9d91bd436463ad5e4ee4aba766628dd6cd7010cf3e2461756b3303710eebc301"}, +] + [[package]] name = "typing-extensions" version = "4.15.0" @@ -3760,4 +3830,4 @@ cffi = ["cffi (>=1.17,<2.0) ; platform_python_implementation != \"PyPy\" and pyt [metadata] lock-version = "2.1" python-versions = "3.11.*" -content-hash = "8886c2739952046692045906293b67f982abb2f848864097d8f667304f50bf8f" +content-hash = "c9cc186b6064f6d4a242742363d26161e6d45f5fcbf672a135463eb83ea39f1c" diff --git a/pyproject.toml b/pyproject.toml index b80f6797..d0a86af0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ requires-poetry = ">=2.3.2" [tool.poetry.dependencies] python = "3.11.*" -openai = "^2.48" +openai = "^3.20" python-dotenv = "^1.2.3" anthropic = "^0.119.0" From 8bb69616b968950ffc60425aaccc2e7638fb83ca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Oct 2026 14:37:38 +0000 Subject: [PATCH 06/22] Bump pandas from 2.3.3 to 3.0.6 Bumps [pandas](https://github.com/pandas-dev/pandas) from 2.3.3 to 3.0.6. - [Release notes](https://github.com/pandas-dev/pandas/releases) - [Commits](https://github.com/pandas-dev/pandas/compare/v2.3.3...v3.0.6) --- updated-dependencies: - dependency-name: pandas dependency-version: 3.0.6 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- poetry.lock | 196 ++++++++++++++++++++++++------------------------- pyproject.toml | 2 +- 2 files changed, 95 insertions(+), 103 deletions(-) diff --git a/poetry.lock b/poetry.lock index 6ea8d960..db8257f2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.4.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.5.1 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" @@ -1042,7 +1042,7 @@ pydantic-settings = ">=2.10.1,<3.0.0" pyyaml = ">=5.3.0,<7.0.0" requests = ">=2.32.5,<3.0.0" sqlalchemy = ">=1.4.0,<3.0.0" -tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<10.0.0" +tenacity = ">=8.1.0,!=8.4.0,<10.0.0" [[package]] name = "langchain-core" @@ -1064,7 +1064,7 @@ langsmith = ">=0.3.45,<1.0.0" packaging = ">=23.2.0" pydantic = ">=2.7.4,<3.0.0" pyyaml = ">=5.3.0,<7.0.0" -tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<10.0.0" +tenacity = ">=8.1.0,!=8.4.0,<10.0.0" typing-extensions = ">=4.7.0,<5.0.0" uuid-utils = ">=0.12.0,<1.0" @@ -1102,7 +1102,7 @@ files = [ httpx = ">=0.28.0" langchain-core = ">=0.3.34,<2.0.0" langchain-openai = ">=0.3.11" -numpy = ">=1.26.4,<2.0.2 || >2.0.2" +numpy = ">=1.26.4,!=2.0.2" pinecone = {version = ">=6.0.0,<8.0.0", extras = ["asyncio"]} pydantic = ">=2.11.1" simsimd = ">=5.9.11" @@ -1729,99 +1729,102 @@ files = [ [[package]] name = "pandas" -version = "2.3.3" +version = "3.0.6" description = "Powerful data structures for data analysis, time series, and statistics" optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:376c6446ae31770764215a6c937f72d917f214b43560603cd60da6408f183b6c"}, - {file = "pandas-2.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e19d192383eab2f4ceb30b412b22ea30690c9e618f78870357ae1d682912015a"}, - {file = "pandas-2.3.3-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5caf26f64126b6c7aec964f74266f435afef1c1b13da3b0636c7518a1fa3e2b1"}, - {file = "pandas-2.3.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd7478f1463441ae4ca7308a70e90b33470fa593429f9d4c578dd00d1fa78838"}, - {file = "pandas-2.3.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4793891684806ae50d1288c9bae9330293ab4e083ccd1c5e383c34549c6e4250"}, - {file = "pandas-2.3.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28083c648d9a99a5dd035ec125d42439c6c1c525098c58af0fc38dd1a7a1b3d4"}, - {file = "pandas-2.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:503cf027cf9940d2ceaa1a93cfb5f8c8c7e6e90720a2850378f0b3f3b1e06826"}, - {file = "pandas-2.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:602b8615ebcc4a0c1751e71840428ddebeb142ec02c786e8ad6b1ce3c8dec523"}, - {file = "pandas-2.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8fe25fc7b623b0ef6b5009149627e34d2a4657e880948ec3c840e9402e5c1b45"}, - {file = "pandas-2.3.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b468d3dad6ff947df92dcb32ede5b7bd41a9b3cceef0a30ed925f6d01fb8fa66"}, - {file = "pandas-2.3.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b98560e98cb334799c0b07ca7967ac361a47326e9b4e5a7dfb5ab2b1c9d35a1b"}, - {file = "pandas-2.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37b5848ba49824e5c30bedb9c830ab9b7751fd049bc7914533e01c65f79791"}, - {file = "pandas-2.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db4301b2d1f926ae677a751eb2bd0e8c5f5319c9cb3f88b0becbbb0b07b34151"}, - {file = "pandas-2.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:f086f6fe114e19d92014a1966f43a3e62285109afe874f067f5abbdcbb10e59c"}, - {file = "pandas-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d21f6d74eb1725c2efaa71a2bfc661a0689579b58e9c0ca58a739ff0b002b53"}, - {file = "pandas-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3fd2f887589c7aa868e02632612ba39acb0b8948faf5cc58f0850e165bd46f35"}, - {file = "pandas-2.3.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecaf1e12bdc03c86ad4a7ea848d66c685cb6851d807a26aa245ca3d2017a1908"}, - {file = "pandas-2.3.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b3d11d2fda7eb164ef27ffc14b4fcab16a80e1ce67e9f57e19ec0afaf715ba89"}, - {file = "pandas-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a68e15f780eddf2b07d242e17a04aa187a7ee12b40b930bfdd78070556550e98"}, - {file = "pandas-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:371a4ab48e950033bcf52b6527eccb564f52dc826c02afd9a1bc0ab731bba084"}, - {file = "pandas-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:a16dcec078a01eeef8ee61bf64074b4e524a2a3f4b3be9326420cabe59c4778b"}, - {file = "pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713"}, - {file = "pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8"}, - {file = "pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d"}, - {file = "pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac"}, - {file = "pandas-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c"}, - {file = "pandas-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493"}, - {file = "pandas-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee"}, - {file = "pandas-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5"}, - {file = "pandas-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21"}, - {file = "pandas-2.3.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78"}, - {file = "pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110"}, - {file = "pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86"}, - {file = "pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc"}, - {file = "pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0"}, - {file = "pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593"}, - {file = "pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c"}, - {file = "pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b"}, - {file = "pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6"}, - {file = "pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3"}, - {file = "pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5"}, - {file = "pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec"}, - {file = "pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7"}, - {file = "pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450"}, - {file = "pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5"}, - {file = "pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788"}, - {file = "pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87"}, - {file = "pandas-2.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c503ba5216814e295f40711470446bc3fd00f0faea8a086cbc688808e26f92a2"}, - {file = "pandas-2.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a637c5cdfa04b6d6e2ecedcb81fc52ffb0fd78ce2ebccc9ea964df9f658de8c8"}, - {file = "pandas-2.3.3-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:854d00d556406bffe66a4c0802f334c9ad5a96b4f1f868adf036a21b11ef13ff"}, - {file = "pandas-2.3.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf1f8a81d04ca90e32a0aceb819d34dbd378a98bf923b6398b9a3ec0bf44de29"}, - {file = "pandas-2.3.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:23ebd657a4d38268c7dfbdf089fbc31ea709d82e4923c5ffd4fbd5747133ce73"}, - {file = "pandas-2.3.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5554c929ccc317d41a5e3d1234f3be588248e61f08a74dd17c9eabb535777dc9"}, - {file = "pandas-2.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:d3e28b3e83862ccf4d85ff19cf8c20b2ae7e503881711ff2d534dc8f761131aa"}, - {file = "pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b"}, +python-versions = ">=3.11" +groups = ["main"] +files = [ + {file = "pandas-3.0.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:085e3786ae6b2e82b406266bce36690f72b9dc1421903ba9296b2981a9fcf586"}, + {file = "pandas-3.0.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d7564d86a94c2eb8ab290b07f63ddaae5c032fa53897c29a2ff2197d43aee8af"}, + {file = "pandas-3.0.6-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e7c0afdcaf6661d795fcefc2f647ddd1136f62cdc153fba177c685d97a87808"}, + {file = "pandas-3.0.6-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47121f9571503f724c9b93e297ab6254ac99c77adf5e9ed085ea419fd585c258"}, + {file = "pandas-3.0.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:994a79608263fe1c14cc48ffa7300e2b834b7d1cb406ffe96a08828cb0cdd79b"}, + {file = "pandas-3.0.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a3a22e07fe75347eaacc75b0e85297947af4fba6b4aae23916bd8b6828d0bba3"}, + {file = "pandas-3.0.6-cp311-cp311-win_amd64.whl", hash = "sha256:2e5fa32ff162dfdbc280157d664f44d23049ae414725af9676df339c501d82cd"}, + {file = "pandas-3.0.6-cp311-cp311-win_arm64.whl", hash = "sha256:5e75072773c1b2f7cb63faa3a6f562aede11f3976f68ed34cb538bc091a28171"}, + {file = "pandas-3.0.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7dac2d65e9087e8e7b5a45fe15c4920911a221df061ab629943ce016489145c7"}, + {file = "pandas-3.0.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9dab635a549e58a053c7b0fa054dc0bd7be22f0ed9a720f4a85d5fb993276172"}, + {file = "pandas-3.0.6-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e3dccb584123b399c07562ac4d62543e90ede49ddf8ce3c13ffc64cbe828c281"}, + {file = "pandas-3.0.6-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0704044b676496b8350e023b09f174a26772456c974a2b11c36bebb558c9490d"}, + {file = "pandas-3.0.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e7c1905ef02c3d6d43d9dbd5b6ccb4da4870a0b0c821bbc103fbdb6f3ad2707b"}, + {file = "pandas-3.0.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:569e114072b24fc4970c12e2b4bab252671668a40b324318903380cab0254c0c"}, + {file = "pandas-3.0.6-cp312-cp312-pyemscripten_2024_0_wasm32.whl", hash = "sha256:2a8fc94be2ee5f1d86f97aacd8cc566f81680b6498e76f3007421bb5d98151bf"}, + {file = "pandas-3.0.6-cp312-cp312-win_amd64.whl", hash = "sha256:3ef908d28590b3f42d7070e7ad8f9b34b442b260b7f3c1afb57e0040c58cdb1b"}, + {file = "pandas-3.0.6-cp312-cp312-win_arm64.whl", hash = "sha256:f4e7c52eb108d752e7592268108fd3e98efd76d83a3125cdd06c621c2e44359b"}, + {file = "pandas-3.0.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9ae8073aed8e21d1a7fe263dcdc6840743549722a6738198a0a46000fa9476f2"}, + {file = "pandas-3.0.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:60d81f9e1799b36f3739e7fff44d1fbb2e8fd5a271b3863e03de9715fccda0fa"}, + {file = "pandas-3.0.6-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:097090508a1dd335013d39106fc10b20f4fd4a171638e47b77d55798ed9dab6c"}, + {file = "pandas-3.0.6-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1e92d9fa834c7d877130027cddc0cad8dcff97c1f6cca26bd6310f847228b658"}, + {file = "pandas-3.0.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b27c8d890e4aa2171437ae2a39de1d215e674158e4865c4023a8b31c932513b2"}, + {file = "pandas-3.0.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f8029ec0f1f89e4f985929ce1f6626dabf3140d61a4e9c1215afdab34eaf9a5d"}, + {file = "pandas-3.0.6-cp313-cp313-win_amd64.whl", hash = "sha256:f3ce8a6968045481e91a3990e797e348ce13db45ee164a7095bbc824e26c09dd"}, + {file = "pandas-3.0.6-cp313-cp313-win_arm64.whl", hash = "sha256:cc39303913e2ea129915670de5d1c9fbd647f543bb72e5543bac8baa94e9e42f"}, + {file = "pandas-3.0.6-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ee913a91669056c1de1a6b733fbfeab711de9e54e3bee2dfa5fe79d9457247d1"}, + {file = "pandas-3.0.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ff51a4459ed036e93d1eb1bb5e6e7b28685d3cb6b7c12b91c05b31024e234729"}, + {file = "pandas-3.0.6-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:654aae059295dbba6ecd2328ca12712a2cf1676214c8699f1c29213f7ccf9c34"}, + {file = "pandas-3.0.6-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62f51d7f651c8054c5e82a69265c98082e795d1442df7ca6edc3a545d61214b1"}, + {file = "pandas-3.0.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:22172a92e7ee678ec0140c7af4fc9366b55413834a1cd86af78b3caa0b0574de"}, + {file = "pandas-3.0.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:583be68728a31d0d750d5b8d9e00f02b153df0d4655f858bde93cb84cfc4227c"}, + {file = "pandas-3.0.6-cp314-cp314-win_amd64.whl", hash = "sha256:77ccbe5057aece6fc172b9b77f19c04335af6882bc2e10c8f3ee4e6bfb3da553"}, + {file = "pandas-3.0.6-cp314-cp314-win_arm64.whl", hash = "sha256:fb625f426b375bcc96e3a04c5d5d266cd7be6ae5d6866e0e703382ab5164068c"}, + {file = "pandas-3.0.6-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9e492cd4bdba6778de4fe0df7f4590c012161ebcf9902dce01b01dc683105514"}, + {file = "pandas-3.0.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d7dcd21238cbb4828ff148481ba01cac8946dc5121457b5aeba28636f8f99a60"}, + {file = "pandas-3.0.6-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6ff482fa91fa2bafd92e8fe66ce3645c851824310f295c1f0a2f96e928fc4541"}, + {file = "pandas-3.0.6-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:db7ec631f26223beee8e5c9e0b8f23c24d8197bbd1d982421d4e3188bea51965"}, + {file = "pandas-3.0.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd75ed0c840f709fc2ae26ddd9534ac77ca1a48ac0cce521a74acaa85f3340a7"}, + {file = "pandas-3.0.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ef738d71d1059245b6bb03e312be06d8b3821326a83486c1ad03b9aba3710e44"}, + {file = "pandas-3.0.6-cp314-cp314t-win_amd64.whl", hash = "sha256:429d9df32731ab01383ed98f2baa7a60368090d1a94fc06019a12062510e8630"}, + {file = "pandas-3.0.6-cp314-cp314t-win_arm64.whl", hash = "sha256:a4dbd4dc65cbe645b92b8785d0f96dd7311010dc6606cf620e51b07b8788a12a"}, + {file = "pandas-3.0.6-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:50c44cbf5820b6b91a5f74aae04972472aefadd3cd9fbd1010409d85528bd570"}, + {file = "pandas-3.0.6-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:eb6900de08ac85f93ac4948aa6b80842eba555875337b8359035ac9c43e92d34"}, + {file = "pandas-3.0.6-cp315-cp315-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e25e2e1adee99ddfada6f7206a79ae8e9c8a8861b0e3eaaba165006d3eef18e"}, + {file = "pandas-3.0.6-cp315-cp315-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4ff44b2cb51cbd691c91f92c4ea6c71e34003f239ebd67c2e857dc898466b49c"}, + {file = "pandas-3.0.6-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:5edd0a7abb0986ecce1ac81f56d99b6763f86aa6946dceb6c661224f90af5a19"}, + {file = "pandas-3.0.6-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:1bcb3e9ed29e74a7439cedff9e2aefd3ea65de84d7de9ccb6c194192541bd60e"}, + {file = "pandas-3.0.6-cp315-cp315-win_amd64.whl", hash = "sha256:253e12cb9081b0afbac607920f6142975966bc315135e09de275fdbaa415d2de"}, + {file = "pandas-3.0.6-cp315-cp315-win_arm64.whl", hash = "sha256:97274c9adf6255bb48c620cd6959805efa7f09ea2167f0e0ae006a448cd2fca7"}, + {file = "pandas-3.0.6-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:265f562fdd1079f69f3de96dd425c3405224038c0af4f920c54bd240ee2c4640"}, + {file = "pandas-3.0.6-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:c6e4aae3e9bea26c6c9a20d88d96c86ec4a99b4db5fd516bcb4e829ab2c0ee36"}, + {file = "pandas-3.0.6-cp315-cp315t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a77a1a44e4d88f1c6a2a64d3eb12efec8420875722e14279800b173a7c7c2804"}, + {file = "pandas-3.0.6-cp315-cp315t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:86fa853a12e0b70927e2b1ee00d56d2224ec9cbb4b9d58348b5ad52d2f21150e"}, + {file = "pandas-3.0.6-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:c826e9babb7790142c399f58599d8de679bea059d7b39c5b6efa2096fac37266"}, + {file = "pandas-3.0.6-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:8fe77b408d82e2615674dfed62533b95e18a03610573877422aada4f625d4947"}, + {file = "pandas-3.0.6-cp315-cp315t-win_amd64.whl", hash = "sha256:83e91d15738d7783c050197cef2f2cf82fc6353dae9865aa87ed1fa16aa4d55a"}, + {file = "pandas-3.0.6-cp315-cp315t-win_arm64.whl", hash = "sha256:963ca21199097a84c7827c4678b04e30833084fbf8ef44fde3fa7180a29f8fa0"}, + {file = "pandas-3.0.6.tar.gz", hash = "sha256:66b07ef7315a31bfe1089cd3d71a7de781c9dca986762d0b4fe7c0ef17465d10"}, ] [package.dependencies] -numpy = {version = ">=1.23.2", markers = "python_version == \"3.11\""} +numpy = {version = ">=1.26.0", markers = "python_version < \"3.14\""} python-dateutil = ">=2.8.2" -pytz = ">=2020.1" -tzdata = ">=2022.7" +tzdata = {version = "*", markers = "sys_platform == \"win32\" or sys_platform == \"emscripten\""} [package.extras] -all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] -aws = ["s3fs (>=2022.11.0)"] -clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] -compression = ["zstandard (>=0.19.0)"] -computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] -consortium-standard = ["dataframe-api-compat (>=0.1.7)"] -excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] -feather = ["pyarrow (>=10.0.1)"] -fss = ["fsspec (>=2022.11.0)"] -gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] -hdf5 = ["tables (>=3.8.0)"] -html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] -mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] -output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] -parquet = ["pyarrow (>=10.0.1)"] -performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] -plot = ["matplotlib (>=3.6.3)"] -postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] -pyarrow = ["pyarrow (>=10.0.1)"] -spss = ["pyreadstat (>=1.2.0)"] -sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] -test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] -xml = ["lxml (>=4.9.2)"] +all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "adbc-driver-sqlite (>=1.2.0)", "beautifulsoup4 (>=4.12.3)", "bottleneck (>=1.4.2)", "fastparquet (>=2024.11.0)", "fsspec (>=2024.10.0)", "gcsfs (>=2024.10.0)", "html5lib (>=1.1)", "hypothesis (>=6.116.0)", "jinja2 (>=3.1.5)", "lxml (>=5.3.0)", "matplotlib (>=3.9.3)", "numba (>=0.60.0)", "numexpr (>=2.10.2)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.5)", "psycopg2 (>=2.9.10)", "pyarrow (>=13.0.0)", "pyiceberg (>=0.8.1)", "pymysql (>=1.1.1)", "pyreadstat (>=1.2.8)", "pytest (>=8.3.4)", "pytest-xdist (>=3.6.1)", "python-calamine (>=0.3.0)", "pytz (>=2020.1)", "pyxlsb (>=1.0.10)", "qtpy (>=2.4.2)", "s3fs (>=2024.10.0)", "scipy (>=1.14.1)", "tables (>=3.10.1)", "tabulate (>=0.9.0)", "xarray (>=2024.10.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.2.0)", "zstandard (>=0.23.0)"] +aws = ["s3fs (>=2024.10.0)"] +clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.4.2)"] +compression = ["zstandard (>=0.23.0)"] +computation = ["scipy (>=1.14.1)", "xarray (>=2024.10.0)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.5)", "python-calamine (>=0.3.0)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.2.0)"] +feather = ["pyarrow (>=13.0.0)"] +fss = ["fsspec (>=2024.10.0)"] +gcp = ["gcsfs (>=2024.10.0)"] +hdf5 = ["tables (>=3.10.1)"] +html = ["beautifulsoup4 (>=4.12.3)", "html5lib (>=1.1)", "lxml (>=5.3.0)"] +iceberg = ["pyiceberg (>=0.8.1)"] +mysql = ["SQLAlchemy (>=2.0.36)", "pymysql (>=1.1.1)"] +output-formatting = ["jinja2 (>=3.1.5)", "tabulate (>=0.9.0)"] +parquet = ["pyarrow (>=13.0.0)"] +performance = ["bottleneck (>=1.4.2)", "numba (>=0.60.0)", "numexpr (>=2.10.2)"] +plot = ["matplotlib (>=3.9.3)"] +postgresql = ["SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "psycopg2 (>=2.9.10)"] +pyarrow = ["pyarrow (>=13.0.0)"] +spss = ["pyreadstat (>=1.2.8)"] +sql-other = ["SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "adbc-driver-sqlite (>=1.2.0)"] +test = ["hypothesis (>=6.116.0)", "pytest (>=8.3.4,<9.1)", "pytest-xdist (>=3.6.1)"] +timezone = ["pytz (>=2020.1)"] +xml = ["lxml (>=5.3.0)"] [[package]] name = "pgvector" @@ -2380,18 +2383,6 @@ files = [ [package.extras] cli = ["click (>=5.0)"] -[[package]] -name = "pytz" -version = "2026.3.post1" -description = "World timezone definitions, modern and historical" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "pytz-2026.3.post1-py2.py3-none-any.whl", hash = "sha256:dd95840dd199baea12d9cc096a1d452caa6596a1c1e4b5f3dbd1541855d5e815"}, - {file = "pytz-2026.3.post1.tar.gz", hash = "sha256:2211d3fcf9a797d3405cac96ac7f61d80e6a644f72a3309607282fe8a2010c5d"}, -] - [[package]] name = "pyyaml" version = "6.0.3" @@ -3088,6 +3079,7 @@ description = "Provider of IANA time zone data" optional = false python-versions = ">=2" groups = ["main"] +markers = "sys_platform == \"win32\" or sys_platform == \"emscripten\"" files = [ {file = "tzdata-2026.3-py2.py3-none-any.whl", hash = "sha256:dc096730c87af6cab1b171c9d532be840741ff5d459015e7f6947bd7d7e54931"}, {file = "tzdata-2026.3.tar.gz", hash = "sha256:4a1518b8993086a7982523e071643f3c0e5f213e75b21318e78bcabfff9d1415"}, @@ -3760,4 +3752,4 @@ cffi = ["cffi (>=1.17,<2.0) ; platform_python_implementation != \"PyPy\" and pyt [metadata] lock-version = "2.1" python-versions = "3.11.*" -content-hash = "8886c2739952046692045906293b67f982abb2f848864097d8f667304f50bf8f" +content-hash = "d2832d4c8e7c7d40356294181ef1b14f1bafc99eeb8d2b64e9b367612f4b23a9" diff --git a/pyproject.toml b/pyproject.toml index b80f6797..c50e6dd1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,7 @@ psycopg2-binary = "^2.9.13" langfuse = "^4.15.4" opentelemetry-instrumentation-anthropic = "^0.62.3" opentelemetry-instrumentation-threading = "0.65b0" -pandas = "^2.2" +pandas = "^3.0" pgvector = "^0.5.0" [tool.poetry.group.dev] From aeefb2d9fe0eaf2ffca22b22c15bb0c1575e02d2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Oct 2026 14:38:00 +0000 Subject: [PATCH 07/22] Bump anthropic from 0.119.0 to 1.9.0 Bumps [anthropic](https://github.com/anthropics/anthropic-sdk-python) from 0.119.0 to 1.9.0. - [Release notes](https://github.com/anthropics/anthropic-sdk-python/releases) - [Changelog](https://github.com/anthropics/anthropic-sdk-python/blob/main/CHANGELOG.md) - [Commits](https://github.com/anthropics/anthropic-sdk-python/compare/v0.119.0...v1.9.0) --- updated-dependencies: - dependency-name: anthropic dependency-version: 1.9.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- poetry.lock | 94 ++++++++++++++++++++++++++++++++++++++++---------- pyproject.toml | 2 +- 2 files changed, 77 insertions(+), 19 deletions(-) diff --git a/poetry.lock b/poetry.lock index 6ea8d960..d7050281 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.4.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.5.1 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" @@ -199,32 +199,31 @@ files = [ [[package]] name = "anthropic" -version = "0.119.0" +version = "1.9.0" description = "The official Python library for the anthropic API" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main"] files = [ - {file = "anthropic-0.119.0-py3-none-any.whl", hash = "sha256:2b39107077489d19d7c66000e9d9263293d431550fcf6b543ead785c6ac85962"}, - {file = "anthropic-0.119.0.tar.gz", hash = "sha256:40a81b094ae2a0056a77771257943b19bd46edce1326e22f85c2794492097f0a"}, + {file = "anthropic-1.9.0-py3-none-any.whl", hash = "sha256:a7fe05a9e4b72113b934501698df5d56484ac89f05677f0f793f8bfddb15cfff"}, + {file = "anthropic-1.9.0.tar.gz", hash = "sha256:da5191a0af0b853a797fc0c6b09fc5b05cb5d9da063ba80fdd03c736abe81b6c"}, ] [package.dependencies] -anyio = ">=3.5.0,<5" -distro = ">=1.7.0,<2" +anyio = ">=4.1.0,<5" docstring-parser = ">=0.15,<1" -httpx = ">=0.25.0,<1" +httpx2 = ">=2.0.0,<3" jiter = ">=0.4.0,<1" -pydantic = ">=1.9.0,<3" -sniffio = "*" +pydantic = ">=1.10.0,<3" +sniffio = ">=1,<2" typing-extensions = ">=4.14,<5" [package.extras] -aiohttp = ["aiohttp", "httpx-aiohttp (>=0.1.9,<1)"] -aws = ["boto3 (>=1.28.57)", "botocore (>=1.31.57)"] -bedrock = ["boto3 (>=1.28.57)", "botocore (>=1.31.57)"] +aiohttp = ["aiohttp (>=3.10.0,<4)"] +aws = ["boto3 (>=1.28.57,<2)", "botocore (>=1.31.57,<2)"] +bedrock = ["boto3 (>=1.28.57,<2)", "botocore (>=1.31.57,<2)"] google-cloud = ["google-auth[requests] (>=2,<3)"] -mcp = ["mcp (>=1.0) ; python_version >= \"3.10\""] +mcp = ["mcp (>=1.0,<3) ; python_version >= \"3.10\""] vertex = ["google-auth[requests] (>=2,<3)"] webhooks = ["standardwebhooks (>=1.0.1,<2)"] @@ -757,6 +756,28 @@ http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] trio = ["trio (>=0.22.0,<1.0)"] +[[package]] +name = "httpcore2" +version = "2.3.0" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "httpcore2-2.3.0-py3-none-any.whl", hash = "sha256:477e9e334f74e5240dcac002e890580f36a57d40ff0fb14cc9655731d23b8415"}, + {file = "httpcore2-2.3.0.tar.gz", hash = "sha256:07327e251560960eea8e969d92d4c6a325feb13cca39e25340731336c3baf924"}, +] + +[package.dependencies] +h11 = ">=0.16" +truststore = ">=0.10" + +[package.extras] +asyncio = ["anyio (>=4.5.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<1.0)"] + [[package]] name = "httpx" version = "0.28.1" @@ -794,6 +815,31 @@ files = [ {file = "httpx_sse-0.4.3.tar.gz", hash = "sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d"}, ] +[[package]] +name = "httpx2" +version = "2.3.0" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "httpx2-2.3.0-py3-none-any.whl", hash = "sha256:6f393663bdf6dbe7fe90118e3eb5b2bd024a675cae0390ac08cec9198812d8b7"}, + {file = "httpx2-2.3.0.tar.gz", hash = "sha256:227e7c41d95a76d4077a52640564132777215fc3394e07b66a3116c33d668fa9"}, +] + +[package.dependencies] +anyio = "*" +httpcore2 = "2.3.0" +idna = "*" +truststore = ">=0.10" + +[package.extras] +brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<15)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +zstd = ["zstandard (>=0.18.0) ; python_version <= \"3.13\""] + [[package]] name = "idna" version = "3.15" @@ -1042,7 +1088,7 @@ pydantic-settings = ">=2.10.1,<3.0.0" pyyaml = ">=5.3.0,<7.0.0" requests = ">=2.32.5,<3.0.0" sqlalchemy = ">=1.4.0,<3.0.0" -tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<10.0.0" +tenacity = ">=8.1.0,!=8.4.0,<10.0.0" [[package]] name = "langchain-core" @@ -1064,7 +1110,7 @@ langsmith = ">=0.3.45,<1.0.0" packaging = ">=23.2.0" pydantic = ">=2.7.4,<3.0.0" pyyaml = ">=5.3.0,<7.0.0" -tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<10.0.0" +tenacity = ">=8.1.0,!=8.4.0,<10.0.0" typing-extensions = ">=4.7.0,<5.0.0" uuid-utils = ">=0.12.0,<1.0" @@ -1102,7 +1148,7 @@ files = [ httpx = ">=0.28.0" langchain-core = ">=0.3.34,<2.0.0" langchain-openai = ">=0.3.11" -numpy = ">=1.26.4,<2.0.2 || >2.0.2" +numpy = ">=1.26.4,!=2.0.2" pinecone = {version = ">=6.0.0,<8.0.0", extras = ["asyncio"]} pydantic = ">=2.11.1" simsimd = ">=5.9.11" @@ -3054,6 +3100,18 @@ notebook = ["ipywidgets (>=6)"] slack = ["slack-sdk"] telegram = ["requests"] +[[package]] +name = "truststore" +version = "0.10.4" +description = "Verify certificates using native system trust stores" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "truststore-0.10.4-py3-none-any.whl", hash = "sha256:adaeaecf1cbb5f4de3b1959b42d41f6fab57b2b1666adb59e89cb0b53361d981"}, + {file = "truststore-0.10.4.tar.gz", hash = "sha256:9d91bd436463ad5e4ee4aba766628dd6cd7010cf3e2461756b3303710eebc301"}, +] + [[package]] name = "typing-extensions" version = "4.15.0" @@ -3760,4 +3818,4 @@ cffi = ["cffi (>=1.17,<2.0) ; platform_python_implementation != \"PyPy\" and pyt [metadata] lock-version = "2.1" python-versions = "3.11.*" -content-hash = "8886c2739952046692045906293b67f982abb2f848864097d8f667304f50bf8f" +content-hash = "99f87509aae864da71c2df9da7c1762989ad49f9e630685872ddeefa94421bcc" diff --git a/pyproject.toml b/pyproject.toml index b80f6797..339d39d1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ requires-poetry = ">=2.3.2" python = "3.11.*" openai = "^2.48" python-dotenv = "^1.2.3" -anthropic = "^0.119.0" +anthropic = "^1.9.0" langchain-pinecone = "^0.2.13" langchain-core = "^1.6" From 01ddcf1682535cdc9060d884edd9240dc57ea82c Mon Sep 17 00:00:00 2001 From: hanna-paasivirta Date: Tue, 6 Oct 2026 20:05:46 +0100 Subject: [PATCH 08/22] Sync bun.lock with elysia bump --- bun.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bun.lock b/bun.lock index bfec56c0..e695f9ea 100644 --- a/bun.lock +++ b/bun.lock @@ -9,7 +9,7 @@ "@elysiajs/html": "^1.4.0", "@openfn/adaptor-apis": "^0.3.0", "@sentry/bun": "^10.60.0", - "elysia": "1.4.27", + "elysia": "1.4.29", "jsdoc-babel": "^0.5.0", }, "devDependencies": { @@ -425,7 +425,7 @@ "electron-to-chromium": ["electron-to-chromium@1.5.377", "", {}, "sha512-cH1jZgJHoezfTnKfKwnScpHywTFVnJUNITDPREFdhNjiuD502+QFpG0Qk7G8jhsV/f+CEAFlIrzP1fT+IMb92g=="], - "elysia": ["elysia@1.4.27", "", { "dependencies": { "cookie": "^1.1.1", "exact-mirror": "^0.2.7", "fast-decode-uri-component": "^1.0.1", "memoirist": "^0.4.0" }, "peerDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "@types/bun": ">= 1.2.0", "file-type": ">= 20.0.0", "openapi-types": ">= 12.0.0", "typescript": ">= 5.0.0" }, "optionalPeers": ["@types/bun", "typescript"] }, "sha512-2UlmNEjPJVA/WZVPYKy+KdsrfFwwNlqSBW1lHz6i2AHc75k7gV4Rhm01kFeotH7PDiHIX2G8X3KnRPc33SGVIg=="], + "elysia": ["elysia@1.4.29", "", { "dependencies": { "cookie": "^1.1.1", "exact-mirror": "^0.2.7", "fast-decode-uri-component": "^1.0.1", "memoirist": "^0.4.0" }, "peerDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "@types/bun": ">= 1.2.0", "file-type": ">= 20.0.0", "openapi-types": ">= 12.0.0", "typescript": ">= 5.0.0" }, "optionalPeers": ["@types/bun", "typescript"] }, "sha512-GwMRGGwSdjfPt+w3LA0fqTuYJtS8uVRJicvoar98/HrO5qdFKDc9CwjIb6Kja+v39lkY+58hr2JvdR9jQzlUuA=="], "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], From 907558abdd583fac8d561cd6b3c87d0b9df74d55 Mon Sep 17 00:00:00 2001 From: doc-han Date: Wed, 7 Oct 2026 08:33:59 +0000 Subject: [PATCH 09/22] feat: revert changes to entry file --- services/entry.py | 69 +++++++++++-------------- services/fork_server.py | 109 ---------------------------------------- 2 files changed, 30 insertions(+), 148 deletions(-) delete mode 100644 services/fork_server.py diff --git a/services/entry.py b/services/entry.py index daf8f597..238f476e 100644 --- a/services/entry.py +++ b/services/entry.py @@ -9,15 +9,17 @@ load_dotenv() +# Langfuse: init after load_dotenv so env vars are available, before any Anthropic client is created from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor from opentelemetry.instrumentation.threading import ThreadingInstrumentor +AnthropicInstrumentor().instrument() +ThreadingInstrumentor().instrument() + from langfuse import Langfuse from langfuse.span_filter import is_default_export_span from langfuse_util import mask_secrets -langfuse = None # set by bootstrap() - def _should_export_span(span): """Drop spans marked as tracing-disabled (user has not opted in).""" @@ -27,6 +29,20 @@ def _should_export_span(span): return is_default_export_span(span) +langfuse = Langfuse( + should_export_span=_should_export_span, + mask=mask_secrets, + release=os.getenv("APOLLO_VERSION", "unknown"), +) + +env = os.getenv('ENVIRONMENT', 'unknown') +trace_rates = { + 'development': 1, + 'staging': 0.05, + 'production': 0.03, + 'unknown': 0.0, + } + def _scrub_event(event: dict, _hint: dict) -> dict: """Mask keys in what Sentry is about to send. @@ -38,41 +54,17 @@ def _scrub_event(event: dict, _hint: dict) -> dict: return mask_secrets(event) -def bootstrap() -> None: - global langfuse - - AnthropicInstrumentor().instrument() - ThreadingInstrumentor().instrument() - - langfuse = Langfuse( - should_export_span=_should_export_span, - mask=mask_secrets, - release=os.getenv("APOLLO_VERSION", "unknown"), - ) - - env = os.getenv("ENVIRONMENT", "unknown") - trace_rates = { - "development": 1, - "staging": 0.05, - "production": 0.03, - "unknown": 0.0, - } - - sentry_sdk.init( - dsn=os.getenv("SENTRY_DSN"), - environment=env, - sample_rate=1.0, - traces_sample_rate=trace_rates.get(env, 0.0), - enable_tracing=True, - auto_enabling_integrations=False, - before_send=_scrub_event, - # before_send covers error events only, and tracing is on. - before_send_transaction=_scrub_event, - ) - - -if os.environ.get("APOLLO_FORK_PRELOAD") != "1": - bootstrap() +sentry_sdk.init( + dsn=os.getenv('SENTRY_DSN'), + environment=env, + sample_rate=1.0, + traces_sample_rate=trace_rates.get(env, 0.0), + enable_tracing=True, + auto_enabling_integrations=False, + before_send=_scrub_event, + # before_send covers error events only, and tracing is on. + before_send_transaction=_scrub_event, +) # At or above this the failure is ours; below it the caller sent something we # correctly refused. @@ -164,8 +156,7 @@ def call( code=500, message=str(e), type="INTERNAL_ERROR", ).to_dict() - if langfuse is not None: - langfuse.flush() + langfuse.flush() return _finish(result, output_path) diff --git a/services/fork_server.py b/services/fork_server.py deleted file mode 100644 index 9aecdce7..00000000 --- a/services/fork_server.py +++ /dev/null @@ -1,109 +0,0 @@ -import os -import sys - -# macOS aborts a forked child that touches an objc framework unless this is set -# before interpreter start, so re-exec once with it in the env. No-op on Linux. -# [To be removed] -if sys.platform == "darwin" and os.environ.get("OBJC_DISABLE_INITIALIZE_FORK_SAFETY") != "YES": - os.environ["OBJC_DISABLE_INITIALIZE_FORK_SAFETY"] = "YES" - os.execvpe(sys.executable, [sys.executable, *sys.argv], os.environ) - -# Tell entry.py to import its heavy modules but defer bootstrap() to each child. -os.environ["APOLLO_FORK_PRELOAD"] = "1" - -import argparse # noqa: E402 -import importlib # noqa: E402 -import json # noqa: E402 -import signal # noqa: E402 -import socket # noqa: E402 -import traceback # noqa: E402 - -import entry # noqa: E402 - - -def _preload_services() -> list[str]: - """Import an opt-in allowlist (APOLLO_FORK_PRELOAD_SERVICES) so children - inherit their deps. Not every service: some do I/O at import and would hang - the parent; entry.call() imports the rest on demand in the child.""" - names = [n.strip() for n in os.environ.get("APOLLO_FORK_PRELOAD_SERVICES", "").split(",") if n.strip()] - loaded = [] - for name in names: - try: - importlib.import_module(f"{name}.{name}") - loaded.append(name) - except Exception as e: - print(f"fork_server: could not preload {name}: {e}", file=sys.stderr, flush=True) - return loaded - - -def _run_child(conn: socket.socket, req: dict) -> None: - os.dup2(conn.fileno(), 1) - os.dup2(conn.fileno(), 2) - sys.stdout = os.fdopen(1, "w", buffering=1) - sys.stderr = os.fdopen(2, "w", buffering=1) - - sys.stdout.write(f"PID:{os.getpid()}\n") # first, so the bridge can cancel this child - sys.stdout.flush() - - code = 0 - try: - entry.bootstrap() - entry.call( - service=req["service"], - input_path=req.get("input"), - output_path=req.get("output"), - apollo_port=req.get("port"), - ) - except Exception: - traceback.print_exc() - code = 1 - finally: - sys.stdout.write(f"EXIT:{code}\n") - sys.stdout.flush() - os._exit(code) - - -def main() -> None: - ap = argparse.ArgumentParser() - ap.add_argument("--socket", required=True) - args = ap.parse_args() - - signal.signal(signal.SIGCHLD, signal.SIG_IGN) # auto-reap children - - loaded = _preload_services() - - if os.path.exists(args.socket): - os.unlink(args.socket) - srv = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - srv.bind(args.socket) - srv.listen(128) - print(f"READY services={len(loaded)}", flush=True) # handshake the bridge waits for - - while True: - try: - conn, _ = srv.accept() - except InterruptedError: - continue - line = b"" - while not line.endswith(b"\n"): - chunk = conn.recv(65536) - if not chunk: - break - line += chunk - if not line: - conn.close() - continue - try: - req = json.loads(line) - except json.JSONDecodeError: - conn.close() - continue - - if os.fork() == 0: - srv.close() # the child must not hold the listening socket - _run_child(conn, req) # never returns - conn.close() # parent drops its copy; the child owns the reply - - -if __name__ == "__main__": - main() From f40a4988508af8dbfd71564120b71fbad58ab97d Mon Sep 17 00:00:00 2001 From: doc-han Date: Wed, 7 Oct 2026 09:06:44 +0000 Subject: [PATCH 10/22] feat: finalize fork bridge & macos deps --- .env.example | 6 ++ platform/src/bridge.fork.ts | 186 ++++++++++++++++++++++++++++++++++ platform/src/bridge.ts | 197 +----------------------------------- services/entry.fork.py | 129 +++++++++++++++++++++++ 4 files changed, 323 insertions(+), 195 deletions(-) create mode 100644 platform/src/bridge.fork.ts create mode 100644 services/entry.fork.py diff --git a/.env.example b/.env.example index 8f27f4bb..a3f087b1 100644 --- a/.env.example +++ b/.env.example @@ -70,3 +70,9 @@ LANGFUSE_BASE_URL=https://cloud.langfuse.com # ZILLIZ_URI = https://in01-XXXXXXXXXXXXX.aws-us-west-2.vectordb.zillizcloud.com:XXXXX # ZILLIZ_TOKEN =db_admin:password (or ApiKey) +# Warm fork-server (see services/entry.fork.py). Flip to "true" to use it. +# APOLLO_FORK_SERVER=true +# macOS only: required when APOLLO_FORK_SERVER=true, or a forked child that touches +# an Objective-C framework aborts. No-op on Linux, safe to leave set everywhere. +# OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES + diff --git a/platform/src/bridge.fork.ts b/platform/src/bridge.fork.ts new file mode 100644 index 00000000..c3c0e7ea --- /dev/null +++ b/platform/src/bridge.fork.ts @@ -0,0 +1,186 @@ +import readline from "node:readline"; +import net from "node:net"; +import path from "node:path"; +import { spawn, type ChildProcess } from "node:child_process"; +import { rm } from "node:fs/promises"; +import { getInternalToken } from "./auth/internal-token"; +import { + emptyResult, + malformedResult, + subprocessCancelled, + subprocessFailed, + subprocessKilled, + subprocessSpawnFailed, +} from "./util/errors"; +import pkg from "../../package.json"; + +// Only these lines are forwarded to the caller (mirrors bridge.ts). +const LOG_LINE = /^(INFO|DEBUG|ERROR|WARNING):/; + +export const USE_FORK_SERVER = + (process.env.APOLLO_FORK_SERVER ?? "").toLowerCase() === "true"; + +const onLines = (stream: NodeJS.ReadableStream, fn: (line: string) => void) => + readline.createInterface({ input: stream, crlfDelay: Infinity }).on("line", fn); + +// --- the warm master: spawned once, forks a child per request ---------------- + +type Master = { proc: ChildProcess; socketPath: string }; +let master: Promise | null = null; +let masterProc: ChildProcess | null = null; + +// Singleton; a failed start clears the slot so the next request retries. +function forkMaster(): Promise { + return (master ??= startMaster().catch((err) => { + master = null; + throw err; + })); +} + +function startMaster(): Promise { + const socketPath = path.resolve(`tmp/fork_server-${process.pid}.sock`); + const proc = spawn( + "poetry", + ["run", "python", "services/entry.fork.py", "--socket", socketPath], + { + env: { + ...process.env, + APOLLO_INTERNAL_TOKEN: getInternalToken(), + APOLLO_VERSION: pkg.version, + }, + } + ); + masterProc = proc; + onLines(proc.stderr!, (line) => console.error(`fork-server: ${line}`)); + + return new Promise((resolve, reject) => { + const fail = (err: Error) => (clearTimeout(timer), reject(subprocessSpawnFailed("fork_server", err))); + const timer = setTimeout(() => fail(new Error("not READY in time")), 60_000); + + onLines(proc.stdout!, (line) => { + console.log(`fork-server: ${line}`); + if (line.startsWith("READY")) { + clearTimeout(timer); + resolve({ proc, socketPath }); + } + }); + proc.on("error", fail); + proc.on("exit", (code, sig) => { + clearTimeout(timer); + console.error(`fork-server exited (code=${code} signal=${sig})`); + master = masterProc = null; // next request starts a fresh one + rm(socketPath).catch(() => {}); + }); + }); +} + +// Don't leave an orphaned master when the server process goes. +process.once("exit", () => masterProc?.kill("SIGTERM")); + +// --- per-request: ask the master to fork a child, stream it back ------------- + +export async function runForked( + scriptName: string, + port: number, + inputPath: string, + outputPath: string, + onLog?: (str: string) => void, + onEvent?: (type: string, payload: any) => void, + signal?: AbortSignal +): Promise { + const cleanup = () => + Promise.all([rm(inputPath).catch(() => {}), rm(outputPath).catch(() => {})]); + + let active: Master; + try { + active = await forkMaster(); + } catch (err) { + await cleanup(); + throw err; + } + + return new Promise((resolve, reject) => { + const conn = net.createConnection({ path: active.socketPath }); + let childPid: number | null = null; + let exitCode: number | null = null; + let cancelled = false; + let hardKill: ReturnType | undefined; + + const killChild = () => { + if (childPid == null) return; // killed once the PID: line arrives + try { + process.kill(childPid, "SIGTERM"); + } catch {} + hardKill = setTimeout(() => { + try { + process.kill(childPid!, "SIGKILL"); + } catch {} + }, 5_000); + hardKill.unref?.(); + }; + + const onAbort = () => { + cancelled = true; + console.warn(`cancelling ${scriptName}: client went away`); + killChild(); + conn.destroy(); + }; + if (signal) { + if (signal.aborted) onAbort(); + else signal.addEventListener("abort", onAbort, { once: true }); + } + + conn.on("connect", () => + conn.write(JSON.stringify({ service: scriptName, input: inputPath, output: outputPath, port }) + "\n") + ); + + // The child's stream: PID:/EXIT: control lines around the service's own stdout. + onLines(conn, (line) => { + if (line.startsWith("PID:")) { + childPid = Number(line.slice(4)) || null; + if (cancelled) killChild(); + } else if (line.startsWith("EXIT:")) { + exitCode = Number(line.slice(5)); + } else if (LOG_LINE.test(line)) { + console.log(line); + onLog?.(line); + } else if (line.startsWith("EVENT:")) { + const [, type, ...rest] = line.split(":"); + let payload: any = rest.join(":"); + try { + payload = JSON.parse(payload); + } catch { + // not json, forward the raw string + } + onEvent?.(type, payload); + } + }); + + const settle = async (finish: () => void) => { + if (hardKill) clearTimeout(hardKill); + signal?.removeEventListener("abort", onAbort); + await cleanup(); + finish(); + }; + + conn.on("error", (err) => + settle(() => reject(subprocessSpawnFailed(scriptName, err))) + ); + + conn.on("close", async () => { + const text = await Bun.file(outputPath).text().catch(() => ""); + await settle(() => { + if (cancelled) return reject(subprocessCancelled(scriptName, "SIGTERM")); + // No EXIT line => the child died mid-flight (crash/OOM/signal). + if (exitCode === null) return reject(subprocessKilled(scriptName, "UNKNOWN")); + if (exitCode !== 0) return reject(subprocessFailed(scriptName, exitCode)); + if (!text) return reject(emptyResult(scriptName)); + try { + resolve(JSON.parse(text)); + } catch { + reject(malformedResult(scriptName)); + } + }); + }); + }); +} diff --git a/platform/src/bridge.ts b/platform/src/bridge.ts index edceebec..011dbeff 100644 --- a/platform/src/bridge.ts +++ b/platform/src/bridge.ts @@ -1,7 +1,6 @@ import readline from "node:readline"; -import net from "node:net"; import path from "node:path"; -import { spawn, type ChildProcess } from "node:child_process"; +import { spawn } from "node:child_process"; import { chmod, rm } from "node:fs/promises"; import { getInternalToken } from "./auth/internal-token"; import { @@ -13,204 +12,12 @@ import { subprocessSpawnFailed, } from "./util/errors"; import pkg from "../../package.json"; +import { USE_FORK_SERVER, runForked } from "./bridge.fork"; // A line a service logged on purpose, as opposed to whatever else lands on a // stream. Only these are forwarded to the caller. const LOG_LINE = /^(INFO|DEBUG|ERROR|WARNING):/; -const USE_FORK_SERVER = ["1", "true", "yes"].includes( - (process.env.APOLLO_FORK_SERVER ?? "").toLowerCase() -); - -interface ForkMaster { - proc: ChildProcess; - socketPath: string; -} -let forkMaster: Promise | null = null; -let forkMasterProc: ChildProcess | null = null; - -function startForkMaster(): Promise { - const socketPath = path.resolve(`tmp/fork_server-${process.pid}.sock`); - const proc = spawn( - "poetry", - ["run", "python", "services/fork_server.py", "--socket", socketPath], - { - env: { - ...process.env, - APOLLO_INTERNAL_TOKEN: getInternalToken(), - APOLLO_VERSION: pkg.version, - OBJC_DISABLE_INITIALIZE_FORK_SAFETY: "YES", - }, - } - ); - forkMasterProc = proc; - - return new Promise((resolve, reject) => { - const timeout = setTimeout( - () => reject(subprocessSpawnFailed("fork_server", new Error("not READY in time"))), - 60_000 - ); - readline.createInterface({ input: proc.stdout!, crlfDelay: Infinity }).on("line", (line) => { - console.log(`fork-server: ${line}`); - if (line.startsWith("READY")) { - clearTimeout(timeout); - resolve({ proc, socketPath }); - } - }); - readline - .createInterface({ input: proc.stderr!, crlfDelay: Infinity }) - .on("line", (line) => console.error(`fork-server: ${line}`)); - - proc.on("error", (err) => { - clearTimeout(timeout); - reject(subprocessSpawnFailed("fork_server", err)); - }); - proc.on("exit", (code, sig) => { - clearTimeout(timeout); - console.error(`fork-server exited (code=${code} signal=${sig})`); - forkMaster = null; // next request starts a fresh master - forkMasterProc = null; - rm(socketPath).catch(() => {}); - }); - }); -} - -function getForkMaster(): Promise { - if (!forkMaster) { - forkMaster = startForkMaster().catch((err) => { - forkMaster = null; - throw err; - }); - } - return forkMaster; -} - -process.once("exit", () => forkMasterProc?.kill("SIGTERM")); - -function runForked( - scriptName: string, - port: number, - inputPath: string, - outputPath: string, - onLog?: (str: string) => void, - onEvent?: (type: string, payload: any) => void, - signal?: AbortSignal -): Promise { - return getForkMaster().then( - (master) => - new Promise((resolve, reject) => { - let childPid: number | null = null; - let exitCode: number | null = null; - let cancelled = false; - let hardKill: ReturnType | undefined; - - const cleanupFiles = async () => { - try { - await rm(inputPath); - await rm(outputPath); - } catch (e) { - console.error("Error removing temporary files"); - console.error(e); - } - }; - - const killChild = () => { - if (childPid == null) return; // killed once the PID: line arrives - try { - process.kill(childPid, "SIGTERM"); - } catch {} - hardKill = setTimeout(() => { - try { - process.kill(childPid!, "SIGKILL"); - } catch {} - }, 5_000); - hardKill.unref?.(); - }; - - const onAbort = () => { - cancelled = true; - console.warn(`cancelling ${scriptName}: client went away`); - killChild(); - conn.destroy(); - }; - - const conn = net.createConnection({ path: master.socketPath }); - conn.on("connect", () => { - conn.write( - JSON.stringify({ service: scriptName, input: inputPath, output: outputPath, port }) + "\n" - ); - }); - - // The child's stream: the service's own stdout, wrapped in PID:/EXIT:. - const rl = readline.createInterface({ input: conn, crlfDelay: Infinity }); - rl.on("line", (line) => { - if (line.startsWith("PID:")) { - childPid = Number(line.slice(4)) || null; - if (cancelled) killChild(); - } else if (line.startsWith("EXIT:")) { - exitCode = Number(line.slice(5)); - } else if (LOG_LINE.test(line)) { - console.log(line); - onLog?.(line); - } else if (/^(EVENT)\:/.test(line)) { - const [_prefix, type, ...payload] = line.split(":"); - let processedPayload: any = payload.join(":"); - try { - processedPayload = JSON.parse(processedPayload); - } catch (e) { - // No json, no problem - } - onEvent?.(type, processedPayload); - } - }); - - if (signal) { - if (signal.aborted) onAbort(); - else signal.addEventListener("abort", onAbort, { once: true }); - } - - conn.on("error", async (err) => { - if (hardKill) clearTimeout(hardKill); - signal?.removeEventListener("abort", onAbort); - await cleanupFiles(); - reject(subprocessSpawnFailed(scriptName, err)); - }); - - conn.on("close", async () => { - rl.close(); - if (hardKill) clearTimeout(hardKill); - signal?.removeEventListener("abort", onAbort); - - const text = await Bun.file(outputPath) - .text() - .catch(() => ""); - await cleanupFiles(); - - if (cancelled) return reject(subprocessCancelled(scriptName, "SIGTERM")); - if (exitCode && exitCode !== 0) return reject(subprocessFailed(scriptName, exitCode)); - // No EXIT line => the child died mid-flight (crash/OOM/signal). - if (exitCode === null) return reject(subprocessKilled(scriptName, "UNKNOWN")); - if (text) { - try { - return resolve(JSON.parse(text)); - } catch (e) { - console.error(`Unreadable output from ${scriptName}`); - console.error(e); - return reject(malformedResult(scriptName)); - } - } - console.warn("No data returned from pythonland"); - return reject(emptyResult(scriptName)); - }); - }), - async (err) => { - await rm(inputPath).catch(() => {}); - await rm(outputPath).catch(() => {}); - throw err; - } - ); -} - /** Run a python script Each script will be run in its own thread because diff --git a/services/entry.fork.py b/services/entry.fork.py new file mode 100644 index 00000000..1211c783 --- /dev/null +++ b/services/entry.fork.py @@ -0,0 +1,129 @@ +"""Fork entry for the Python side (used when APOLLO_FORK_SERVER=true; see +platform/src/bridge.fork.ts). Run as a script, never imported. + +Pays the heavy imports once, then forks a fresh child per request. Each child +inherits the imports via copy-on-write and imports entry.py AFTER forking, so +entry.py's own init runs in the child where it's fork-safe - entry.py is left +untouched. The parent only imports and never inits, so it stays forkable. + +macOS: set OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES in your env (see .env.example), +or a forked child that touches an Objective-C framework aborts. No-op on Linux. + +Protocol (NDJSON over a unix socket, one connection per request): + bridge -> master : {"service","input","output","port"} + child -> bridge : PID: then the service's stdout then EXIT: +""" + +import argparse +import importlib +import json +import os +import signal +import socket +import sys +import traceback + +# Warm entry.py's heavy deps so forked children inherit them (copy-on-write). +# Mirrors entry.py's imports; a missing one is just imported per-child - slower, +# never wrong. +PRELOAD = ( + "sentry_sdk", + "anthropic", + "langfuse", + "langfuse_util", + "util", + "opentelemetry.instrumentation.anthropic", + "opentelemetry.instrumentation.threading", +) + + +def preload() -> int: + """Warm the shared deps, plus any opt-in services. Services are opt-in + (APOLLO_FORK_PRELOAD_SERVICES) because some do I/O at import and would hang + the parent; the child imports the rest on demand.""" + for module in PRELOAD: + importlib.import_module(module) + + names = [s.strip() for s in os.environ.get("APOLLO_FORK_PRELOAD_SERVICES", "").split(",") if s.strip()] + loaded = 0 + for name in names: + try: + importlib.import_module(f"{name}.{name}") + loaded += 1 + except Exception as e: + print(f"entry.fork: could not preload {name}: {e}", file=sys.stderr, flush=True) + return loaded + + +def run_child(conn: socket.socket, req: dict) -> None: + """In the forked child: stream through the socket, run one job, exit.""" + # Route stdout/stderr to the socket so the service's logging reaches the bridge. + os.dup2(conn.fileno(), 1) + os.dup2(conn.fileno(), 2) + sys.stdout = os.fdopen(1, "w", buffering=1) + sys.stderr = os.fdopen(2, "w", buffering=1) + + print(f"PID:{os.getpid()}") # first, so the bridge can cancel this child + + code = 0 + try: + import entry # post-fork: entry.py's init runs here (fork-safe), deps warm + + entry.call( + service=req["service"], + input_path=req.get("input"), + output_path=req.get("output"), + apollo_port=req.get("port"), + ) + except Exception: + traceback.print_exc() + code = 1 + finally: + print(f"EXIT:{code}") + os._exit(code) + + +def read_request(conn: socket.socket) -> dict | None: + """Read one newline-terminated JSON request; None if there isn't a usable one.""" + line = b"" + while not line.endswith(b"\n"): + chunk = conn.recv(65536) + if not chunk: + break + line += chunk + try: + return json.loads(line) if line else None + except json.JSONDecodeError: + return None + + +def serve(sock_path: str) -> None: + signal.signal(signal.SIGCHLD, signal.SIG_IGN) # auto-reap children + count = preload() + + if os.path.exists(sock_path): + os.unlink(sock_path) + server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + server.bind(sock_path) + server.listen(128) + print(f"READY services={count}", flush=True) # handshake the bridge waits for + + while True: + try: + conn, _ = server.accept() + except InterruptedError: + continue + req = read_request(conn) + if req is None: + conn.close() + continue + if os.fork() == 0: + server.close() # the child must not hold the listening socket + run_child(conn, req) # never returns + conn.close() # parent drops its copy; the child owns the reply + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--socket", required=True) + serve(parser.parse_args().socket) From 03a108147bf2998e2dbb6e7cbc6c1d52d76ee9eb Mon Sep 17 00:00:00 2001 From: doc-han Date: Wed, 7 Oct 2026 11:35:47 +0000 Subject: [PATCH 11/22] chore: update changelog --- .env.example | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.env.example b/.env.example index a3f087b1..5e945f07 100644 --- a/.env.example +++ b/.env.example @@ -70,9 +70,9 @@ LANGFUSE_BASE_URL=https://cloud.langfuse.com # ZILLIZ_URI = https://in01-XXXXXXXXXXXXX.aws-us-west-2.vectordb.zillizcloud.com:XXXXX # ZILLIZ_TOKEN =db_admin:password (or ApiKey) -# Warm fork-server (see services/entry.fork.py). Flip to "true" to use it. +# Turn this on to use the fork server mechanism # APOLLO_FORK_SERVER=true -# macOS only: required when APOLLO_FORK_SERVER=true, or a forked child that touches -# an Objective-C framework aborts. No-op on Linux, safe to leave set everywhere. + +# macOS only: required when APOLLO_FORK_SERVER=true # OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES From 1a1f9755463aaf0bd6a7771b45957bf55c3575a9 Mon Sep 17 00:00:00 2001 From: hanna-paasivirta Date: Thu, 8 Oct 2026 21:19:52 +0100 Subject: [PATCH 12/22] Use httpx2 to match anthropic 1.x --- services/global_chat/planner.py | 12 ++-- .../global_chat/tests/unit/test_planner.py | 66 +++++++++---------- services/job_chat/job_chat.py | 4 +- 3 files changed, 41 insertions(+), 41 deletions(-) diff --git a/services/global_chat/planner.py b/services/global_chat/planner.py index 42ba790a..1735c5c7 100644 --- a/services/global_chat/planner.py +++ b/services/global_chat/planner.py @@ -6,7 +6,7 @@ from typing import List, Dict, Optional from concurrent.futures import ThreadPoolExecutor, as_completed from dataclasses import dataclass -import httpx +import httpx2 import anthropic from anthropic import Anthropic import sentry_sdk @@ -74,7 +74,7 @@ def _api_error_message(error: Exception) -> str: if isinstance(message, str) and message: return message - if isinstance(error, (anthropic.APIConnectionError, httpx.RequestError)): + if isinstance(error, (anthropic.APIConnectionError, httpx2.RequestError)): return str(error) or type(error).__name__ status = getattr(error, "status_code", None) @@ -158,7 +158,7 @@ def _model_api_failure(error: Exception) -> tuple[int, str, str, dict]: # leaves the server and nothing upstream is trusted to be key-free. details = {"upstream_message": mask_secrets(upstream)} - if isinstance(error, (anthropic.APIConnectionError, httpx.RequestError)): + if isinstance(error, (anthropic.APIConnectionError, httpx2.RequestError)): cause = getattr(error, "__cause__", None) if cause: # A proxy error carries the proxy URL, credentials and all. @@ -387,10 +387,10 @@ def run( except ApolloError: raise - except (anthropic.APIError, httpx.RequestError) as e: + except (anthropic.APIError, httpx2.RequestError) as e: # A rejection from the model API is not a tool failure. # - # httpx.RequestError as well as APIError: the SDK only + # httpx2.RequestError as well as APIError: the SDK only # wraps httpx exceptions around the initial send, and on a # streaming request that returns once the headers arrive. # The body is read later, unwrapped, so a stream that dies @@ -569,7 +569,7 @@ def _call_api(self, system_prompt, messages, stream, stream_manager, tool_choice # Per-request timeout (same values as the SDK default): # required for non-streaming calls with max_tokens > ~21k, # which the SDK otherwise rejects. - timeout=httpx.Timeout(600.0, connect=5.0), + timeout=httpx2.Timeout(600.0, connect=5.0), **_CONTEXT_MANAGEMENT, ) return response diff --git a/services/global_chat/tests/unit/test_planner.py b/services/global_chat/tests/unit/test_planner.py index 81fa0567..f66fb9ec 100644 --- a/services/global_chat/tests/unit/test_planner.py +++ b/services/global_chat/tests/unit/test_planner.py @@ -3,7 +3,7 @@ from unittest.mock import patch import anthropic -import httpx +import httpx2 import pytest from util import ApolloError @@ -412,8 +412,8 @@ def test_model_api_error_is_not_reported_as_a_tool_failure() -> None: # Shaped like a real rejection: the SDK's own str() is the dict repr, # and the readable sentence is in the parsed body. - request = httpx.Request("POST", "https://api.anthropic.com/v1/messages") - response = httpx.Response(400, request=request, json={}) + request = httpx2.Request("POST", "https://api.anthropic.com/v1/messages") + response = httpx2.Response(400, request=request, json={}) api_error = anthropic.BadRequestError( "Error code: 400 - {'type': 'error', 'error': {...}}", response=response, @@ -470,11 +470,11 @@ def _raise_from_planner(error: Exception) -> ApolloError: def test_a_rejected_key_does_not_describe_our_account_to_the_caller() -> None: """The upstream sentence for an auth failure is about our key, and every user of the instance would be shown it in chat.""" - request = httpx.Request("POST", "https://api.anthropic.com/v1/messages") + request = httpx2.Request("POST", "https://api.anthropic.com/v1/messages") error = _raise_from_planner( anthropic.AuthenticationError( "Error code: 401 - {'type': 'error', 'error': {...}}", - response=httpx.Response(401, request=request, json={}), + response=httpx2.Response(401, request=request, json={}), body={ "type": "error", "error": { @@ -497,11 +497,11 @@ def test_our_own_request_shape_being_wrong_is_not_blamed_on_the_caller() -> None """The planner sends beta headers, thinking and context-management config and tool definitions the caller never touches. Anthropic rejects those with a 400, and answering the caller 400 would blame them for it.""" - request = httpx.Request("POST", "https://api.anthropic.com/v1/messages") + request = httpx2.Request("POST", "https://api.anthropic.com/v1/messages") error = _raise_from_planner( anthropic.BadRequestError( "Error code: 400", - response=httpx.Response(400, request=request, json={}), + response=httpx2.Response(400, request=request, json={}), body={ "type": "error", "error": { @@ -527,11 +527,11 @@ def test_our_own_request_shape_being_wrong_is_not_blamed_on_the_caller() -> None def test_a_payload_over_the_size_limit_is_the_callers_to_act_on() -> None: """413 is the sibling of prompt-too-long: their workflow is too big, and a retry of the same payload can never succeed.""" - request = httpx.Request("POST", "https://api.anthropic.com/v1/messages") + request = httpx2.Request("POST", "https://api.anthropic.com/v1/messages") error = _raise_from_planner( anthropic.RequestTooLargeError( "Error code: 413", - response=httpx.Response(413, request=request, json={}), + response=httpx2.Response(413, request=request, json={}), body={"type": "error", "error": {"type": "request_too_large", "message": "request body too large"}}, ), @@ -548,11 +548,11 @@ def test_a_payload_over_the_size_limit_is_the_callers_to_act_on() -> None: def test_a_stream_that_dies_mid_reply_does_not_record_the_opening_200() -> None: """The SDK builds a mid-stream error from the response that opened the stream, which succeeded, so its status would read as a call that worked.""" - request = httpx.Request("POST", "https://api.anthropic.com/v1/messages") + request = httpx2.Request("POST", "https://api.anthropic.com/v1/messages") error = _raise_from_planner( anthropic.APIStatusError( "Overloaded", - response=httpx.Response(200, request=request, json={}), + response=httpx2.Response(200, request=request, json={}), body={"type": "error", "error": {"type": "overloaded_error", "message": "Overloaded"}}, ), @@ -567,13 +567,13 @@ def test_a_mid_stream_failure_is_classified_by_what_the_body_says() -> None: opened the stream, whatever actually went wrong, so the class says nothing and the body's type is the only thing left. Global chat streams, so this is the common path, not the corner.""" - request = httpx.Request("POST", "https://api.anthropic.com/v1/messages") + request = httpx2.Request("POST", "https://api.anthropic.com/v1/messages") def mid_stream(kind: str, message: str) -> ApolloError: return _raise_from_planner( anthropic.APIStatusError( f"{{'type': 'error', 'error': {{'type': '{kind}'}}}}", - response=httpx.Response(200, request=request, json={}), + response=httpx2.Response(200, request=request, json={}), body={"type": "error", "error": {"type": kind, "message": message}}, ), @@ -609,11 +609,11 @@ def test_an_overload_with_no_readable_body_still_says_to_try_again() -> None: """A 529 is the response most likely to come back from an edge with an HTML body, and then there is no type to read. It is also the one kind whose advice differs, so falling back to the class matters here.""" - request = httpx.Request("POST", "https://api.anthropic.com/v1/messages") + request = httpx2.Request("POST", "https://api.anthropic.com/v1/messages") error = _raise_from_planner( anthropic.OverloadedError( "Error code: 529", - response=httpx.Response(529, request=request, text="busy"), + response=httpx2.Response(529, request=request, text="busy"), body="busy", ), ) @@ -625,11 +625,11 @@ def test_an_overload_with_no_readable_body_still_says_to_try_again() -> None: def test_details_do_not_carry_key_shaped_values_off_the_server() -> None: """details is serialised to the caller (errors.ts toErrorPayload), so the upstream sentence leaves the server even though only message is rendered.""" - request = httpx.Request("POST", "https://api.anthropic.com/v1/messages") + request = httpx2.Request("POST", "https://api.anthropic.com/v1/messages") error = _raise_from_planner( anthropic.BadRequestError( "Error code: 400", - response=httpx.Response(400, request=request, json={}), + response=httpx2.Response(400, request=request, json={}), body={ "type": "error", "error": { @@ -646,8 +646,8 @@ def test_details_do_not_carry_key_shaped_values_off_the_server() -> None: def test_the_cause_of_a_connection_failure_is_masked_too() -> None: """A proxy error carries the proxy URL, which is where credentials get written, and details is serialised to the caller.""" - request = httpx.Request("POST", "https://api.anthropic.com/v1/messages") - dropped = httpx.ProxyError("proxy rejected") + request = httpx2.Request("POST", "https://api.anthropic.com/v1/messages") + dropped = httpx2.ProxyError("proxy rejected") dropped.__cause__ = Exception("http://user:sk-ant-api03-" + "b" * 95 + "@proxy:8080") error = _raise_from_planner(dropped) @@ -658,9 +658,9 @@ def test_the_cause_of_a_connection_failure_is_masked_too() -> None: def test_a_dropped_connection_keeps_the_text_httpx_wrote() -> None: """The SDK only wraps httpx around the initial send, so a stream that dies while the body is being read raises a raw httpx error with no status.""" - request = httpx.Request("POST", "https://api.anthropic.com/v1/messages") + request = httpx2.Request("POST", "https://api.anthropic.com/v1/messages") error = _raise_from_planner( - httpx.ReadError("peer closed connection", request=request), + httpx2.ReadError("peer closed connection", request=request), ) assert error.code == 503 @@ -722,11 +722,11 @@ class FakeError(Exception): def test_a_rate_limit_keeps_the_retry_after_the_bridge_contract_pins() -> None: """platform/test/server.test.ts asserts RATE_LIMIT carries retry_after, and dropping it would leave a caller with nothing to wait on.""" - request = httpx.Request("POST", "https://api.anthropic.com/v1/messages") + request = httpx2.Request("POST", "https://api.anthropic.com/v1/messages") error = _raise_from_planner( anthropic.RateLimitError( "Error code: 429", - response=httpx.Response( + response=httpx2.Response( 429, request=request, json={}, headers={"retry-after": "30"}, ), body={"type": "error", "error": {"type": "rate_limit_error", @@ -740,11 +740,11 @@ def test_a_rate_limit_keeps_the_retry_after_the_bridge_contract_pins() -> None: def test_a_rate_limit_without_the_header_still_gives_something_to_wait_on() -> None: - request = httpx.Request("POST", "https://api.anthropic.com/v1/messages") + request = httpx2.Request("POST", "https://api.anthropic.com/v1/messages") error = _raise_from_planner( anthropic.RateLimitError( "Error code: 429", - response=httpx.Response(429, request=request, json={}), + response=httpx2.Response(429, request=request, json={}), body={}, ), ) @@ -757,13 +757,13 @@ def test_a_broken_retry_after_header_does_not_raise_inside_the_handler() -> None header would raise from inside the except block and arrive as the generic 500 this whole change exists to remove. And the value is someone else's, so a caller told to wait a century would wait forever.""" - request = httpx.Request("POST", "https://api.anthropic.com/v1/messages") + request = httpx2.Request("POST", "https://api.anthropic.com/v1/messages") def rate_limited(header: bytes) -> ApolloError: return _raise_from_planner( anthropic.RateLimitError( "Error code: 429", - response=httpx.Response( + response=httpx2.Response( 429, request=request, json={}, headers=[(b"retry-after", header)], ), @@ -788,17 +788,17 @@ def test_our_account_failing_is_not_reported_as_the_caller_failing() -> None: """A 403 from the model API means our org cannot use it. Passing it through would answer the caller with a verdict we reached about ourselves, which is what the 401 rule exists to prevent.""" - request = httpx.Request("POST", "https://api.anthropic.com/v1/messages") + request = httpx2.Request("POST", "https://api.anthropic.com/v1/messages") for sdk_error in ( anthropic.PermissionDeniedError( "Error code: 403", - response=httpx.Response(403, request=request, json={}), + response=httpx2.Response(403, request=request, json={}), body={"type": "error", "error": {"type": "permission_error", "message": "not allowed"}}, ), anthropic.NotFoundError( "Error code: 404", - response=httpx.Response(404, request=request, json={}), + response=httpx2.Response(404, request=request, json={}), body={"type": "error", "error": {"type": "not_found_error", "message": "model: nope"}}, ), @@ -815,7 +815,7 @@ def test_connection_failure_is_not_reported_as_a_tool_failure() -> None: planner.model = "test-model" planner.max_tool_calls = 5 - request = httpx.Request("POST", "https://api.anthropic.com/v1/messages") + request = httpx2.Request("POST", "https://api.anthropic.com/v1/messages") api_error = anthropic.APIConnectionError(request=request) with ( @@ -843,7 +843,7 @@ def test_stream_dropping_midway_is_not_reported_as_a_tool_failure() -> None: planner.model = "test-model" planner.max_tool_calls = 5 - dropped = httpx.RemoteProtocolError( + dropped = httpx2.RemoteProtocolError( "peer closed connection without sending complete message body" ) @@ -864,7 +864,7 @@ def test_connection_error_keeps_the_sdk_wording() -> None: """APIConnectionError's message is the SDK's own constant, not upstream text, so it is worth more to a reader than the class name.""" error = anthropic.APIConnectionError( - request=httpx.Request("POST", "https://api.anthropic.com/v1/messages") + request=httpx2.Request("POST", "https://api.anthropic.com/v1/messages") ) assert _api_error_message(error) == "Connection error." diff --git a/services/job_chat/job_chat.py b/services/job_chat/job_chat.py index 919040ed..9cc70017 100644 --- a/services/job_chat/job_chat.py +++ b/services/job_chat/job_chat.py @@ -4,7 +4,7 @@ import yaml from typing import List, Optional, Dict, Any from dataclasses import dataclass -import httpx +import httpx2 from anthropic import ( Anthropic, APIConnectionError, @@ -370,7 +370,7 @@ def generate( # Per-request timeout (same values as the SDK default): # required for non-streaming calls with max_tokens > ~21k, # which the SDK otherwise rejects. - timeout=httpx.Timeout(600.0, connect=5.0), + timeout=httpx2.Timeout(600.0, connect=5.0), **tool_kwargs ) message = self.client.messages.create(**create_kwargs) From 2ba057a5afa3c5cfb747a8b1ac049068f0a559c5 Mon Sep 17 00:00:00 2001 From: hanna-paasivirta Date: Thu, 8 Oct 2026 21:19:52 +0100 Subject: [PATCH 13/22] Drop temperature, removed in anthropic 1.x --- services/global_chat/config.yaml | 1 - services/global_chat/router.py | 2 -- services/job_chat/rag.yaml | 1 - services/job_chat/retrieve_docs.py | 5 +---- services/job_chat/tests/unit/test_retrieve_docs.py | 2 -- services/vocab_mapper/vocab_mapper.py | 1 - 6 files changed, 1 insertion(+), 11 deletions(-) diff --git a/services/global_chat/config.yaml b/services/global_chat/config.yaml index 112b13e9..49be678e 100644 --- a/services/global_chat/config.yaml +++ b/services/global_chat/config.yaml @@ -4,7 +4,6 @@ router: model: "claude-haiku" max_tokens: 500 - temperature: 0.0 # Planner configuration (complex orchestration) planner: diff --git a/services/global_chat/router.py b/services/global_chat/router.py index c2431862..2fd58247 100644 --- a/services/global_chat/router.py +++ b/services/global_chat/router.py @@ -70,7 +70,6 @@ def __init__(self, config_loader: ConfigLoader, api_key: Optional[str] = None): router_config = config_loader.config.get("router", {}) self.model = resolve_model(router_config.get("model", "claude-haiku")) self.max_tokens = router_config.get("max_tokens", 500) - self.temperature = router_config.get("temperature", 0.0) logger.info(f"RouterAgent initialized with model: {self.model}") @@ -174,7 +173,6 @@ def _make_routing_decision( response = self.client.messages.create( model=self.model, max_tokens=self.max_tokens, - temperature=self.temperature, system=[{"type": "text", "text": system_prompt}], messages=[ {"role": "user", "content": routing_message} diff --git a/services/job_chat/rag.yaml b/services/job_chat/rag.yaml index 13caa0de..d6bdd320 100644 --- a/services/job_chat/rag.yaml +++ b/services/job_chat/rag.yaml @@ -4,5 +4,4 @@ llm_search_decision: "claude-sonnet" llm_retrieval: "claude-sonnet" threshold: 0.8 top_k: 5 -temperature: 0 prompts_version: 1.0 diff --git a/services/job_chat/retrieve_docs.py b/services/job_chat/retrieve_docs.py index 33d35a89..9e80cf95 100644 --- a/services/job_chat/retrieve_docs.py +++ b/services/job_chat/retrieve_docs.py @@ -113,7 +113,6 @@ def needs_docs(content, client, user_context=""): response_text, usage = call_llm( model=resolve_model(config["llm_search_decision"]), - temperature=config["temperature"], system_prompt=config_loader.prompts["prompts"]["needs_docs_system_prompt"], user_prompt=formatted_user_prompt, client=client @@ -148,7 +147,6 @@ def generate_queries(content, client, user_context=""): text, usage = call_llm( model=resolve_model(config["llm_retrieval"]), - temperature=config["temperature"], system_prompt=config_loader.prompts["prompts"]["search_docs_system_prompt"], user_prompt=formatted_user_prompt, client=client, @@ -208,7 +206,7 @@ def format_context(adaptor, code, history): return formatted_text -def call_llm(model, temperature, system_prompt, user_prompt, client, output_schema=None): +def call_llm(model, system_prompt, user_prompt, client, output_schema=None): """Helper method to make LLM calls with error handling.""" try: messages = [ @@ -226,7 +224,6 @@ def call_llm(model, temperature, system_prompt, user_prompt, client, output_sche kwargs = dict( model=model, max_tokens=1024, - temperature=temperature, system=system_prompt, messages=messages ) diff --git a/services/job_chat/tests/unit/test_retrieve_docs.py b/services/job_chat/tests/unit/test_retrieve_docs.py index 45b57ddf..58b60b03 100644 --- a/services/job_chat/tests/unit/test_retrieve_docs.py +++ b/services/job_chat/tests/unit/test_retrieve_docs.py @@ -51,7 +51,6 @@ def test_call_llm_returns_text_and_usage_on_success(): text, usage = rd.call_llm( model="claude-haiku-4-5", - temperature=0, system_prompt="sys", user_prompt="usr", client=client, @@ -68,7 +67,6 @@ def test_call_llm_wraps_unexpected_error_as_apollo_error(): with pytest.raises(ApolloError) as exc: rd.call_llm( model="claude-haiku-4-5", - temperature=0, system_prompt="sys", user_prompt="usr", client=client, diff --git a/services/vocab_mapper/vocab_mapper.py b/services/vocab_mapper/vocab_mapper.py index 29189206..8310f1d9 100644 --- a/services/vocab_mapper/vocab_mapper.py +++ b/services/vocab_mapper/vocab_mapper.py @@ -39,7 +39,6 @@ def _call_llm(self, system_prompt: str, user_prompt: str) -> str: message = self.client.messages.create( model=CLAUDE_SONNET, max_tokens=500, - temperature=0, system=system_prompt, messages=[ { From fb82a745d4078486f1f296021da972e1cc35300e Mon Sep 17 00:00:00 2001 From: doc-han Date: Fri, 9 Oct 2026 08:47:47 +0000 Subject: [PATCH 14/22] fix: resolve issues --- platform/src/bridge.fork.ts | 2 +- services/entry.fork.py | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/platform/src/bridge.fork.ts b/platform/src/bridge.fork.ts index c3c0e7ea..70177b79 100644 --- a/platform/src/bridge.fork.ts +++ b/platform/src/bridge.fork.ts @@ -66,10 +66,10 @@ function startMaster(): Promise { }); proc.on("error", fail); proc.on("exit", (code, sig) => { - clearTimeout(timer); console.error(`fork-server exited (code=${code} signal=${sig})`); master = masterProc = null; // next request starts a fresh one rm(socketPath).catch(() => {}); + fail(new Error(`fork-server exited before ready (code=${code} signal=${sig})`)); }); }); } diff --git a/services/entry.fork.py b/services/entry.fork.py index 1211c783..9c4fef70 100644 --- a/services/entry.fork.py +++ b/services/entry.fork.py @@ -23,6 +23,8 @@ import sys import traceback +import sentry_sdk # for the per-child service tag + flush (see run_child) + # Warm entry.py's heavy deps so forked children inherit them (copy-on-write). # Mirrors entry.py's imports; a missing one is just imported per-child - slower, # never wrong. @@ -57,11 +59,11 @@ def preload() -> int: def run_child(conn: socket.socket, req: dict) -> None: """In the forked child: stream through the socket, run one job, exit.""" - # Route stdout/stderr to the socket so the service's logging reaches the bridge. + # Route stdout to the socket so the service's logging reaches the bridge. + # Leave stderr on fd 2 (the master's stderr pipe) so Python tracebacks still + # reach the server logs, the way the spawn path forwards them. os.dup2(conn.fileno(), 1) - os.dup2(conn.fileno(), 2) sys.stdout = os.fdopen(1, "w", buffering=1) - sys.stderr = os.fdopen(2, "w", buffering=1) print(f"PID:{os.getpid()}") # first, so the bridge can cancel this child @@ -69,6 +71,7 @@ def run_child(conn: socket.socket, req: dict) -> None: try: import entry # post-fork: entry.py's init runs here (fork-safe), deps warm + sentry_sdk.set_tag("service", req["service"]) # entry.main() tags it; call() doesn't entry.call( service=req["service"], input_path=req.get("input"), @@ -79,6 +82,16 @@ def run_child(conn: socket.socket, req: dict) -> None: traceback.print_exc() code = 1 finally: + try: + sentry_sdk.flush(timeout=2) + except Exception: + pass + langfuse = getattr(sys.modules.get("entry"), "langfuse", None) + if langfuse is not None: + try: + langfuse.flush() + except Exception: + pass print(f"EXIT:{code}") os._exit(code) From e7dab29c37503066f666d8aeebabd0e40de1ba83 Mon Sep 17 00:00:00 2001 From: doc-han Date: Mon, 12 Oct 2026 09:24:40 +0000 Subject: [PATCH 15/22] feat: move imports to yaml --- services/entry.fork.py | 19 +++++++------------ services/fork_preload.yaml | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+), 12 deletions(-) create mode 100644 services/fork_preload.yaml diff --git a/services/entry.fork.py b/services/entry.fork.py index 9c4fef70..c83cbf71 100644 --- a/services/entry.fork.py +++ b/services/entry.fork.py @@ -22,28 +22,23 @@ import socket import sys import traceback +from pathlib import Path import sentry_sdk # for the per-child service tag + flush (see run_child) +import yaml # Warm entry.py's heavy deps so forked children inherit them (copy-on-write). -# Mirrors entry.py's imports; a missing one is just imported per-child - slower, -# never wrong. -PRELOAD = ( - "sentry_sdk", - "anthropic", - "langfuse", - "langfuse_util", - "util", - "opentelemetry.instrumentation.anthropic", - "opentelemetry.instrumentation.threading", -) +# See fork_preload.yaml for the list and why each module is there. +PRELOAD_PATH = Path(__file__).parent / "fork_preload.yaml" def preload() -> int: """Warm the shared deps, plus any opt-in services. Services are opt-in (APOLLO_FORK_PRELOAD_SERVICES) because some do I/O at import and would hang the parent; the child imports the rest on demand.""" - for module in PRELOAD: + with PRELOAD_PATH.open() as f: + modules = yaml.safe_load(f)["preload"] + for module in modules: importlib.import_module(module) names = [s.strip() for s in os.environ.get("APOLLO_FORK_PRELOAD_SERVICES", "").split(",") if s.strip()] diff --git a/services/fork_preload.yaml b/services/fork_preload.yaml new file mode 100644 index 00000000..7aac853a --- /dev/null +++ b/services/fork_preload.yaml @@ -0,0 +1,22 @@ +# Modules the fork master (entry.fork.py) imports once at startup, before +# accepting any requests. A forked child inherits these via copy-on-write, so +# the cost of importing them is paid once per server lifetime instead of once +# per request. A module missing from this list isn't an error - the child +# just imports it itself on demand, which is slower but never wrong. + +preload: + # Mirrors entry.py's own top-level imports (Sentry init, Langfuse, otel). + - sentry_sdk + - anthropic + - langfuse + - langfuse_util + - util + - opentelemetry.instrumentation.anthropic + - opentelemetry.instrumentation.threading + + # global_chat is ~95% of fork traffic; warm its RAG path (search_docsite) + # so the common case doesn't pay for these on the first request. + - pinecone + - openai + - langchain_openai + - langchain_pinecone From cb34f293606ad935ffed5d5a77fe6d7545d50f4e Mon Sep 17 00:00:00 2001 From: doc-han Date: Mon, 12 Oct 2026 09:26:25 +0000 Subject: [PATCH 16/22] chore: share log lines --- platform/src/bridge.fork.ts | 4 +--- platform/src/bridge.ts | 5 +---- platform/src/util/log-line.ts | 4 ++++ 3 files changed, 6 insertions(+), 7 deletions(-) create mode 100644 platform/src/util/log-line.ts diff --git a/platform/src/bridge.fork.ts b/platform/src/bridge.fork.ts index 70177b79..a6d34b14 100644 --- a/platform/src/bridge.fork.ts +++ b/platform/src/bridge.fork.ts @@ -12,11 +12,9 @@ import { subprocessKilled, subprocessSpawnFailed, } from "./util/errors"; +import { LOG_LINE } from "./util/log-line"; import pkg from "../../package.json"; -// Only these lines are forwarded to the caller (mirrors bridge.ts). -const LOG_LINE = /^(INFO|DEBUG|ERROR|WARNING):/; - export const USE_FORK_SERVER = (process.env.APOLLO_FORK_SERVER ?? "").toLowerCase() === "true"; diff --git a/platform/src/bridge.ts b/platform/src/bridge.ts index 011dbeff..bd79ad6e 100644 --- a/platform/src/bridge.ts +++ b/platform/src/bridge.ts @@ -13,10 +13,7 @@ import { } from "./util/errors"; import pkg from "../../package.json"; import { USE_FORK_SERVER, runForked } from "./bridge.fork"; - -// A line a service logged on purpose, as opposed to whatever else lands on a -// stream. Only these are forwarded to the caller. -const LOG_LINE = /^(INFO|DEBUG|ERROR|WARNING):/; +import { LOG_LINE } from "./util/log-line"; /** Run a python script diff --git a/platform/src/util/log-line.ts b/platform/src/util/log-line.ts new file mode 100644 index 00000000..b3c69ff7 --- /dev/null +++ b/platform/src/util/log-line.ts @@ -0,0 +1,4 @@ +// A line a service logged on purpose, as opposed to whatever else lands on a +// stream. Only these are forwarded to the caller. Shared by bridge.ts and +// bridge.fork.ts. +export const LOG_LINE = /^(INFO|DEBUG|ERROR|WARNING):/; From 3b56857dcdd33fddfd304479d36d53866fcff2c0 Mon Sep 17 00:00:00 2001 From: doc-han Date: Mon, 12 Oct 2026 10:59:14 +0000 Subject: [PATCH 17/22] chore: remove log --- platform/src/bridge.fork.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/platform/src/bridge.fork.ts b/platform/src/bridge.fork.ts index a6d34b14..6427d7be 100644 --- a/platform/src/bridge.fork.ts +++ b/platform/src/bridge.fork.ts @@ -56,7 +56,6 @@ function startMaster(): Promise { const timer = setTimeout(() => fail(new Error("not READY in time")), 60_000); onLines(proc.stdout!, (line) => { - console.log(`fork-server: ${line}`); if (line.startsWith("READY")) { clearTimeout(timer); resolve({ proc, socketPath }); From 5b356f49879091c4a92e213e97627717b7487919 Mon Sep 17 00:00:00 2001 From: hanna-paasivirta Date: Mon, 12 Oct 2026 18:59:15 +0100 Subject: [PATCH 18/22] Pick up the newer minor/patch bumps from #715 --- poetry.lock | 71 ++++++++++++++++++++++++++------------------------ pyproject.toml | 4 +-- 2 files changed, 39 insertions(+), 36 deletions(-) diff --git a/poetry.lock b/poetry.lock index 086bf8f3..2a210221 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1093,14 +1093,14 @@ tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<10.0.0" [[package]] name = "langchain-core" -version = "1.6.5" +version = "1.6.10" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0.0,>=3.10.0" groups = ["main"] files = [ - {file = "langchain_core-1.6.5-py3-none-any.whl", hash = "sha256:54c7b0e9314b9084fb04405bb33dc5d32986d512d92b7b8863899cd5f6267556"}, - {file = "langchain_core-1.6.5.tar.gz", hash = "sha256:bdb059fef65473fd444558dbb18f50901657402c43ceed9dc0fdc7b76a393c6b"}, + {file = "langchain_core-1.6.10-py3-none-any.whl", hash = "sha256:14341bdd8b42d0dd9a53dbbcd8b0599ab47b0c718c7caa12e3eb5c50b32cffcb"}, + {file = "langchain_core-1.6.10.tar.gz", hash = "sha256:3ad7a64eab150c1fea9f8a748b1c076aa1a960c5cf7c28d81a841a2f2dbffad1"}, ] [package.dependencies] @@ -1117,22 +1117,25 @@ uuid-utils = ">=0.12.0,<1.0" [[package]] name = "langchain-openai" -version = "1.6.6" +version = "1.7.1" description = "An integration package connecting OpenAI and LangChain" optional = false python-versions = "<4.0.0,>=3.10.0" groups = ["main"] files = [ - {file = "langchain_openai-1.6.6-py3-none-any.whl", hash = "sha256:60dcaa443ddfdf1559feaf1d25916f394c7dda809aebe22a769fc39f02705be7"}, - {file = "langchain_openai-1.6.6.tar.gz", hash = "sha256:7b3848f42825aca40165463aa37757051165eb292ba7f24658a2f58f9bb221f9"}, + {file = "langchain_openai-1.7.1-py3-none-any.whl", hash = "sha256:e65f2da39199a8e155fb6ae732e0aea208a01da2710a5da701d5e1a116195fcf"}, + {file = "langchain_openai-1.7.1.tar.gz", hash = "sha256:f9fa064c576911ff8d7c6566003bffb7eb5682c43d48407310d9de6b955f5496"}, ] [package.dependencies] certifi = ">=2024.6.2" -langchain-core = ">=1.6.4,<2.0.0" +langchain-core = ">=1.6.10,<2.0.0" openai = ">=2.45.0,<4.0.0" tiktoken = ">=0.7.0,<1.0.0" +[package.extras] +azure-identity = ["aiohttp (>=3.11.0,<4.0.0)", "azure-identity (>=1.25.0,<2.0.0)"] + [[package]] name = "langchain-pinecone" version = "0.2.13" @@ -1171,18 +1174,18 @@ typing-extensions = ">=4.13.0,<5.0.0" [[package]] name = "langchain-text-splitters" -version = "1.1.2" +version = "1.1.3" description = "LangChain text splitting utilities" optional = false python-versions = "<4.0.0,>=3.10.0" groups = ["main"] files = [ - {file = "langchain_text_splitters-1.1.2-py3-none-any.whl", hash = "sha256:a2de0d799ff31886429fd6e2e0032df275b60ec817c19059a7b46181cc1c2f10"}, - {file = "langchain_text_splitters-1.1.2.tar.gz", hash = "sha256:782a723db0a4746ac91e251c7c1d57fd23636e4f38ed733074e28d7a86f41627"}, + {file = "langchain_text_splitters-1.1.3-py3-none-any.whl", hash = "sha256:50edeb318b3be6a6308dddd7d616ab82823a9ccbea59a9c14c58a7b91df60295"}, + {file = "langchain_text_splitters-1.1.3.tar.gz", hash = "sha256:929b6c76f99d611a5b1d8f5591ef302909b86a436ceb3217034d24e4757868d8"}, ] [package.dependencies] -langchain-core = ">=1.2.31,<2.0.0" +langchain-core = ">=1.4.7,<2.0.0" [[package]] name = "langfuse" @@ -2454,14 +2457,14 @@ six = ">=1.5" [[package]] name = "python-dotenv" -version = "1.2.3" +version = "1.2.4" description = "Read key-value pairs from a .env file and set them as environment variables" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "python_dotenv-1.2.3-py3-none-any.whl", hash = "sha256:904552145e8bfed22162c09dab1c2b9b54fefa7b23ba780f4f26ca0316b0f0d9"}, - {file = "python_dotenv-1.2.3.tar.gz", hash = "sha256:a20a594dabeaa385725aa239d5244871c143ecb356add8a20fcf23773a6c3a35"}, + {file = "python_dotenv-1.2.4-py3-none-any.whl", hash = "sha256:42269a8a5b3fd54ffa6f3d84b18abed50064717576b4ecf03dc4a55d8aa04fdc"}, + {file = "python_dotenv-1.2.4.tar.gz", hash = "sha256:f0d53e69935a851c0dcc78f3ab7aaccd8cabef0b92382b576b824212902873c0"}, ] [package.extras] @@ -2713,30 +2716,30 @@ requests = ">=2.0.1,<3.0.0" [[package]] name = "ruff" -version = "0.16.9" +version = "0.16.10" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "ruff-0.16.9-py3-none-linux_armv6l.whl", hash = "sha256:95e6f022090368ab3b824c36276839c53b2adf1a3f4c09fefc33dfc400f6da96"}, - {file = "ruff-0.16.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a5f27be168556594a86d2f415db0cf43f5291917849318f873c7e2791f7a8c67"}, - {file = "ruff-0.16.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1632eb1d6197f33bd00b1acbc5b71009e89a8895c158e2d2b03a834fac964ab6"}, - {file = "ruff-0.16.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3f951b14d865d5952c89d40a5ca07e87abe24fa5453299878411e127748fb1c"}, - {file = "ruff-0.16.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:447fc07e1573afff7cb02803462b12b6c8ece7cf10e2cd78565fa6d7a1c0bf8d"}, - {file = "ruff-0.16.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a3e039a6a40ed976c491722b60e0ae4a4aa1a86057f540ee7a37a5d19ae9120"}, - {file = "ruff-0.16.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4684dded7db60aa57cb118fa158630f5feade4af5782903b6053484bdf9bd129"}, - {file = "ruff-0.16.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d29c934357e45642fda2f34c0b1f4025b4a6c01e15e4bf0016879d60078a142c"}, - {file = "ruff-0.16.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a21713e629d3e5bdb2f5c2def1cc7f04f47fa8e1a7eb0571b4a28e1da64bc728"}, - {file = "ruff-0.16.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:7baa24ef5fc8e77aa93879e1d3f43754a01ae488e869f1ae30cf431afd4d2452"}, - {file = "ruff-0.16.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a41aac6230aadfaa133bdfa1614488531ffa3e0837567ae04c0da2058a9c0f9e"}, - {file = "ruff-0.16.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:c2529fb5896d49115b0e9aa8f887490b34bbe76baf879ec2264ac59406869ce7"}, - {file = "ruff-0.16.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:41e3870277694177429b56406d65dfbdb2c2802c52b715edaf6a0b829c69d4ee"}, - {file = "ruff-0.16.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8adbe4e58af167f767d7b2ba5e83c42e878350796cf78c2f5e14ab9903a92588"}, - {file = "ruff-0.16.9-py3-none-win32.whl", hash = "sha256:0e1dbc2073624dee6618d41d0098690a7244654af746704b64759e12b6b6b385"}, - {file = "ruff-0.16.9-py3-none-win_amd64.whl", hash = "sha256:6bd40fec8cd4c8a3d4dd589bd8ad4e6320c13c29234159bfd959a40d529d597b"}, - {file = "ruff-0.16.9-py3-none-win_arm64.whl", hash = "sha256:ed1a252039200f57a59eebc063b54beabea67bfbaaca0eeaa7f54b5fbcda2284"}, - {file = "ruff-0.16.9.tar.gz", hash = "sha256:12b625c6cfba78d285d9f48eda5f053374f1e53cb10ef17342a383750db99161"}, + {file = "ruff-0.16.10-py3-none-linux_armv6l.whl", hash = "sha256:488b0fe3f3574210e5cf80d9f59b9e3ab17a127a8155de3f307b392589cfb511"}, + {file = "ruff-0.16.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e748ff95c934c4e978783b8e687bc174e7bd84e8ad24e3243e1ecfcda5e0282d"}, + {file = "ruff-0.16.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3031a4a2e8e7b8a46f70be45f198c35a11ece509a94b80334d8d397a33c67550"}, + {file = "ruff-0.16.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:494401c86df4c4c25f69b9419605d944467ee98c42fb6ad405ef4fa40b8fb67d"}, + {file = "ruff-0.16.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d203abc0ff2b773ee33d00ab8df0bb67046fbc7c07b119332f08b9b345cf8221"}, + {file = "ruff-0.16.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd83d1235a5258d318477bc5b576303974cbdef5df0c01a1bff14efcc23bd12a"}, + {file = "ruff-0.16.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc2610fb269fa56dd8a68669ae470fa6272902668c0fc2ebc3aa112b2633d5b8"}, + {file = "ruff-0.16.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3e70175e29cc94c26ea296c80e470180b744b7419026898e58f520c6ab32578e"}, + {file = "ruff-0.16.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f33f43a864a8483eebd160e713336c8bab02c934feaff0a33cf5ccb41546d09a"}, + {file = "ruff-0.16.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:1dfc6f0088149fb6a362c1c446bcbb3fd2157b3852fe2fa68409276eab9ad9b3"}, + {file = "ruff-0.16.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6553498afc35f580f036030795810b9e6bcea31604b0fd9e8d352795473042e3"}, + {file = "ruff-0.16.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a3b8471dea115d37f123882be852bed13403746d3a76c11de4a19ec5f9ff5a03"}, + {file = "ruff-0.16.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:92e59a70bcbd9d3a5483656da906ec28edfdacfce00afd99edb8b4e9d15644be"}, + {file = "ruff-0.16.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:7ae7375f803b5520dc9f546bed7e3a0acb70b91812e9bb4b19927de22f25b77d"}, + {file = "ruff-0.16.10-py3-none-win32.whl", hash = "sha256:2a12e01cb9156c10c466f63b46eaae5ecea28dfbd21b5836353ae498e7d1349a"}, + {file = "ruff-0.16.10-py3-none-win_amd64.whl", hash = "sha256:97f2015c92aa97105b0eab19eb5d224884399281cfc5da86a92db4ab5e7fb2ca"}, + {file = "ruff-0.16.10-py3-none-win_arm64.whl", hash = "sha256:25a65fe998c4e6861ec079ada5826a2fc605e6cbccbe9dcd7fac1f54e791621b"}, + {file = "ruff-0.16.10.tar.gz", hash = "sha256:eff4728c4eaae93f0955cd264d24b2ab348e74bf59986ccf282ba6dc16b3b017"}, ] [[package]] @@ -3849,4 +3852,4 @@ cffi = ["cffi (>=1.17,<2.0) ; platform_python_implementation != \"PyPy\" and pyt [metadata] lock-version = "2.1" python-versions = ">=3.11,<3.12" -content-hash = "4e3a89d36ecc43b33a5ea63f1f2f61b84e7d6e984e9f346bbf967ab4e77455c1" +content-hash = "2add86d883acf08254e340046c1fa784e73c1fa261879c79195d43ea8183c1e0" diff --git a/pyproject.toml b/pyproject.toml index 65546f47..9eac9a5c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ requires-poetry = ">=2.3.2" [tool.poetry.dependencies] python = ">=3.11,<3.12" openai = "^3.20" -python-dotenv = "^1.2.3" +python-dotenv = "^1.2.4" anthropic = "^1.9.0" langchain-pinecone = "^0.2.13" @@ -34,7 +34,7 @@ optional = false [tool.poetry.group.dev.dependencies] pytest = "^9.1.1" -ruff = "^0.16.9" +ruff = "^0.16.10" [build-system] requires = ["poetry-core"] From 034725203abe2470d2a26168649d415d0db8dbc6 Mon Sep 17 00:00:00 2001 From: hanna-paasivirta Date: Tue, 13 Oct 2026 09:53:29 +0100 Subject: [PATCH 19/22] Add changeset for dependency bumps --- .changeset/october-dependency-bumps.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/october-dependency-bumps.md diff --git a/.changeset/october-dependency-bumps.md b/.changeset/october-dependency-bumps.md new file mode 100644 index 00000000..9ea649d7 --- /dev/null +++ b/.changeset/october-dependency-bumps.md @@ -0,0 +1,5 @@ +--- +"apollo": patch +--- + +Update dependencies, including the Anthropic Python SDK to 1.x, the OpenAI SDK to 3.x and pandas to 3.x From 79a81ad4e6c4bd7a06275012f775a394c59ee135 Mon Sep 17 00:00:00 2001 From: hanna-paasivirta Date: Tue, 13 Oct 2026 09:54:52 +0100 Subject: [PATCH 20/22] Use httpx2 in the web search planner tests --- services/global_chat/tests/unit/test_planner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/global_chat/tests/unit/test_planner.py b/services/global_chat/tests/unit/test_planner.py index 00a6379c..047e2345 100644 --- a/services/global_chat/tests/unit/test_planner.py +++ b/services/global_chat/tests/unit/test_planner.py @@ -1454,9 +1454,9 @@ def test_meta_omits_the_web_fields_when_web_search_is_off() -> None: def make_bad_request(message: str = "web search is not enabled for this account") -> BadRequestError: - request = httpx.Request("POST", "https://api.anthropic.com/v1/messages") + request = httpx2.Request("POST", "https://api.anthropic.com/v1/messages") body = {"type": "error", "error": {"type": "invalid_request_error", "message": message}} - return BadRequestError(message, response=httpx.Response(400, request=request, json=body), body=body) + return BadRequestError(message, response=httpx2.Response(400, request=request, json=body), body=body) def test_a_bad_request_with_web_tools_retries_without_them() -> None: From 8ff4d376fc3b36f6853cc6f26e742c1217d627d1 Mon Sep 17 00:00:00 2001 From: doc-han Date: Tue, 13 Oct 2026 10:18:53 +0000 Subject: [PATCH 21/22] chore: update changeset --- .changeset/spicy-vans-wait.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/spicy-vans-wait.md diff --git a/.changeset/spicy-vans-wait.md b/.changeset/spicy-vans-wait.md new file mode 100644 index 00000000..20e45000 --- /dev/null +++ b/.changeset/spicy-vans-wait.md @@ -0,0 +1,5 @@ +--- +"apollo": patch +--- + +fork python processes to reduce startup time From 22bdba79376c400e0dda678959d57e83122f3e0a Mon Sep 17 00:00:00 2001 From: hanna-paasivirta Date: Tue, 13 Oct 2026 19:10:45 +0100 Subject: [PATCH 22/22] Version 3.4.0 --- .changeset/october-dependency-bumps.md | 5 ----- .changeset/olive-moons-search.md | 5 ----- .changeset/spicy-vans-wait.md | 5 ----- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- 5 files changed, 13 insertions(+), 16 deletions(-) delete mode 100644 .changeset/october-dependency-bumps.md delete mode 100644 .changeset/olive-moons-search.md delete mode 100644 .changeset/spicy-vans-wait.md diff --git a/.changeset/october-dependency-bumps.md b/.changeset/october-dependency-bumps.md deleted file mode 100644 index 9ea649d7..00000000 --- a/.changeset/october-dependency-bumps.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"apollo": patch ---- - -Update dependencies, including the Anthropic Python SDK to 1.x, the OpenAI SDK to 3.x and pandas to 3.x diff --git a/.changeset/olive-moons-search.md b/.changeset/olive-moons-search.md deleted file mode 100644 index 07a4f319..00000000 --- a/.changeset/olive-moons-search.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"apollo": minor ---- - -global_chat: opt-in web search and fetch for the planner diff --git a/.changeset/spicy-vans-wait.md b/.changeset/spicy-vans-wait.md deleted file mode 100644 index 20e45000..00000000 --- a/.changeset/spicy-vans-wait.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"apollo": patch ---- - -fork python processes to reduce startup time diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f28238e..59606ccf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # apollo +## 3.4.0 + +### Minor Changes + +- 02eaf61: global_chat: opt-in web search and fetch for the planner + +### Patch Changes + +- 0347252: Update dependencies, including the Anthropic Python SDK to 1.x, the + OpenAI SDK to 3.x and pandas to 3.x +- 8ff4d37: fork python processes to reduce startup time + ## 3.3.1 ### Patch Changes diff --git a/package.json b/package.json index 573e536e..d5441f81 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "apollo", "module": "platform/index.ts", - "version": "3.3.1", + "version": "3.4.0", "type": "module", "scripts": { "start": "NODE_ENV=production bun platform/src/index.ts",