Skip to content

FE-717: Prepare Petrinaut for AI assistant#8721

Open
CiaranMn wants to merge 4 commits into
mainfrom
cm/prepare-petrinaut-for-ai-actions
Open

FE-717: Prepare Petrinaut for AI assistant#8721
CiaranMn wants to merge 4 commits into
mainfrom
cm/prepare-petrinaut-for-ai-actions

Conversation

@CiaranMn
Copy link
Copy Markdown
Member

🌟 What is the purpose of this PR?

This is preparatory work for adding an AI assistant, which will need access to tools to mutate the Petri net.

The PR:

  1. Moves the net mutation functions from the react context to Petrinaut core
  2. Adds them as methods to the instance. IN NEXT PR: nest these under an actions property on the instance (e.g. instance.actions.addType).
  3. Adds Zod schemas with descriptions for all of them, and generates AI tools from them.
  4. Adds schema validation to the instance methods.
  5. Changes to make the input parameters to the functions compatible with AI tool calling:
    • Changes the updateX functions which take a callback to instead take an update object
    • Changes all functions to take a single object, instead of positional values (e.g. updateX(id, update) becomes updateX({ id, update }). This has caused changes to core. While I was touching these functions in core I just took their typing from the mutation functions in core rather than having them all repeat the interface, but can revert it if there was a reason for how it was before.
    • Adds a few more mutation methods to allow for mutating nested non-primitive values (e.g. arc arrays).

Pre-Merge Checklist 🚀

🚢 Has this modified a publishable library?

This PR:

  • does not modify any publishable blocks or libraries, or modifications do not need publishing

📜 Does this require a change to the docs?

The changes in this PR:

  • are internal and do not require a docs change

🕸️ Does this require a change to the Turbo Graph?

The changes in this PR:

  • do not affect the execution graph

🐾 Next steps

Add the AI assistant UI and demo website server endpoint.

🛡 What tests cover this?

  • A few unit tests added.

❓ How to test this?

  1. Check that Petrinaut still works.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 15, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hash Ready Ready Preview, Comment May 15, 2026 6:43pm
petrinaut Ready Ready Preview, Comment May 15, 2026 6:43pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
hashdotdesign-tokens Ignored Ignored Preview May 15, 2026 6:43pm

@cursor
Copy link
Copy Markdown

cursor Bot commented May 15, 2026

PR Summary

Medium Risk
Medium risk because it refactors all SDCPN mutation call sites to new validated, schema-driven action APIs and adds new cascading delete/arc/type-element mutations, which could subtly change editor behavior if any inputs or validation differ from prior logic.

Overview
Moves all SDCPN mutation logic out of the React MutationProvider into core via new createPetrinautActions, and mixes these validated action methods directly into the Petrinaut instance.

Adds a comprehensive set of Zod schemas (with descriptions) for every mutation in action-schemas.ts plus new entity schemas for places/transitions/types/equations/parameters/scenarios/metrics, then builds AI-facing tool metadata in core/ai.ts (including a getLatestNetDefinition tool name and a shared petrinautAiPrompt).

Updates the editor/UI to call mutations with single-object inputs (replacing callback/positional mutation APIs), introduces granular actions like updateArcPlace and type element add/update/move/remove, and expands tests to cover validation, readonly no-ops, cascading deletes, and relaxed import/clipboard defaults.

Reviewed by Cursor Bugbot for commit a2406d2. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions github-actions Bot added area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team area/apps > hash.design Affects the `hash.design` design site (app) labels May 15, 2026
@augmentcode
Copy link
Copy Markdown

augmentcode Bot commented May 15, 2026

🤖 Augment PR Summary

Summary: Preparatory refactor to make Petrinaut’s SDCPN mutations callable as validated “actions”, enabling future AI-assistant tool calling.

Changes:

  • Moved net mutation helpers out of React context into core as createPetrinautActions() and mixed them into the Petrinaut instance.
  • Introduced Zod v4 schemas for core entities plus action input schemas with rich descriptions.
  • Added schema-based input validation and updated mutation APIs to accept single-object payloads (AI-tool friendly), replacing callback-based updaters.
  • Added granular mutation actions for arcs and type elements (endpoint/weight/type updates, element CRUD/reorder, bulk deletes, position commits).
  • Added AI exports: generated tool metadata from schemas, a callback map backed by the Petrinaut instance, and a Petrinaut-specific prompt bundle.
  • Updated clipboard/file-format parsers to reuse current schemas while preserving relaxed import defaults; added tests.
  • Refactored UI/editor call sites to the new action signatures and expanded unit tests for correctness/validation.

Technical Notes: Action inputs use z.strictObject to reject unknown keys; validation is applied both at input boundaries and after in-place draft mutation.

🤖 Was this summary useful? React with 👍 or 👎

Copy link
Copy Markdown

@augmentcode augmentcode Bot left a comment

Choose a reason for hiding this comment

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

Review completed. 1 suggestion posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

}
for (const equation of sdcpn.differentialEquations) {
if (equation.colorId === parsedTypeId) {
equation.colorId = "";
Copy link
Copy Markdown

@augmentcode augmentcode Bot May 15, 2026

Choose a reason for hiding this comment

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

libs/@hashintel/petrinaut/src/core/actions.ts:~320 — removeType assigns equation.colorId = "", but differentialEquationSchema requires a non-empty idSchema for colorId, so this can leave the document in an invalid state where later equation updates/validations will throw and the equation becomes effectively uneditable.

Severity: high

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Copy link
Copy Markdown

@augmentcode augmentcode Bot left a comment

Choose a reason for hiding this comment

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

Review completed. 1 suggestion posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

});

if (typeof window !== "undefined") {
window.addEventListener("beforeunload", () => {
Copy link
Copy Markdown

@augmentcode augmentcode Bot May 15, 2026

Choose a reason for hiding this comment

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

libs/@hashintel/petrinaut/src/core/instance.ts:66 — This beforeunload cleanup doesn’t cover instance.dispose() (and the handler itself isn’t removed), so doc subscriptions/listeners can still accumulate in long-lived pages or if multiple Petrinaut instances are created/destroyed.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

(item) => item.elementId === input.elementId,
);
if (element) {
Object.assign(element, clone(input.update));
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a2406d2. Configure here.

type: z.enum(["real", "integer", "boolean", "ratio"]),
...currentScenarioParameterSchema.shape,
identifier: z.string(),
default: z.number(),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

File format rejects equations with cleared colorId

High Severity

The differentialEquationSchema in both file-format and clipboard types now inherits colorId: idSchema (which enforces min(1)) from currentDifferentialEquationSchema.shape, but only overrides id and name to be more permissive. The old schema used plain z.string() for colorId. Since removeType and deleteItemsByIds actively set equation.colorId = "" when a referenced type is removed, any file exported after that operation cannot be re-imported, and clipboard paste of such equations fails.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit a2406d2. Configure here.

existingParameter.name = event.target.value;
updateParameter({
parameterId: parameter.id,
update: { name: event.target.value },
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Validated mutations throw on intermediate onChange keystrokes

Medium Severity

The onChange handlers for parameter name, type name, and differential equation name call mutation actions directly on every keystroke. The new actions validate through displayNameSchema, which rejects empty strings. When a user clears or selects-all-and-retypes the field, the validation throws an uncaught error, preventing the update and causing an input desync. The old callback-based mutations had no such validation. Other properties (e.g., place name) correctly use local state with onBlur validation.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit a2406d2. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/apps > hash.design Affects the `hash.design` design site (app) area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team

Development

Successfully merging this pull request may close these issues.

2 participants