Skip to content

feat(cli): offer agent skills install once on prisma generate - #29690

Merged
aqrln merged 11 commits into
mainfrom
tml-2971-s2-one-time-skill-offer-on-prisma-generate
Jul 22, 2026
Merged

feat(cli): offer agent skills install once on prisma generate#29690
aqrln merged 11 commits into
mainfrom
tml-2971-s2-one-time-skill-offer-on-prisma-generate

Conversation

@tensordreams

Copy link
Copy Markdown
Contributor

Stacked PR — based on #29689 (S1, the skill-install runner); will be retargeted to main once #29689 merges. The diff here is only S2's two commits.

Existing projects (which never ran the new prisma init) get exactly one polite, interactive, time-limited offer to install the prisma/skills catalog, shown after a successful prisma generate. Second slice (S2) of the Agent-Native Prisma ORM project (#29688).

Changes

  • Offer module (packages/cli/src/utils/skills/skills-offer.ts): handleSkillsOffer() runs the full NPS-style gate chain — prior acknowledgement, already-installed detection, interactive TTY, Deno guard, CI, git hook, npm lifecycle hook, container, and "first Prisma command ≥ 1 day ago" — then asks one yes/no question with a 30-second timeout defaulting to No. Every outcome (accepted / declined / timeout / already-installed) persists skills-offer.json in the OS config dir, so the offer fires once ever per machine (unlike the NPS survey's once-per-timeframe). Accepting runs S1's pinned skill-install runner; failure prints the manual command, non-fatally. The whole body never throws — an offer failure can never fail generate.
  • Generate wiring (packages/cli/src/Generate.ts): the offer runs in the existing !hideHints non-watch success block, before the NPS survey; if the offer prompted, the survey is skipped for that run — at most one prompt per generate. Injectable handler mirroring the existing surveyHandler seam.
  • Shared helper (packages/cli/src/utils/prompt-timeout.ts): the timeout() racer extracted verbatim from nps/survey.ts; both prompts now share it.
  • Telemetry: a single skills_offer_resolved { outcome, cliVersion } event through the existing PostHog capture path, only when a prompt was actually shown.
  • Tests: 27 unit tests for the module (every gate short-circuit, input variants, fake-timer timeout, four failure-isolation cases) + 4 Generate-level tests (ordering, mutual exclusion both ways, --no-hints and watch suppression). Injection over module mocking throughout.

Why

  • Once-ever, not once-per-timeframe: a declined offer should never nag again; prisma init (S1) and docs remain the discovery paths.
  • Acknowledgement only after a prompt resolves: gated-out runs (CI, non-TTY) write nothing, so a developer whose first runs are in CI still gets the offer later on a real TTY.
  • Ordering inside the resolution path (acknowledge → install → telemetry) makes once-ever survive a crash mid-install and keeps an offline telemetry endpoint from robbing an accepting user of the install.
  • Mutual exclusion with NPS keeps the post-generate moment to a single question, ever.

Verification (live pty runs, built CLI, isolated config dirs)

  • First interactive run: offer shown; n persists outcome: "declined"; second run silent.
  • Accept run: skills land via the S1 runner (24 SKILL.md across .claude/.windsurf/.agents + skills-lock.json); outcome: "accepted".
  • Non-TTY run: no prompt, no acknowledgement written, generate output normal.
  • In prompted runs the offer was the only prompt (NPS skipped; mechanism also pinned by unit tests).

Full captures: projects/agent-native/slices/generate-skill-offer/verification.md on the project branch (#29688).

Linear: TML-2971

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a shared @clack/prompts abstraction and migrates the NPS survey from readline to structured prompt outcomes. Introduces a skills-offer flow with environment gates, installation detection, acknowledgement persistence, telemetry, and failure isolation. Updates Generate to run the skills offer before the survey and uses the CLI/client generator versions for mismatch hints. Expands tests for prompt behavior, skills-offer outcomes, and Generate execution modes.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Clearly summarizes the new one-time skills-install offer added to prisma generate.
Description check ✅ Passed Describes the one-time skills offer, prompt flow, telemetry, and tests introduced in this PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch tml-2971-s2-one-time-skill-offer-on-prisma-generate
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch tml-2971-s2-one-time-skill-offer-on-prisma-generate

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

tensordreams added a commit that referenced this pull request Jul 3, 2026
All three S2 dispatches satisfied; scoreboard 5 PASS + 1 accepted
deferral. Live pty evidence in the slice verification record. One
session-limit stall (D15) retried cleanly.
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size
packages/client/runtime/index-browser.js 2.29 KB (0%)
packages/client/runtime/index-browser.d.ts 3.37 KB (0%)
packages/cli/build/index.js 110 B (0%)
packages/client/prisma-client-0.0.0.tgz 26.72 MB (0%)
packages/cli/prisma-0.0.0.tgz 14.05 MB (+0.04% 🔺)
packages/bundle-size/da-workers-libsql/output.tgz 1.33 MB (0%)
packages/bundle-size/da-workers-neon/output.tgz 1.39 MB (0%)
packages/bundle-size/da-workers-pg/output.tgz 1.39 MB (0%)
packages/bundle-size/da-workers-planetscale/output.tgz 1.33 MB (0%)
packages/bundle-size/da-workers-d1/output.tgz 1.31 MB (0%)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/cli/src/utils/prompt-timeout.ts`:
- Around line 5-16: The timeout helper in timeout() currently only handles the
resolved path, so rejected prompt promises are lost and can leave the outer
Promise pending. Update timeout() to forward both success and failure from the
input promise by adding rejection handling to the promise.then chain (or
equivalent) and clearing the timeout in both cases, using the timeoutId within
timeout() so promise rejections properly propagate to callers.

In `@packages/cli/src/utils/skills/skills-offer.ts`:
- Around line 145-166: The unguarded await in promptForInstall is affected by
the shared timeout() rejection behavior, so fix the underlying timeout helper
rather than adding a separate catch here. Make timeout() resolve with undefined
on timeout/rejection so promptForInstall can keep handling the existing answer
=== undefined path and return 'timeout' instead of bubbling to the top-level
catch.
- Around line 119-143: The install path in handleSkillsOfferImpl is not isolated
like submitOfferEvent, so a thrown ctx.installSkills error can escape and make
handleSkillsOffer report prompted:false after the prompt already showed. Wrap
the ctx.installSkills({ cwd: ctx.cwd }) call in its own try/catch inside
handleSkillsOfferImpl, log the failure similarly to the telemetry block, and
continue on to submitOfferEvent so the function still returns { prompted: true }
even when installation fails.
- Around line 222-231: The CLI version lookup is duplicated in getCliVersion and
the Generate entrypoint, so extract the esbuild-specific package.json read into
one shared helper and have both call it instead of using their own
eval(require('../package.json')) workaround. Move the version-resolution logic
into a single reusable utility with a clear name, keep the fallback to unknown
and debug logging there, and update the existing callers to use that helper so
the special-case behavior lives in one place.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 10fdcbfc-94fd-4699-8ed7-c2a4fcc8041b

📥 Commits

Reviewing files that changed from the base of the PR and between ca261b4 and 744539e.

📒 Files selected for processing (6)
  • packages/cli/src/Generate.ts
  • packages/cli/src/__tests__/commands/Generate.test.ts
  • packages/cli/src/__tests__/skills-offer.vitest.ts
  • packages/cli/src/utils/nps/survey.ts
  • packages/cli/src/utils/prompt-timeout.ts
  • packages/cli/src/utils/skills/skills-offer.ts

Comment thread packages/cli/src/utils/prompt-timeout.ts Outdated
Comment thread packages/cli/src/utils/skills/skills-offer.ts
Comment thread packages/cli/src/utils/skills/skills-offer.ts
Comment thread packages/cli/src/utils/skills/skills-offer.ts Outdated
@codspeed-hq

codspeed-hq Bot commented Jul 6, 2026

Copy link
Copy Markdown

Merging this PR will regress 1 benchmark

⚡ 1 improved benchmark
❌ 1 regressed benchmark
✅ 15 untouched benchmarks
⏩ 30 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
compile blog post page (uncached baseline) 3.2 ms 5.9 ms -46%
compile findUnique (uncached baseline) 79,875.3 µs 926.9 µs ×86

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing tml-2971-s2-one-time-skill-offer-on-prisma-generate (7446b2e) with main (272078a)2

Open in CodSpeed

Footnotes

  1. 30 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on main (96d844a) during the generation of this report, so 272078a was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

Base automatically changed from tml-2968-s1-install-prisma-skills-during-prisma-init to main July 9, 2026 15:02
@tensordreams
tensordreams force-pushed the tml-2971-s2-one-time-skill-offer-on-prisma-generate branch from b7edbaa to bbd64a2 Compare July 9, 2026 15:07
@tensordreams
tensordreams changed the base branch from main to v7 July 21, 2026 12:04
@tensordreams
tensordreams changed the base branch from v7 to main July 21, 2026 15:09
Comment thread packages/cli/src/get-cli-version.ts Outdated
Comment thread packages/cli/src/utils/prompt-timeout.ts Outdated
Comment thread packages/cli/src/utils/skills/skills-offer.ts Outdated
Comment thread packages/cli/src/utils/skills/skills-offer.ts Outdated
@tensordreams
tensordreams force-pushed the tml-2971-s2-one-time-skill-offer-on-prisma-generate branch from 275ec9f to cf04278 Compare July 21, 2026 16:41

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/cli/src/__tests__/nps.test.ts`:
- Around line 312-331: Add a regression test alongside the existing
prompt-outcome tests that configures prompts.text to resolve with an answered
value of "0", invokes handleNpsSurveyImpl, and verifies the zero rating is
captured and the expected survey completion behavior occurs. Keep the test
focused on the falsy rating boundary and match the existing test setup and
assertions.

In `@packages/cli/src/utils/nps/survey.ts`:
- Around line 79-87: Update the rating check in the survey flow around
collectFeedback so a valid rating of 0 is submitted and acknowledged like other
ratings. Check for absence explicitly rather than relying on truthiness, while
preserving the existing submitSurveyEvent, thank-you message, and writeConfig
behavior.
- Around line 116-118: Update the feedbackAnswer prompts.text call to include a
timeoutMs derived from the existing promptTimeoutSecs value, matching the
deadline used by the rating prompt and preventing the follow-up survey prompt
from waiting indefinitely.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 38916f32-83e1-47f5-9c59-477c7b3e2ebe

📥 Commits

Reviewing files that changed from the base of the PR and between cf04278 and cad6ce1.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (6)
  • packages/cli/package.json
  • packages/cli/src/__tests__/nps.test.ts
  • packages/cli/src/__tests__/skills-offer.vitest.ts
  • packages/cli/src/utils/nps/survey.ts
  • packages/cli/src/utils/prompts.ts
  • packages/cli/src/utils/skills/skills-offer.ts

Comment thread packages/cli/src/__tests__/nps.test.ts
Comment thread packages/cli/src/utils/nps/survey.ts
Comment thread packages/cli/src/utils/nps/survey.ts
Add handleSkillsOffer(), which offers to install the Prisma agent
skills once ever per machine. The offer only fires when no
skills-offer.json acknowledgement exists in the prisma config
directory, the project has no Prisma skills installed already (that
case writes an already-installed acknowledgement so the project is
never scanned again), the session is interactive, not Deno, not CI,
not a git or npm lifecycle hook, not a container, and the first CLI
command was issued at least a day ago. The prompt defaults to No and
times out after 30 seconds; the outcome (accepted, declined, timeout,
already-installed) is persisted unconditionally and reported through
a skills_offer_resolved PostHog event only when a prompt was actually
shown. Accepting runs the skill-install runner with the same
non-fatal manual-command warning as prisma init.

The offer never throws, and the acknowledgement write and telemetry
submission are additionally guarded on their own so that a read-only
config dir or an offline telemetry endpoint cannot misreport a shown
prompt as not shown (the Generate caller uses that flag for mutual
exclusion with the NPS survey).

The timeout() helper moves from the NPS survey to a shared
prompt-timeout module so both prompts use the same implementation.
Wire the one-time skills offer into the non-watch generate success
path, in the same block as the NPS survey and before it. When the
offer actually prompts, the survey is skipped for that run so a single
generate never shows two prompts; when it does not prompt, the survey
runs exactly as before. Watch mode and --no-hints continue to suppress
both. The offer handler is a constructor parameter defaulting to
handleSkillsOffer, mirroring the existing surveyHandler injection.
The init-time install copies skills into .claude/skills/,
.windsurf/skills/, and .agents/skills/, but the generate-time offer's
already-installed scan only checked two of the three directories plus
skills-lock.json. A project where only the Windsurf copy survives
(e.g. the other directories were removed) would be re-offered the
install. The scan now covers all three per-agent directories.

Addresses a review finding on the initial PR.
timeout() swallowed rejections and resolved to undefined, which hid stdin
failures from every caller and made a broken stream indistinguishable from
a genuine timeout. Reject with the original error instead, and clear the
timer on both paths so a settled prompt never leaves a timer holding the
event loop open.

The skills offer keeps treating an unreadable answer as no answer, so the
offer is still recorded as resolved and generate never asks twice. The NPS
survey now aborts on a prompt failure instead of writing an acknowledgement
for a survey the user never saw.

Also distinguish ENOENT/ENOTDIR from unexpected errors when probing for the
acknowledgement file and the installed skill directories, so a permission
error is no longer silently read as "not installed".
Release builds replace the version in package.json before pnpm build, so
the version can be imported directly instead of being read through an eval
wrapper at runtime. This drops the get-cli-version module along with its
'unknown' fallback, which no longer has a way to trigger, and matches how
MCP.ts already reads the version.
The guard dates to #27133, where merely creating a readline interface on
Deno kept `prisma generate` alive until Enter was pressed. Verified against
Deno 2.9.3: creating and closing an interface, and the full question-with-
timeout path, both exit cleanly and behave exactly as they do on Node, so
the prompts no longer need to be skipped there.
The skills offer asked for "y" followed by Enter, which is a clumsy way to
answer a yes/no question. clack's confirm submits on the y/n keypress
itself, so accepting or declining is now a single key.

Its prompts also take an AbortSignal, which replaces the timeout helper
that raced a promise against a timer: the deadline now cancels the prompt
and restores the terminal instead of walking away from a prompt still
holding stdin. An aborted signal also tells a lapsed deadline apart from a
user dismissing the prompt, so Ctrl+C and Esc are recorded as declining
rather than as a timeout.

Both prompts move behind a small Prompts interface so callers stay testable
without a TTY. The NPS survey loses its readline lifecycle and the proxy
that guarded against a closed stream, both of which clack owns per prompt.

@clack/prompts is ESM-only and goes in devDependencies, following the
convention that bundles dev dependencies into the CJS CLI build.
`if (result.rating)` treated a rating of 0 as no rating at all, so the most
negative score the survey can collect was dropped: no event was captured
and the user was not thanked, while the timeframe was still acknowledged so
the survey never asked again. Check for an answer rather than a truthy one.

The follow-up feedback prompt also had no deadline of its own and would
wait indefinitely once the rating was in. It now carries the same 30s
deadline as the rating prompt; a rating already given is still submitted
when the follow-up lapses.
…solves

The offer is shown once ever per machine, so that single conversation is
also the only chance to tell the user how to install the skills in other
projects. Every prompted outcome now ends with the manual install command:
after a successful install it points at other projects, and after a
decline, dismissal, or timeout it doubles as the way to opt back in. The
failed-install warning already carries the command and stays as is.

The command comes from a new manualInstallCommand export in skill-install,
sharing the runner detection used by the install itself, so it renders as
npx/pnpm dlx/yarn dlx/bunx to match the project at hand.
The already-installed branch wrote the machine-global acknowledgement, so
the first generate run in any project that already had the skills (e.g.
one set up by prisma init) silently settled the offer for every project on
the machine, including ones with no skills at all. Detection is per
project while the acknowledgement is per machine; conflating them spent
the one prompt on a project that never saw it.

The branch now stays silent without recording anything: projects with the
skills are skipped on every run via detection, and the acknowledgement is
only ever written for a prompt that was actually shown. The
'already-installed' outcome disappears from SkillsOfferOutcome along with
its only writer.
@tensordreams
tensordreams force-pushed the tml-2971-s2-one-time-skill-offer-on-prisma-generate branch from 8dc3ce1 to 7446b2e Compare July 22, 2026 12:04
@aqrln
aqrln merged commit c5c6cba into main Jul 22, 2026
253 checks passed
@aqrln
aqrln deleted the tml-2971-s2-one-time-skill-offer-on-prisma-generate branch July 22, 2026 12:33
lh0x00 pushed a commit to lh0x00/prisma that referenced this pull request Aug 9, 2026
…#29690)

> **Stacked PR** — based on prisma#29689 (S1, the skill-install runner); will
be retargeted to `main` once prisma#29689 merges. The diff here is only S2's
two commits.

Existing projects (which never ran the new `prisma init`) get exactly
one polite, interactive, time-limited offer to install the
[prisma/skills](https://github.com/prisma/skills) catalog, shown after a
successful `prisma generate`. Second slice (S2) of the Agent-Native
Prisma ORM project (prisma#29688).

## Changes

- **Offer module** (`packages/cli/src/utils/skills/skills-offer.ts`):
`handleSkillsOffer()` runs the full NPS-style gate chain — prior
acknowledgement, already-installed detection, interactive TTY, Deno
guard, CI, git hook, npm lifecycle hook, container, and "first Prisma
command ≥ 1 day ago" — then asks one yes/no question with a 30-second
timeout defaulting to No. Every outcome (`accepted` / `declined` /
`timeout` / `already-installed`) persists `skills-offer.json` in the OS
config dir, so the offer fires **once ever per machine** (unlike the NPS
survey's once-per-timeframe). Accepting runs S1's pinned skill-install
runner; failure prints the manual command, non-fatally. The whole body
never throws — an offer failure can never fail `generate`.
- **Generate wiring** (`packages/cli/src/Generate.ts`): the offer runs
in the existing `!hideHints` non-watch success block, before the NPS
survey; if the offer prompted, the survey is skipped for that run — at
most one prompt per generate. Injectable handler mirroring the existing
`surveyHandler` seam.
- **Shared helper** (`packages/cli/src/utils/prompt-timeout.ts`): the
`timeout()` racer extracted verbatim from `nps/survey.ts`; both prompts
now share it.
- **Telemetry**: a single `skills_offer_resolved` `{ outcome, cliVersion
}` event through the existing PostHog capture path, only when a prompt
was actually shown.
- **Tests**: 27 unit tests for the module (every gate short-circuit,
input variants, fake-timer timeout, four failure-isolation cases) + 4
Generate-level tests (ordering, mutual exclusion both ways, `--no-hints`
and watch suppression). Injection over module mocking throughout.

## Why

- **Once-ever, not once-per-timeframe**: a declined offer should never
nag again; `prisma init` (S1) and docs remain the discovery paths.
- **Acknowledgement only after a prompt resolves**: gated-out runs (CI,
non-TTY) write nothing, so a developer whose first runs are in CI still
gets the offer later on a real TTY.
- **Ordering inside the resolution path** (acknowledge → install →
telemetry) makes once-ever survive a crash mid-install and keeps an
offline telemetry endpoint from robbing an accepting user of the
install.
- **Mutual exclusion with NPS** keeps the post-generate moment to a
single question, ever.

## Verification (live pty runs, built CLI, isolated config dirs)

- First interactive run: offer shown; `n` persists `outcome:
"declined"`; second run silent.
- Accept run: skills land via the S1 runner (24 SKILL.md across
`.claude`/`.windsurf`/`.agents` + `skills-lock.json`); `outcome:
"accepted"`.
- Non-TTY run: no prompt, no acknowledgement written, generate output
normal.
- In prompted runs the offer was the only prompt (NPS skipped; mechanism
also pinned by unit tests).

Full captures:
`projects/agent-native/slices/generate-skill-offer/verification.md` on
the project branch (prisma#29688).

**Linear:**
[TML-2971](https://linear.app/prisma-company/issue/TML-2971/s2-one-time-skill-offer-on-prisma-generate)
OIRNOIR pushed a commit to OIRNOIR/YouTube-Helper-Server that referenced this pull request Sep 1, 2026
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [@prisma/adapter-pg](https://github.com/prisma/prisma) ([source](https://github.com/prisma/prisma/tree/HEAD/packages/adapter-pg)) | imports | minor | [`7.9.1` -> `7.10.0`](https://renovatebot.com/diffs/npm/@prisma%2fadapter-pg/7.9.1/7.10.0) |
| [@prisma/client](https://www.prisma.io) ([source](https://github.com/prisma/prisma/tree/HEAD/packages/client)) | imports | minor | [`7.9.1` -> `7.10.0`](https://renovatebot.com/diffs/npm/@prisma%2fclient/7.9.1/7.10.0) |

---

### Release Notes

<details>
<summary>prisma/prisma (@&#8203;prisma/adapter-pg)</summary>

### [`v7.10.0`](https://github.com/prisma/orm/releases/tag/7.10.0)

[Compare Source](prisma/orm@7.9.1...7.10.0)

##### Prisma ORM 7.10.0

Prisma ORM 7.10.0 introduces a compatibility package for running Prisma 7 alongside newer Prisma versions, secures Prisma Studio's local server, and includes fixes across Prisma Client and the PostgreSQL, MariaDB, Neon, SQLite, and Prisma Postgres Serverless adapters.

##### Highlights

##### Run Prisma 7 alongside Prisma 8

This release introduces `@prisma/prisma7`, a compatibility package that lets you retain a matching Prisma 7 CLI and configuration while installing Prisma 8 in the same project.

Once 7.10.0 is released, a side-by-side installation can use:

```sh
npm install --save-dev prisma@8 @prisma/prisma7@7.10.0
npm install @prisma/client@7.10.0
```

Use `prisma` for the directly installed Prisma 8 CLI and `prisma7` for Prisma 7:

```sh
npx prisma --version
npx prisma7 --version

npx prisma7 generate
npx prisma7 migrate dev
npx prisma7 db push
```

Prisma 7 now prefers version-specific configuration files, allowing its configuration to coexist with Prisma 8's `prisma.config.*` files:

```ts
// prisma7.config.ts
import { defineConfig } from '@prisma/prisma7/config'

export default defineConfig({
  schema: 'prisma/schema.prisma',
  migrations: {
    path: 'prisma/migrations',
  },
})
```

Without an explicit `--config` option, Prisma 7 searches for:

1. Root-level `prisma7.config.*` files.
2. `.config/prisma7.*` files.
3. Existing `prisma.config.*` files as a backwards-compatible fallback.

The supported extensions are `.js`, `.ts`, `.mjs`, `.cjs`, `.mts`, and `.cts`. An explicit config path always takes precedence:

```sh
npx prisma7 generate --config ./custom/prisma7.config.ts
```

New projects initialized by the Prisma 7 CLI use `prisma7.config.ts`. Existing projects containing only `prisma.config.*` continue to work without migration or additional warnings. If a `prisma7.config.*` file exists but cannot be loaded, Prisma reports the error rather than silently falling back to another configuration.

The `prisma7` identity is carried through CLI help, version output, shell completion, initialization, migration, database, and generation guidance. Stable Prisma concepts such as `schema.prisma`, Prisma Migrate, `@prisma/client`, and `PRISMA_*` environment variables remain unchanged.

Together, the separate executable and configuration namespace make it possible to operate Prisma 7 and Prisma 8 side by side without command or config-file collisions.

[#&#8203;29949](prisma/orm#29949), [#&#8203;29969](prisma/orm#29969), [#&#8203;29994](prisma/orm#29994), [#&#8203;30000](prisma/orm#30000), [#&#8203;30002](prisma/orm#30002), [#&#8203;30020](prisma/orm#30020)

##### Prisma Studio security hardening

Prisma Studio's local HTTP server now:

- Binds explicitly to `127.0.0.1` instead of all network interfaces.
- Rejects browser requests from origins other than the active `localhost` or `127.0.0.1` Studio URL.
- No longer returns wildcard CORS headers.
- Applies the same protections across Node.js, Bun, and Deno.

This prevents network clients or malicious websites from accessing Studio's database endpoints while Studio is running.

[#&#8203;29890](prisma/orm#29890)

##### Prisma Client

- Fixed `P2002` errors from nested writes so `meta.modelName` identifies the model where the unique constraint violation occurred, including models using `@@map` and `@@schema`. [#&#8203;29628](prisma/orm#29628)
- Fixed automatically batched `findUniqueOrThrow()` calls so every missing record rejects with `P2025`; later misses no longer resolve to `undefined`. [#&#8203;29654](prisma/orm#29654)
- Parameter-chunked statements are now executed atomically in a transaction and rolled back if a later chunk fails. [#&#8203;29771](prisma/orm#29771)
- Improved interactive transaction cleanup during `$disconnect()`, including transactions whose driver-level startup is still in progress. [#&#8203;28768](prisma/orm#28768)
- Prevented transaction cleanup failures after a timeout or backend termination from becoming unhandled promise rejections. [#&#8203;29611](prisma/orm#29611)
- Fixed fluent relation queries when relation fields are literally named `select` or `include`. [#&#8203;29683](prisma/orm#29683)
- Fixed handling of `Date` and `Uint8Array` values created in other JavaScript realms, such as iframes, jsdom, and Node.js `vm` contexts. [#&#8203;29177](prisma/orm#29177)
- Invalid `Date` values passed to `$queryRaw` or `$executeRaw` now throw `PrismaClientValidationError` instead of a generic error. [#&#8203;29718](prisma/orm#29718)
- Fixed `moduleFormat` inference for the `prisma-client` generator in TypeScript projects using `module: "node16"` or `"nodenext"`. Generated output now follows the nearest `package.json` `type`, defaulting to CommonJS when absent. [#&#8203;29712](prisma/orm#29712)
- Deserialized `Bytes` values now own standalone `ArrayBuffer`s rather than exposing unrelated contents from Node.js's shared `Buffer` pool. This applies to both regular and raw query results. [#&#8203;29701](prisma/orm#29701)
- Fixed an incorrect logging context in the remote executor, including Accelerate-backed query execution. [#&#8203;28892](prisma/orm#28892)

##### Client extensions and observability

- Result-extension `compute` callbacks now receive the current model name as a typed second argument:

  ```ts
  compute(data, modelName) {
    // ...
  }
  ```

  The model name is also preserved when multiple extensions compose the same computed field. [#&#8203;29782](prisma/orm#29782)

- Improved OpenTelemetry context for remotely executed queries:

  - `$on('query')` callbacks run within the matching `db_query` span.
  - Events from one operation share the same trace.
  - Error events are recorded as span exceptions.
  - Log events continue to be emitted when tracing is disabled or their reported span is unavailable.

  [#&#8203;28892](prisma/orm#28892)

##### Driver adapters

##### MariaDB

- `@prisma/adapter-mariadb` now accepts an existing `mariadb` pool. External pools remain caller-owned unless `disposeExternalPool: true` is supplied. [#&#8203;27992](prisma/orm#27992)
- Fixed pooled connection leaks during commit, rollback, and failed transaction startup. Connections are now returned with `release()` and transaction-specific listeners are removed before reuse. [#&#8203;29612](prisma/orm#29612)
- Added support for bracketed IPv6 addresses in both `mysql://` and `mariadb://` connection strings. [#&#8203;29026](prisma/orm#29026)
- Prevented malformed connection strings from exposing embedded passwords in retained debug output and diagnostic reports. [#&#8203;27992](prisma/orm#27992)

##### PostgreSQL, Neon, and Prisma Postgres Serverless

- PostgreSQL deadlocks using SQLSTATE `40P01` are now reported as `P2034` transaction write conflicts. [#&#8203;29717](prisma/orm#29717)
- PostgreSQL `RESTRICT` violations using SQLSTATE `23001` are now reported as `P2003`, preserving an available field or constraint name. [#&#8203;29554](prisma/orm#29554)
- `@prisma/adapter-pg` now preserves database constraint names when reporting unique constraint violations through `P2002`. [#&#8203;29587](prisma/orm#29587)
- Prisma Postgres Serverless now prefers the named constraint for `P2002`, falling back to parsed field names when no constraint name is available. [#&#8203;29801](prisma/orm#29801)
- Fixed Neon HTTP adapter serialization for typed parameters such as `Bytes` and `DateTime`. [#&#8203;29747](prisma/orm#29747)

##### SQLite

- `@prisma/adapter-better-sqlite3` now converts previously unhandled SQLite result codes into typed database errors instead of exposing raw driver errors.
- The complete `SQLITE_BUSY` family is now mapped to socket timeout errors, with numeric extended result codes preserved where available.

[#&#8203;29794](prisma/orm#29794)

##### CLI and Migrate

- `prisma generate` can now offer to install Prisma's agent skills. The opt-in prompt:

  - Is shown at most once per machine.
  - Is skipped in CI, containers, Git hooks, npm lifecycle scripts, and watch mode.
  - Is skipped when `--no-hints` is used or Prisma skills are already installed.
  - Times out after 30 seconds.
  - Never causes generation to fail if installation is unsuccessful.

  [#&#8203;29690](prisma/orm#29690)

- A globally installed CLI now warns during `prisma generate` when its version differs from the project's local `prisma` or `@prisma/client`, and recommends running the local CLI. The check is best-effort and does not fail generation. [#&#8203;29593](prisma/orm#29593)

- `prisma version` and `prisma version --json` now include the resolved Prisma CLI package path, making global-versus-local installation issues easier to diagnose. [#&#8203;29573](prisma/orm#29573)

- Empty or generator-only schema files now report `Schema must contain a datasource block` from `db pull`, `db push`, and `migrate dev`, rather than reaching the schema engine and potentially producing inconsistent errors. [#&#8203;29657](prisma/orm#29657)

- CLI commands now tolerate corrupt, unreadable, or unwritable command-state files. Invalid state is reinitialized, writes are atomic, and persistence failures fall back to in-memory state. [#&#8203;29609](prisma/orm#29609)

- Studio now recognizes semicolon-delimited `sqlserver://` connection strings before reporting the existing explicit message that SQL Server is not supported by Studio. [#&#8203;29623](prisma/orm#29623)

- The AI-agent safety checkpoint now also covers interactive `prisma db push` confirmations involving data-loss warnings, rather than only invocations using `--accept-data-loss`. [#&#8203;29793](prisma/orm#29793)

##### Performance and reliability

- Optimized query-plan execution by eagerly evaluating plans with one unconditional database operation and synchronously interpreting the remaining pure plan. Cached plans remain immutable. [#&#8203;29004](prisma/orm#29004)
- Prevented call-stack overflows when rendering very large parameter lists or combining chunked results containing hundreds of thousands of rows. [#&#8203;29751](prisma/orm#29751)
- Reduced ordinary query setup overhead by constructing fluent-relation field maps lazily and in linear time. Non-fluent queries no longer build this map. [#&#8203;29752](prisma/orm#29752)

##### Dependencies

- Updated the transitive `fast-uri` dependency to a patched release addressing production audit advisories affecting versions through `3.1.3`. [#&#8203;29758](prisma/orm#29758)

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zMC4zIiwidXBkYXRlZEluVmVyIjoiNDQuMzAuMyIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://git.oirnoir.dev/OIRNOIR/YouTube-Helper-Server/pulls/41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants