@awak-app/simy-cli 0.2.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +145 -1
- package/package.json +14 -5
- package/src/agent.js +740 -37
- package/src/bounded-local-task-subtask-pool.js +708 -0
- package/src/bounded-local-task-subtasks-contract.js +1189 -0
- package/src/cli-contract.js +42 -3
- package/src/console/app.js +212 -90
- package/src/desktop-executor.js +21 -2
- package/src/durable-local-task-steps-contract.js +1256 -0
- package/src/durable-local-task-worker.js +2607 -0
- package/src/execution-capability-contract.js +116 -0
- package/src/execution-guardrail.js +69 -12
- package/src/index.js +22 -7
- package/src/local-attachments.js +94 -113
- package/src/local-task-artifact-contract.js +266 -0
- package/src/local-task-attachment-store.js +447 -0
- package/src/local-task-file-capabilities.js +738 -0
- package/src/local-task-scenario-packs.js +681 -0
- package/src/local-task.js +1137 -0
- package/src/orchestrator/audit.js +42 -1
- package/src/orchestrator/loop.js +29 -3
- package/src/repository-inventory.js +37 -1
- package/src/runner.js +44 -0
- package/src/shutdown.js +63 -0
- package/src/sqm/bundle-store.js +249 -0
- package/src/sqm/canonical.js +45 -0
- package/src/sqm/checkers.js +299 -0
- package/src/sqm/command.js +149 -0
- package/src/sqm/evidence-client.js +12 -0
- package/src/sqm/index.js +141 -0
- package/src/sqm/proof.js +154 -0
- package/src/sqm/repository.js +163 -0
- package/src/sqm/session.js +58 -0
- package/src/sqm/validation.js +305 -0
- package/src/workspace-context.js +40 -7
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SIMY CLI
|
|
2
2
|
|
|
3
|
-
Local execution agent for SIMY Agentic Loop runs.
|
|
3
|
+
Local execution agent for SIMY Local Tasks and Agentic Loop runs.
|
|
4
4
|
|
|
5
5
|
For normal use, install SIMY globally and keep its background agent running:
|
|
6
6
|
|
|
@@ -44,6 +44,95 @@ the Provider command boundary, and permits exactly one Provider invocation. It
|
|
|
44
44
|
does not create an Agentic Loop ledger, audit session, or retry lifecycle for
|
|
45
45
|
that task.
|
|
46
46
|
|
|
47
|
+
## Local Tasks
|
|
48
|
+
|
|
49
|
+
CLI API contract v9 promotes non-coding work to a first-class **Local Task**
|
|
50
|
+
runtime. A Local Task is separate from Agentic Loop: it runs one bounded Codex
|
|
51
|
+
or Claude Code session without Git branches, pull requests, audits, or automatic
|
|
52
|
+
Provider retries. Knowledge-work deliverables use an isolated task sandbox by
|
|
53
|
+
default, so they do not require a repository.
|
|
54
|
+
|
|
55
|
+
`POST /v1/local-tasks/start` accepts JSON or the same verified multipart
|
|
56
|
+
attachment envelope used by Agentic Loop and requires a stable
|
|
57
|
+
`Idempotency-Key`. Repeating the same request returns the original task; using
|
|
58
|
+
the same key for different content returns
|
|
59
|
+
`LOCAL_TASK_IDEMPOTENCY_CONFLICT`. `GET /v1/local-tasks/reconcile` with the same
|
|
60
|
+
header recovers a task when the original response was lost. Only the key hash is
|
|
61
|
+
persisted. Task state, verified inputs, and the event log stay under
|
|
62
|
+
`~/.simy/tasks/<task-id>/`. Tasks that do not need a Git
|
|
63
|
+
repository run in `~/simy/<task-id>/`, with generated files in its `outputs/`
|
|
64
|
+
directory. The public snapshot exposes this user-facing workspace as
|
|
65
|
+
`workspace_display_path` without exposing internal state paths. Set
|
|
66
|
+
`SIMY_LOCAL_TASK_WORKSPACE_ROOT` to override the default workspace root.
|
|
67
|
+
|
|
68
|
+
Local Tasks provide:
|
|
69
|
+
|
|
70
|
+
- `GET /v1/local-tasks/<id>` for the current structured snapshot;
|
|
71
|
+
- `GET /v1/local-tasks/reconcile` for request-key reconciliation;
|
|
72
|
+
- `GET /v1/local-tasks/<id>/stream` for live Server-Sent Events;
|
|
73
|
+
- `POST /v1/local-tasks/<id>/control` with `{"action":"stop"}`;
|
|
74
|
+
- `GET /v1/local-tasks/<id>/artifacts/<artifact-id>` for a verified output;
|
|
75
|
+
- one Provider invocation, a configurable Provider-token safety budget, and a
|
|
76
|
+
bounded runtime timeout;
|
|
77
|
+
- restart-safe terminal persistence. An interrupted active task fails closed
|
|
78
|
+
after CLI restart and is never replayed automatically.
|
|
79
|
+
|
|
80
|
+
Interactive Pipelines can use the same daemon worker for a `local_task` node.
|
|
81
|
+
The CLI still invokes the selected Provider exactly once. Before the node is
|
|
82
|
+
reported as successful, every output file is re-verified, uploaded through a
|
|
83
|
+
task-bound short-lived URL, and committed only after SIMY rechecks its byte
|
|
84
|
+
size and SHA-256 digest. Ordinary My AI Local Tasks keep their existing local
|
|
85
|
+
verified-download behavior. Scheduled or unattended Pipeline runs are not
|
|
86
|
+
allowed to select a desktop implicitly.
|
|
87
|
+
|
|
88
|
+
Web and Backend may opt into `durable_local_task_steps` for a versioned
|
|
89
|
+
multi-step Local Task. The daemon then claims and executes one closed-schema
|
|
90
|
+
step at a time (maximum eight), with an independent Provider invocation
|
|
91
|
+
boundary per step and aggregate step, token, and runtime budgets. The task
|
|
92
|
+
workspace is stable for the turn while each lease attempt has its own local
|
|
93
|
+
record. A step that crossed its Provider boundary is never replayed
|
|
94
|
+
automatically.
|
|
95
|
+
|
|
96
|
+
Plan initialization uses a two-phase claim. Web stores an authoritative
|
|
97
|
+
`execution_spec.controlled_plan`; the CLI validates that its Provider,
|
|
98
|
+
operation, permission, repository, approval target, and aggregate budgets
|
|
99
|
+
cannot exceed the enclosing execution spec, then submits the exact plan for
|
|
100
|
+
Backend persistence. The CLI never asks a Provider to infer or expand a plan.
|
|
101
|
+
Older one-shot requests receive a deterministic one-step compatibility plan.
|
|
102
|
+
|
|
103
|
+
Human approval and unknown Provider results are distinct non-executable
|
|
104
|
+
dispositions. Neither holds a Provider process, heartbeat lease, or update
|
|
105
|
+
work reservation. Only bounded summaries and verified artifact references from
|
|
106
|
+
completed steps may enter the next step's context. Unknown plan fields,
|
|
107
|
+
unscoped approvals, unsafe paths, and Provider-supplied risk metadata fail
|
|
108
|
+
closed. The original `local_task_execution.v1` one-shot path remains available
|
|
109
|
+
unchanged for clients that do not negotiate this feature.
|
|
110
|
+
|
|
111
|
+
Contract 10 additionally advertises `bounded_local_task_subtasks`. Backend
|
|
112
|
+
admits at most two Provider children at once from a closed `parallel_reads`
|
|
113
|
+
plan with 2-4 source-bound candidates. When Crew declines or times out, the
|
|
114
|
+
same v2 contract can admit one `serial_uploaded` read-only child for 2-4
|
|
115
|
+
uploaded sources; this fallback never routes those uploads through the v1 CLI
|
|
116
|
+
staging materializer. The CLI never prefetches beyond an available execution slot:
|
|
117
|
+
each child starts only after a fenced server claim and an explicitly confirmed
|
|
118
|
+
invocation boundary. Children inherit the parent Provider and model, run in
|
|
119
|
+
separate read-only task sandboxes, receive only verified immutable SIMY uploads,
|
|
120
|
+
and cannot use mutation tools or nested delegation. Downloaded bytes are checked
|
|
121
|
+
against the claimed size and SHA-256 digest, then exposed through a mode `0400`
|
|
122
|
+
file without revealing the storage URI to the Provider.
|
|
123
|
+
|
|
124
|
+
Cancellation uses one pool-wide abort signal and prevents new claims. Unknown
|
|
125
|
+
invocation or final-status boundaries are never replayed automatically. Sibling
|
|
126
|
+
fan-in summaries remain explicitly untrusted data, and all lease, generation,
|
|
127
|
+
budget, usage, and elapsed-time bigint fields cross the JSON boundary as
|
|
128
|
+
canonical decimal strings. The contract 9 `durable_local_task_steps` path
|
|
129
|
+
remains serial and unchanged.
|
|
130
|
+
|
|
131
|
+
External side effects such as sending messages, submitting forms, uploading, or
|
|
132
|
+
purchasing are outside this MVP. The router rejects them instead of silently
|
|
133
|
+
granting broad permissions. The legacy `/v1/direct-execution/*` contract remains
|
|
134
|
+
available for older Web clients.
|
|
135
|
+
|
|
47
136
|
## CLI updates
|
|
48
137
|
|
|
49
138
|
The CLI checks the npm registry at startup and once per hour while it is
|
|
@@ -114,6 +203,61 @@ limit. SIMY Web can edit that suggestion and call
|
|
|
114
203
|
`provider_token_budget`. The CLI persists the higher limit and resumes the same
|
|
115
204
|
run. SIMY token consumption remains a separate platform billing record.
|
|
116
205
|
|
|
206
|
+
## SQM local checks
|
|
207
|
+
|
|
208
|
+
SQM deliberately has two identity-bound stages:
|
|
209
|
+
|
|
210
|
+
1. `simy sqm min-check` quickly inspects committed changes, the working tree,
|
|
211
|
+
untracked files, and deletions. It runs only deterministic low-cost rules,
|
|
212
|
+
reports preliminary findings, and writes the applicable state, transition,
|
|
213
|
+
stress, and scenario plan. A passing min-check is not a complete validation.
|
|
214
|
+
2. `simy sqm check` verifies that repository, base, HEAD, working-tree digest,
|
|
215
|
+
and signed bundle still match the min-check. It then evaluates applicable
|
|
216
|
+
state transitions, invariants, stress/strength expectations, and scenarios,
|
|
217
|
+
writes `proof.json`, and signs that proof with the local device identity.
|
|
218
|
+
|
|
219
|
+
Normal runs do not require a separate sync command: the CLI
|
|
220
|
+
uses a verified local cache and revalidates it with TTL and ETag semantics.
|
|
221
|
+
The Agentic Loop runs min-check after each code modification and the full check
|
|
222
|
+
before PR readiness. Findings and the redacted signed-proof summary are recorded
|
|
223
|
+
in its audit; source text is never uploaded.
|
|
224
|
+
|
|
225
|
+
Configure the bundle service with `SIMY_SQM_BUNDLE_URL`. Authentication uses
|
|
226
|
+
the current SIMY session in the coding loop, or `SIMY_SQM_TOKEN`/
|
|
227
|
+
`SIMY_ACCESS_TOKEN` for the diagnostic command. On the first authenticated
|
|
228
|
+
HTTPS request, the CLI receives the bundle verification key from the SIMY
|
|
229
|
+
gateway, verifies the signed bundle, and pins that key to the endpoint,
|
|
230
|
+
account, organization, and repository cache identity for offline use. Explicit
|
|
231
|
+
trust anchors can instead be configured as a JSON key-ID map in
|
|
232
|
+
`SIMY_SQM_PUBLIC_KEYS_JSON`, or as one `SIMY_SQM_KEY_ID` plus
|
|
233
|
+
`SIMY_SQM_PUBLIC_KEY`. Public keys may be PEM, base64 SPKI, or a base64 raw
|
|
234
|
+
32-byte Ed25519 key. Optional settings are:
|
|
235
|
+
|
|
236
|
+
- `SIMY_SQM_CACHE_DIR`: verified bundle cache location.
|
|
237
|
+
- `SIMY_SQM_CACHE_TTL_MS`: revalidation TTL, defaulting to five minutes.
|
|
238
|
+
- `SIMY_SQM_ACCOUNT_ID` and `SIMY_SQM_ORGANIZATION_ID`: tenant identity for
|
|
239
|
+
diagnostic checks. Coding-loop checks receive tenant identity from the
|
|
240
|
+
authenticated session. Cache entries are isolated by endpoint, account,
|
|
241
|
+
organization, and repository, and the organization is verified against the
|
|
242
|
+
signed bundle. `SIMY_SQM_ORGANIZATION_ID` is required for standalone
|
|
243
|
+
diagnostic checks; without a tenant identity SQM fails closed in shadow mode.
|
|
244
|
+
|
|
245
|
+
Use either phase with `--offline` to prohibit network access and `--refresh` to force
|
|
246
|
+
ETag revalidation, `--base <branch>` to select a base branch, and `--json` for
|
|
247
|
+
machine-readable results. Full check additionally accepts `--min-result`,
|
|
248
|
+
`--proof`, `--signed-evidence`, and `--no-upload`. The min result and full proof
|
|
249
|
+
share one pinned signed bundle and one exact repository identity, so a code
|
|
250
|
+
change cannot silently reuse an old preflight. If Cloud is unavailable, the CLI clearly warns and
|
|
251
|
+
uses the last unexpired signature-verified bundle only after a network failure
|
|
252
|
+
or Cloud 5xx response. Authentication, authorization, compatibility,
|
|
253
|
+
signature, schema, tenant, and expiry failures never execute stale knowledge.
|
|
254
|
+
With no verified cache it skips SQM
|
|
255
|
+
in shadow mode. Bundles contain only the fixed declarative checker vocabulary;
|
|
256
|
+
the CLI never executes shell, JavaScript, Python, WASM, or another remotely
|
|
257
|
+
supplied implementation. A module's matcher array has explicit **AND semantics**:
|
|
258
|
+
every matcher must match before any check in that module runs; it is not an OR
|
|
259
|
+
list.
|
|
260
|
+
|
|
117
261
|
## Interactive console
|
|
118
262
|
|
|
119
263
|
Running `simy` in a terminal opens the Agentic Loop chat. It discovers the
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awak-app/simy-cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Local SIMY
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Local SIMY executor for non-coding Local Tasks and Agentic Loop runs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"simy": "src/index.js"
|
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
"start": "node ./src/index.js",
|
|
15
15
|
"test": "node --test",
|
|
16
16
|
"test:e2e:console": "node ./scripts/console-e2e.js",
|
|
17
|
+
"test:e2e:sqm-complete-loop": "node ./scripts/sqm-complete-loop-e2e.js",
|
|
18
|
+
"test:e2e:console:narrow": "CLI_E2E_COLUMNS=78 CLI_E2E_ROWS=40 node ./scripts/console-e2e.js",
|
|
19
|
+
"test:e2e:console:no-color": "CLI_E2E_NO_COLOR=1 node ./scripts/console-e2e.js",
|
|
20
|
+
"test:e2e:console:recovery": "node ./scripts/console-recovery-e2e.js",
|
|
17
21
|
"test:e2e:auto-update": "node ./scripts/auto-update-e2e.js",
|
|
18
22
|
"test:e2e:audit-gate": "node ./scripts/audit-gate-e2e.js",
|
|
19
23
|
"test:e2e:retry-circuit": "node ./scripts/retry-circuit-e2e.js",
|
|
@@ -26,13 +30,16 @@
|
|
|
26
30
|
"test:e2e:budgets": "node ./scripts/budget-enforcement-e2e.js",
|
|
27
31
|
"test:e2e:desktop-executor": "node ./scripts/desktop-executor-e2e.js",
|
|
28
32
|
"test:e2e:pre-guardrail": "node ./scripts/pre-guardrail-e2e.js",
|
|
33
|
+
"test:e2e:local-task-default-workspace": "node ./scripts/local-task-default-workspace-e2e.js",
|
|
34
|
+
"test:e2e:local-task-idempotency": "node ./scripts/local-task-idempotency-e2e.js",
|
|
29
35
|
"test:e2e:completion-contract": "node ./scripts/completion-contract-e2e.js",
|
|
30
36
|
"test:e2e:console:real-provider": "node ./scripts/real-provider-console-e2e.js",
|
|
31
37
|
"test:e2e:console:fullstack": "node ./scripts/fullstack-cli-smoke.js",
|
|
32
|
-
"check": "npm run check:auto-update && node --check ./src/desktop-executor.js && node --check ./scripts/desktop-executor-e2e.js && node --check ./scripts/pre-guardrail-e2e.js && node --check ./scripts/fixtures/fake-desktop-provider.js && npm run check:syntax && npm run check:real-provider-syntax && npm test && npm run check:package",
|
|
33
|
-
"check:auto-update": "node --check ./src/auto-update.js && node --check ./scripts/auto-update-e2e.js",
|
|
38
|
+
"check": "npm run check:auto-update && node --check ./src/desktop-executor.js && node --check ./src/local-task.js && node --check ./scripts/desktop-executor-e2e.js && node --check ./scripts/pre-guardrail-e2e.js && node --check ./scripts/fixtures/fake-desktop-provider.js && npm run check:syntax && npm run check:real-provider-syntax && npm test && npm run check:package",
|
|
39
|
+
"check:auto-update": "node --check ./src/auto-update.js && node --check ./scripts/auto-update-e2e.js && npm run check:sqm",
|
|
40
|
+
"check:sqm": "node --check ./src/sqm/canonical.js && node --check ./src/sqm/validation.js && node --check ./src/sqm/repository.js && node --check ./src/sqm/checkers.js && node --check ./src/sqm/bundle-store.js && node --check ./src/sqm/proof.js && node --check ./src/sqm/evidence-client.js && node --check ./src/sqm/session.js && node --check ./src/sqm/index.js && node --check ./src/sqm/command.js && node --check ./scripts/sqm-complete-loop-e2e.js",
|
|
34
41
|
"check:real-provider-syntax": "node --check ./scripts/real-codex-probe.js && node --check ./scripts/real-claude-probe.js && node --check ./scripts/real-provider-console-fixture.js && node --check ./scripts/real-provider-console-e2e.js",
|
|
35
|
-
"check:syntax": "node --check ./src/index.js && node --check ./src/agent.js && node --check ./src/browser.js && node --check ./src/web-api.js && node --check ./src/run-registry.js && node --check ./src/direct-executor.js && node --check ./src/execution-guardrail.js && node --check ./src/backend-executable.js && node --check ./src/provider-stream.js && node --check ./src/console/index.js && node --check ./src/console/app.js && node --check ./src/console/commands.js && node --check ./src/local-attachments.js && node --check ./src/repository-inventory.js && node --check ./src/session-store.js && node --check ./src/web-origin.js && node --check ./src/workspace-context.js && node --check ./src/orchestrator/index.js && node --check ./src/orchestrator/shared.js && node --check ./src/orchestrator/recovery.js && node --check ./src/orchestrator/risk.js && node --check ./src/orchestrator/contract.js && node --check ./src/orchestrator/completion-contract.js && node --check ./src/orchestrator/instruction.js && node --check ./src/orchestrator/problem-solving.js && node --check ./src/orchestrator/budget.js && node --check ./src/orchestrator/execution-io.js && node --check ./src/orchestrator/presentation.js && node --check ./src/orchestrator/result.js && node --check ./src/orchestrator/retry.js && node --check ./src/orchestrator/evidence.js && node --check ./src/orchestrator/independent-audit.js && node --check ./src/orchestrator/audit.js && node --check ./src/orchestrator/loop.js && node --check ./src/runner.js && node --check ./scripts/fixtures/completion-contract-fixture.js && node --check ./scripts/fixtures/fake-coding-backend.js && node --check ./scripts/e2e-terminal-evidence.js && node --check ./scripts/audit-gate-e2e.js && node --check ./scripts/completion-contract-e2e.js && node --check ./scripts/retry-circuit-e2e.js && node --check ./scripts/follow-up-charter-e2e.js && node --check ./scripts/task-routing-e2e.js && node --check ./scripts/executor-version-preflight-e2e.js && node --check ./scripts/blocked-recovery-e2e.js && node --check ./scripts/process-localization-e2e.js && node --check ./scripts/hypothesis-retries-e2e.js && node --check ./scripts/budget-enforcement-e2e.js && node --check ./scripts/console-e2e-fixture.js && node --check ./scripts/console-e2e.js && node --check ./scripts/real-provider-console-fixture.js && node --check ./scripts/real-provider-console-e2e.js && node --check ./scripts/fullstack-cli-smoke.js && node --check ./scripts/check-package-contents.js",
|
|
42
|
+
"check:syntax": "node --check ./src/index.js && node --check ./src/agent.js && node --check ./src/browser.js && node --check ./src/web-api.js && node --check ./src/durable-local-task-worker.js && node --check ./src/durable-local-task-steps-contract.js && node --check ./src/bounded-local-task-subtasks-contract.js && node --check ./src/bounded-local-task-subtask-pool.js && node --check ./src/local-task-artifact-contract.js && node --check ./src/execution-capability-contract.js && node --check ./src/shutdown.js && node --check ./src/run-registry.js && node --check ./src/direct-executor.js && node --check ./src/execution-guardrail.js && node --check ./src/backend-executable.js && node --check ./src/provider-stream.js && node --check ./src/console/index.js && node --check ./src/console/app.js && node --check ./src/console/commands.js && node --check ./src/local-attachments.js && node --check ./src/repository-inventory.js && node --check ./src/session-store.js && node --check ./src/web-origin.js && node --check ./src/workspace-context.js && node --check ./src/orchestrator/index.js && node --check ./src/orchestrator/shared.js && node --check ./src/orchestrator/recovery.js && node --check ./src/orchestrator/risk.js && node --check ./src/orchestrator/contract.js && node --check ./src/orchestrator/completion-contract.js && node --check ./src/orchestrator/instruction.js && node --check ./src/orchestrator/problem-solving.js && node --check ./src/orchestrator/budget.js && node --check ./src/orchestrator/execution-io.js && node --check ./src/orchestrator/presentation.js && node --check ./src/orchestrator/result.js && node --check ./src/orchestrator/retry.js && node --check ./src/orchestrator/evidence.js && node --check ./src/orchestrator/independent-audit.js && node --check ./src/orchestrator/audit.js && node --check ./src/orchestrator/loop.js && node --check ./src/runner.js && node --check ./scripts/fixtures/completion-contract-fixture.js && node --check ./scripts/fixtures/fake-coding-backend.js && node --check ./scripts/e2e-terminal-evidence.js && node --check ./scripts/audit-gate-e2e.js && node --check ./scripts/completion-contract-e2e.js && node --check ./scripts/retry-circuit-e2e.js && node --check ./scripts/follow-up-charter-e2e.js && node --check ./scripts/task-routing-e2e.js && node --check ./scripts/executor-version-preflight-e2e.js && node --check ./scripts/blocked-recovery-e2e.js && node --check ./scripts/process-localization-e2e.js && node --check ./scripts/hypothesis-retries-e2e.js && node --check ./scripts/budget-enforcement-e2e.js && node --check ./scripts/local-task-default-workspace-e2e.js && node --check ./scripts/local-task-idempotency-e2e.js && node --check ./scripts/console-e2e-fixture.js && node --check ./scripts/console-e2e.js && node --check ./scripts/console-recovery-e2e-fixture.js && node --check ./scripts/console-recovery-e2e.js && node --check ./scripts/real-provider-console-fixture.js && node --check ./scripts/real-provider-console-e2e.js && node --check ./scripts/fullstack-cli-smoke.js && node --check ./scripts/check-package-contents.js",
|
|
36
43
|
"check:package": "node ./scripts/check-package-contents.js"
|
|
37
44
|
},
|
|
38
45
|
"engines": {
|
|
@@ -52,6 +59,8 @@
|
|
|
52
59
|
},
|
|
53
60
|
"dependencies": {
|
|
54
61
|
"ink": "^6.8.0",
|
|
62
|
+
"pdf-lib": "^1.17.1",
|
|
63
|
+
"pngjs": "^7.0.0",
|
|
55
64
|
"react": "^19.2.0"
|
|
56
65
|
},
|
|
57
66
|
"devDependencies": {
|