@com55/node-red-ai-access 0.2.0-beta.4 → 0.2.0-beta.5
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/CHANGELOG.md +58 -0
- package/README.md +93 -9
- package/ai-access.html +1 -1
- package/dist/plugin.cjs +279 -106
- package/dist/plugin.d.cts +17 -2
- package/docs/api/openapi.yaml +2 -0
- package/docs/errors.md +8 -0
- package/docs/mcp-tools.md +2 -2
- package/package.json +1 -1
package/dist/plugin.d.cts
CHANGED
|
@@ -268,6 +268,11 @@ interface Proposal {
|
|
|
268
268
|
* Never blocks approve — AI may scaffold first; humans configure later.
|
|
269
269
|
*/
|
|
270
270
|
warnings?: ProposalWarning[];
|
|
271
|
+
/** Fields whose `[REDACTED]` placeholder was restored to the live secret at submit. */
|
|
272
|
+
restoredSecrets?: {
|
|
273
|
+
nodeId: string;
|
|
274
|
+
property: string;
|
|
275
|
+
}[];
|
|
271
276
|
/**
|
|
272
277
|
* Short human title (≤80 chars). Set at submit (AI-supplied or auto-generated).
|
|
273
278
|
* Optional on legacy proposals; API responses always resolve a title.
|
|
@@ -291,6 +296,10 @@ interface CreateProposalInput {
|
|
|
291
296
|
title: string;
|
|
292
297
|
/** Soft validation notes to persist with the proposal. */
|
|
293
298
|
warnings?: ProposalWarning[];
|
|
299
|
+
restoredSecrets?: {
|
|
300
|
+
nodeId: string;
|
|
301
|
+
property: string;
|
|
302
|
+
}[];
|
|
294
303
|
}
|
|
295
304
|
declare class ProposalStore {
|
|
296
305
|
private readonly paths;
|
|
@@ -355,6 +364,8 @@ interface PersistedAiAccessSettings {
|
|
|
355
364
|
rateLimitWindowMs?: number;
|
|
356
365
|
rateLimitMaxPerIp?: number;
|
|
357
366
|
rateLimitMaxPerToken?: number;
|
|
367
|
+
/** Secret-like env / config names redacted from AI responses (case-insensitive words). */
|
|
368
|
+
secretNamePatterns?: string[];
|
|
358
369
|
oauth?: {
|
|
359
370
|
enabled?: boolean;
|
|
360
371
|
accessTokenTtlSec?: number;
|
|
@@ -374,6 +385,7 @@ interface EffectiveAiAccessSettings {
|
|
|
374
385
|
rateLimitWindowMs: number;
|
|
375
386
|
rateLimitMaxPerIp: number;
|
|
376
387
|
rateLimitMaxPerToken: number;
|
|
388
|
+
secretNamePatterns: string[];
|
|
377
389
|
oauth: {
|
|
378
390
|
enabled: boolean;
|
|
379
391
|
accessTokenTtlSec: number;
|
|
@@ -401,8 +413,11 @@ declare class SettingsStore {
|
|
|
401
413
|
* disk override and fall back to settings.js / default).
|
|
402
414
|
*/
|
|
403
415
|
update(partial: PersistedAiAccessSettings): EffectiveAiAccessSettingsWithMeta;
|
|
404
|
-
/**
|
|
405
|
-
|
|
416
|
+
/**
|
|
417
|
+
* Merge into existing disk overrides (only provided keys change). Keys in
|
|
418
|
+
* `reset` are removed from disk so they fall back to settings.js / default.
|
|
419
|
+
*/
|
|
420
|
+
patch(partial: PersistedAiAccessSettings, reset?: readonly (keyof PersistedAiAccessSettings)[]): EffectiveAiAccessSettingsWithMeta;
|
|
406
421
|
private persist;
|
|
407
422
|
}
|
|
408
423
|
|
package/docs/api/openapi.yaml
CHANGED
|
@@ -1505,6 +1505,7 @@ components:
|
|
|
1505
1505
|
- `chunk_conflict` (409): Same draft seq re-sent with different data
|
|
1506
1506
|
- `missing_chunks` (400): Draft submit with gaps in seq
|
|
1507
1507
|
- `draft_hash_mismatch` (400): Draft sha256 does not match assembled bytes
|
|
1508
|
+
- `redacted_placeholder_mismatch` (400): A `[REDACTED]` placeholder was added, duplicated, moved, or its env/header name changed
|
|
1508
1509
|
- `upstream_error` (502): Node-RED runtime/flows error
|
|
1509
1510
|
- `internal_error` (500): Unexpected server error
|
|
1510
1511
|
enum:
|
|
@@ -1557,6 +1558,7 @@ components:
|
|
|
1557
1558
|
- chunk_conflict
|
|
1558
1559
|
- missing_chunks
|
|
1559
1560
|
- draft_hash_mismatch
|
|
1561
|
+
- redacted_placeholder_mismatch
|
|
1560
1562
|
- upstream_error
|
|
1561
1563
|
- internal_error
|
|
1562
1564
|
# END GENERATED ERROR CODES
|
package/docs/errors.md
CHANGED
|
@@ -62,6 +62,7 @@ GET-link `401` responses include a `WWW-Authenticate: Bearer …` header.
|
|
|
62
62
|
| `chunk_conflict` | 409 | Same draft seq re-sent with different data | Re-send identical data or start a new draft | GET |
|
|
63
63
|
| `missing_chunks` | 400 | Draft submit with gaps in seq | Upload every seq from 0 through max | GET |
|
|
64
64
|
| `draft_hash_mismatch` | 400 | Draft sha256 does not match assembled bytes | Send the hex sha256 of the assembled UTF-8 | GET |
|
|
65
|
+
| `redacted_placeholder_mismatch` | 400 | A `[REDACTED]` placeholder was added, duplicated, moved, or its env/header name changed | Keep placeholders exactly where they were shown (same line, same name) or supply a real value | GET, REST, MCP |
|
|
65
66
|
| `upstream_error` | 502 | Node-RED runtime/flows error | Retry; check Node-RED logs | GET, REST, MCP |
|
|
66
67
|
| `internal_error` | 500 | Unexpected server error | Retry; check Node-RED logs | GET, REST, MCP |
|
|
67
68
|
|
|
@@ -74,6 +75,13 @@ Returned in `warnings[]` on a successful propose/submit; they never block.
|
|
|
74
75
|
| `missing_config_node` | 201 | Warning: node has no (or an unresolved) config node yet | Configure before deploy if needed; see `candidates` | GET, REST, MCP |
|
|
75
76
|
| `unwired_node` | 201 | Warning: node has outputs but no wires | Wire it, or ignore while scaffolding | GET, REST, MCP |
|
|
76
77
|
| `incomplete_wires` | 201 | Warning: fewer wire ports than outputs | Add ports if outputs should connect | GET, REST, MCP |
|
|
78
|
+
| `secret_destination_changed` | 201 | Warning: a node holding a restored secret changed where it sends data (url/host/method/headers/…) | Reviewer must verify the new destination before approving | GET, REST, MCP |
|
|
79
|
+
| `secret_node_code_changed` | 201 | Warning: a node holding a restored secret had its code changed | Reviewer must check the code does not send the secret elsewhere | GET, REST, MCP |
|
|
80
|
+
| `secret_wires_changed` | 201 | Warning: a node holding a restored secret had its output wires changed | Reviewer must check where its messages now go | GET, REST, MCP |
|
|
81
|
+
| `secret_scope_changed` | 201 | Warning: tab/group env or a config node scoping a secret-holding node changed | Reviewer must check env-resolved hosts/URLs (e.g. `${API_HOST}`) | GET, REST, MCP |
|
|
82
|
+
| `outbound_node_changed` | 201 | Warning: proposal adds/changes an outbound-capable node (http request/response, mqtt, tcp, udp, email, websocket, link out/call, function, exec, file, or any node with url/host fields) | Reviewer must check it cannot send secret data elsewhere | GET, REST, MCP |
|
|
83
|
+
| `secret_tab_changed` | 201 | Warning: proposal with restored secrets also changes other nodes in the tab | Review every change before approving | GET, REST, MCP |
|
|
84
|
+
| `secret_reference_added` | 201 | Warning: an added/changed node now reads a secret-named env/global/flow value (env.get, $env, ${…}, typed input) | Reviewer must check the value is not sent anywhere unexpected | GET, REST, MCP |
|
|
77
85
|
|
|
78
86
|
## Auto-closed proposal statuses
|
|
79
87
|
|
package/docs/mcp-tools.md
CHANGED
|
@@ -69,7 +69,7 @@ _No input parameters._
|
|
|
69
69
|
|
|
70
70
|
## `list_flows`
|
|
71
71
|
|
|
72
|
-
List all flows as a flat Admin API v2 array plus the current rev string. Returns { rev, flows }. Call this (or get_flow) before submit_proposal so expectedRev matches.
|
|
72
|
+
List all flows as a flat Admin API v2 array plus the current rev string. Likely secrets are shown as "[REDACTED]" (nodes list redacted paths in _aiRedactions). Returns { rev, flows }. Call this (or get_flow) before submit_proposal so expectedRev matches.
|
|
73
73
|
|
|
74
74
|
_No input parameters._
|
|
75
75
|
|
|
@@ -126,7 +126,7 @@ Search the public Node-RED catalogue for modules to recommend. Returns module id
|
|
|
126
126
|
|
|
127
127
|
## `submit_proposal`
|
|
128
128
|
|
|
129
|
-
Submit a replace_flow proposal for owner approval (does not deploy). Preferred for small string edits: payload: { flowId, nodes: [{ op:"replace_text", node, field, find, replace, occurrence? }] } — find must be unique unless occurrence (1-based) is set; multiple replace_text ops apply in order; yields a short readable diff. Or send a full tab: payload.flow from get_flow (id, type, label?, nodes[], configs?). Inputs (all top-level, next to each other): type="replace_flow", expectedRev (required string from list_flows/get_flow rev; expected_rev alias accepted), optional title (≤80 chars), and payload: { flowId, flow? } and/or payload.nodes / top-level nodes. Do not nest expectedRev inside payload. Payload size limit is 1500000 bytes (413 if exceeded). expectedRev is checked against the live rev at submit time (409 if stale). replace_text errors: 400 text_not_found; 409 ambiguous_match with matchCount. Unknown palette types return 400 unknown_node_type with nearest matches — call list_node_types / search_palette and ask the user to install via Manage palette (never auto-install). Returns a lean proposal (id, status, title, storedTitle, flowLabel, displayName, reviewUrl, changeSummary, …) by default; title may gain " in <flow>"; storedTitle is the title as saved (your title without that suffix, or the auto-generated title, which may already name the flow). Pass include_payload=true to include payload and baseFlow. When telling the user about the proposal, cite displayName and reviewUrl — not the raw id. Humans approve on the /ai-access dashboard (reviewUrl opens/scrolls to it).
|
|
129
|
+
Submit a replace_flow proposal for owner approval (does not deploy). Preferred for small string edits: payload: { flowId, nodes: [{ op:"replace_text", node, field, find, replace, occurrence? }] } — find must be unique unless occurrence (1-based) is set; multiple replace_text ops apply in order; yields a short readable diff. Or send a full tab: payload.flow from get_flow (id, type, label?, nodes[], configs?). Inputs (all top-level, next to each other): type="replace_flow", expectedRev (required string from list_flows/get_flow rev; expected_rev alias accepted), optional title (≤80 chars), and payload: { flowId, flow? } and/or payload.nodes / top-level nodes. Do not nest expectedRev inside payload. Secret values appear as "[REDACTED]" in reads; leave the placeholder unchanged to keep the stored secret (it is restored on submit), or replace it with a new value to change it. Payload size limit is 1500000 bytes (413 if exceeded). expectedRev is checked against the live rev at submit time (409 if stale). replace_text errors: 400 text_not_found; 409 ambiguous_match with matchCount. Unknown palette types return 400 unknown_node_type with nearest matches — call list_node_types / search_palette and ask the user to install via Manage palette (never auto-install). Returns a lean proposal (id, status, title, storedTitle, flowLabel, displayName, reviewUrl, changeSummary, …) by default; title may gain " in <flow>"; storedTitle is the title as saved (your title without that suffix, or the auto-generated title, which may already name the flow). Pass include_payload=true to include payload and baseFlow. When telling the user about the proposal, cite displayName and reviewUrl — not the raw id. Humans approve on the /ai-access dashboard (reviewUrl opens/scrolls to it).
|
|
130
130
|
|
|
131
131
|
| Parameter | Required | Type | Description |
|
|
132
132
|
| --- | --- | --- | --- |
|
package/package.json
CHANGED