@n8n/instance-ai 1.23.2 → 1.24.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.
Files changed (143) hide show
  1. package/dist/agent/instance-agent.js +5 -2
  2. package/dist/agent/instance-agent.js.map +1 -1
  3. package/dist/agent/system-prompt.d.ts +1 -0
  4. package/dist/agent/system-prompt.js +15 -1
  5. package/dist/agent/system-prompt.js.map +1 -1
  6. package/dist/build.tsbuildinfo +1 -1
  7. package/dist/error-formatting.js +3 -7
  8. package/dist/error-formatting.js.map +1 -1
  9. package/dist/errors/folder-resolution.error.d.ts +6 -0
  10. package/dist/errors/folder-resolution.error.js +13 -0
  11. package/dist/errors/folder-resolution.error.js.map +1 -0
  12. package/dist/errors/workflow-snapshot-changed.error.d.ts +4 -0
  13. package/dist/errors/workflow-snapshot-changed.error.js +11 -0
  14. package/dist/errors/workflow-snapshot-changed.error.js.map +1 -0
  15. package/dist/index.d.ts +9 -2
  16. package/dist/index.js +19 -3
  17. package/dist/index.js.map +1 -1
  18. package/dist/knowledge-base/extract-builder-templates-archive.js +2 -4
  19. package/dist/knowledge-base/extract-builder-templates-archive.js.map +1 -1
  20. package/dist/runtime/background-task-manager.d.ts +3 -1
  21. package/dist/runtime/background-task-manager.js +15 -1
  22. package/dist/runtime/background-task-manager.js.map +1 -1
  23. package/dist/runtime/liveness-policy.js.map +1 -1
  24. package/dist/runtime/resumable-stream-executor.d.ts +1 -2
  25. package/dist/runtime/resumable-stream-executor.js +4 -17
  26. package/dist/runtime/resumable-stream-executor.js.map +1 -1
  27. package/dist/runtime/run-state-registry.d.ts +4 -0
  28. package/dist/runtime/run-state-registry.js +18 -0
  29. package/dist/runtime/run-state-registry.js.map +1 -1
  30. package/dist/runtime/stream-runner.d.ts +0 -2
  31. package/dist/runtime/stream-runner.js +0 -1
  32. package/dist/runtime/stream-runner.js.map +1 -1
  33. package/dist/storage/agent-tree-snapshot.d.ts +0 -4
  34. package/dist/stream/consume-with-hitl.d.ts +0 -3
  35. package/dist/stream/consume-with-hitl.js +0 -2
  36. package/dist/stream/consume-with-hitl.js.map +1 -1
  37. package/dist/tools/conversation-history.schema.d.ts +231 -0
  38. package/dist/tools/conversation-history.schema.js +36 -0
  39. package/dist/tools/conversation-history.schema.js.map +1 -0
  40. package/dist/tools/conversation-history.tool.d.ts +2 -0
  41. package/dist/tools/conversation-history.tool.js +135 -0
  42. package/dist/tools/conversation-history.tool.js.map +1 -0
  43. package/dist/tools/credentials.tool.d.ts +3 -0
  44. package/dist/tools/credentials.tool.js +65 -0
  45. package/dist/tools/credentials.tool.js.map +1 -1
  46. package/dist/tools/data-tables.tool.js +59 -14
  47. package/dist/tools/data-tables.tool.js.map +1 -1
  48. package/dist/tools/evals/eval-config.tool.js +3 -5
  49. package/dist/tools/evals/eval-config.tool.js.map +1 -1
  50. package/dist/tools/index.js +12 -0
  51. package/dist/tools/index.js.map +1 -1
  52. package/dist/tools/mcp-servers.tool.js +1 -1
  53. package/dist/tools/mcp-servers.tool.js.map +1 -1
  54. package/dist/tools/n8n-docs/registry.d.ts +0 -1
  55. package/dist/tools/n8n-docs/registry.js +2 -5
  56. package/dist/tools/n8n-docs/registry.js.map +1 -1
  57. package/dist/tools/n8n-docs.tool.js +2 -1
  58. package/dist/tools/n8n-docs.tool.js.map +1 -1
  59. package/dist/tools/nodes/credential-setupability.json +1792 -0
  60. package/dist/tools/nodes/setup-preference.d.ts +9 -0
  61. package/dist/tools/nodes/setup-preference.js +23 -0
  62. package/dist/tools/nodes/setup-preference.js.map +1 -0
  63. package/dist/tools/nodes.tool.js +22 -9
  64. package/dist/tools/nodes.tool.js.map +1 -1
  65. package/dist/tools/orchestration/agent-target-binding.d.ts +6 -0
  66. package/dist/tools/orchestration/agent-target-binding.js +56 -32
  67. package/dist/tools/orchestration/agent-target-binding.js.map +1 -1
  68. package/dist/tools/orchestration/build-agent.tool.js +20 -3
  69. package/dist/tools/orchestration/build-agent.tool.js.map +1 -1
  70. package/dist/tools/orchestration/eval-setup-agent.tool.js +0 -1
  71. package/dist/tools/orchestration/eval-setup-agent.tool.js.map +1 -1
  72. package/dist/tools/orchestration/list-agent-capabilities.tool.d.ts +2 -0
  73. package/dist/tools/orchestration/list-agent-capabilities.tool.js +45 -0
  74. package/dist/tools/orchestration/list-agent-capabilities.tool.js.map +1 -0
  75. package/dist/tools/orchestration/verification/prepare-run.d.ts +1 -1
  76. package/dist/tools/orchestration/verification/prepare-run.js +32 -37
  77. package/dist/tools/orchestration/verification/prepare-run.js.map +1 -1
  78. package/dist/tools/orchestration/verification/types.d.ts +1 -0
  79. package/dist/tools/orchestration/verify-built-workflow.tool.d.ts +3 -0
  80. package/dist/tools/orchestration/verify-built-workflow.tool.js +8 -2
  81. package/dist/tools/orchestration/verify-built-workflow.tool.js.map +1 -1
  82. package/dist/tools/tool-ids.d.ts +2 -0
  83. package/dist/tools/tool-ids.js +4 -0
  84. package/dist/tools/tool-ids.js.map +1 -1
  85. package/dist/tools/workflows/build-workflow.tool.d.ts +32 -0
  86. package/dist/tools/workflows/build-workflow.tool.js +140 -29
  87. package/dist/tools/workflows/build-workflow.tool.js.map +1 -1
  88. package/dist/tools/workflows/generate-simulation-fixtures.service.d.ts +6 -0
  89. package/dist/tools/workflows/generate-simulation-fixtures.service.js +119 -14
  90. package/dist/tools/workflows/generate-simulation-fixtures.service.js.map +1 -1
  91. package/dist/tools/workflows/plan-verification-simulation.js +21 -2
  92. package/dist/tools/workflows/plan-verification-simulation.js.map +1 -1
  93. package/dist/tools/workflows/preserve-node-positions.js +33 -9
  94. package/dist/tools/workflows/preserve-node-positions.js.map +1 -1
  95. package/dist/tools/workflows/setup-items.d.ts +23 -0
  96. package/dist/tools/workflows/setup-items.js +154 -0
  97. package/dist/tools/workflows/setup-items.js.map +1 -0
  98. package/dist/tools/workflows/summarize-workflow.d.ts +4 -1
  99. package/dist/tools/workflows/summarize-workflow.js +8 -2
  100. package/dist/tools/workflows/summarize-workflow.js.map +1 -1
  101. package/dist/tools/workflows/workflow-build-remediation.js +3 -2
  102. package/dist/tools/workflows/workflow-build-remediation.js.map +1 -1
  103. package/dist/tools/workflows/workflow-build-telemetry.d.ts +1 -1
  104. package/dist/tools/workflows/workflow-build-telemetry.js.map +1 -1
  105. package/dist/tools/workflows/workflow-file-bindings.d.ts +1 -0
  106. package/dist/tools/workflows/workflow-file-bindings.js +13 -1
  107. package/dist/tools/workflows/workflow-file-bindings.js.map +1 -1
  108. package/dist/tools/workflows/workflow-source-compiler.d.ts +1 -0
  109. package/dist/tools/workflows/workflow-source-compiler.js +1 -0
  110. package/dist/tools/workflows/workflow-source-compiler.js.map +1 -1
  111. package/dist/tools/workflows/workflow-source-materializer.d.ts +28 -0
  112. package/dist/tools/workflows/workflow-source-materializer.js +98 -0
  113. package/dist/tools/workflows/workflow-source-materializer.js.map +1 -0
  114. package/dist/tools/workflows.tool.d.ts +1 -1
  115. package/dist/tools/workflows.tool.js +195 -23
  116. package/dist/tools/workflows.tool.js.map +1 -1
  117. package/dist/tools/workspace.tool.js +8 -3
  118. package/dist/tools/workspace.tool.js.map +1 -1
  119. package/dist/tracing/langsmith-tracing.js +3 -5
  120. package/dist/tracing/langsmith-tracing.js.map +1 -1
  121. package/dist/tracing/trace-payloads.js +4 -5
  122. package/dist/tracing/trace-payloads.js.map +1 -1
  123. package/dist/types.d.ts +92 -7
  124. package/dist/types.js +3 -1
  125. package/dist/types.js.map +1 -1
  126. package/dist/utils/model-config-id.d.ts +1 -0
  127. package/dist/utils/model-config-id.js +24 -0
  128. package/dist/utils/model-config-id.js.map +1 -0
  129. package/dist/utils/node-keyed-items.d.ts +1 -0
  130. package/dist/utils/node-keyed-items.js +10 -0
  131. package/dist/utils/node-keyed-items.js.map +1 -0
  132. package/dist/workflow-loop/guidance.js +1 -1
  133. package/dist/workflow-loop/guidance.js.map +1 -1
  134. package/dist/workspace/sandbox-setup.js +4 -6
  135. package/dist/workspace/sandbox-setup.js.map +1 -1
  136. package/package.json +12 -12
  137. package/skills/agent-builder/SKILL.md +23 -0
  138. package/skills/data-table-manager/SKILL.md +34 -3
  139. package/skills/intent-recognition/SKILL.md +55 -0
  140. package/skills/workflow-builder/SKILL.md +111 -27
  141. package/dist/stream/output-redaction.d.ts +0 -31
  142. package/dist/stream/output-redaction.js +0 -191
  143. package/dist/stream/output-redaction.js.map +0 -1
@@ -34,12 +34,17 @@ You are an expert n8n workflow builder. You generate complete, valid
34
34
  TypeScript code using `@n8n/workflow-sdk` for new workflows and for existing
35
35
  saved workflow changes.
36
36
 
37
- Always write the complete TypeScript SDK source with
37
+ For a new workflow, write the complete TypeScript SDK source with
38
38
  `workspace_write_file` first, then call `build-workflow({ filePath })`. For
39
39
  existing saved workflow edits, call `workflows(action="get-as-code",
40
- workflowId)`, apply the edit to the returned code, write it to the file, then
41
- call `build-workflow({ filePath, workflowId })` the first time all edits go
42
- through a workspace source file and `build-workflow`. Do not load
40
+ workflowId)`: it writes the current source to a bound workspace file
41
+ (`src/workflows/<name>.workflow.ts`) and returns the `filePath` plus a `nodes`
42
+ index with line numbers. Locate the target node from the index, read only the
43
+ lines you need, apply the edit with `workspace_str_replace_file`, then call
44
+ `build-workflow({ filePath })` — the file is already bound, so no `workflowId`
45
+ is needed. Never re-emit the whole source with `workspace_write_file`, and do
46
+ not fetch the same unchanged workflow again in another format. All edits go
47
+ through the workspace source file and `build-workflow`. Do not load
43
48
  `planning` or call `create-tasks` first; `planning` is only for coordinated
44
49
  multi-artifact work per the orchestrator routing rules. Do not create a plan
45
50
  just for verification.
@@ -60,11 +65,12 @@ editing anything — never guess at the cause or change the node on a hunch.
60
65
 
61
66
  When called with failure details for an existing workflow, start from the
62
67
  workspace source file if one is available in the conversation or tool output. If
63
- you only have a saved n8n workflow ID, use `workflows(action="get-as-code")`,
64
- make the smallest requested edit to the returned code, write it to a stable
65
- `src/workflows/<name>.workflow.ts` path, then call `build-workflow` once with
66
- `filePath` and `workflowId`. Later repairs should reuse the same `filePath`;
67
- `build-workflow` remembers the bound workflow ID.
68
+ you only have a saved n8n workflow ID, use `workflows(action="get-as-code")`:
69
+ it writes the source to a bound `src/workflows/<name>.workflow.ts` file and
70
+ returns its `filePath` with a node index. Make the smallest requested edit in
71
+ that file with `workspace_str_replace_file`, then call `build-workflow` with the
72
+ `filePath`. Later repairs reuse the same `filePath`; `build-workflow` remembers
73
+ the bound workflow ID.
68
74
 
69
75
  For repairs, prefer editing the workspace file directly with file tools
70
76
  (`workspace_str_replace_file`) and calling `build-workflow` again with the same
@@ -197,9 +203,9 @@ follow its build → publish → assign steps.
197
203
  `src/workflows/main.workflow.ts` for a one-off new workflow, or a clearly
198
204
  named `.workflow.ts` file when multiple source files are useful. For an
199
205
  existing workflow with no source file in context, call
200
- `workflows(action="get-as-code", workflowId)`, apply your edit to the
201
- returned code, and pass the n8n `workflowId` only on the first
202
- `build-workflow` call.
206
+ `workflows(action="get-as-code", workflowId)` and use the `filePath` it
207
+ returns the file is written and bound for you. Edit it in place; do not
208
+ rewrite it.
203
209
  6. Produce complete TypeScript SDK code and write it with
204
210
  `workspace_write_file` (new/full rewrite) or `workspace_str_replace_file`
205
211
  (targeted edit). Do not put secrets in the source file.
@@ -225,6 +231,15 @@ follow its build → publish → assign steps.
225
231
  For planned build follow-ups where `buildTask.isSupportingWorkflow === true`,
226
232
  pass `isSupportingWorkflow: true`; that saved supporting workflow is the
227
233
  task's final deliverable.
234
+ When the tool offers `folderPath` and the new workflow has a home — the user
235
+ named a folder, or you chose one from the project's folders because the
236
+ related workflows live there — pass it on the create call, named the way the
237
+ user named it (`Clients/Acme`, `Acme`). The workflow is created inside that
238
+ folder; a folder that does not resolve fails the build before anything is
239
+ saved and lists the real folders, so retry with one of those or ask the user.
240
+ Never leave a workflow at the project root when its place was already clear.
241
+ `folderPath` is for new workflows only; move an existing one with
242
+ `workspace(action="move-workflow-to-folder")`.
228
243
  9. Trace wiring before declaring done. For IF, Switch, Merge, AI-agent, loop, or
229
244
  multi-workflow wiring, trace each branch from source to target. Confirm IF
230
245
  branches are wired on the workflow builder (`.to(ifNode).onTrue(...).onFalse(...)`
@@ -239,10 +254,14 @@ follow its build → publish → assign steps.
239
254
  `workflow-sdk validate` on that file, then calling `build-workflow` again
240
255
  with the same `filePath`. Save again before any verification step.
241
256
  11. Modify existing workflows by editing the workspace `.workflow.ts` source
242
- file. If the file was created from `workflows(action="get-as-code")`, pass
243
- the real n8n `workflowId` on the first `build-workflow` call so the file is
244
- bound to the saved workflow. Never pass local SDK workflow IDs as n8n
257
+ file with scoped replacements. A file created by
258
+ `workflows(action="get-as-code")` is already bound to the saved workflow;
259
+ pass the real n8n `workflowId` on the first `build-workflow` call only when
260
+ you wrote the file yourself. Never pass local SDK workflow IDs as n8n
245
261
  workflow IDs.
262
+ If you know the workflow's folder (from a `list` result's `folder`), call
263
+ `workflows(action="list", folderPath)` to read its sibling workflows before
264
+ editing. Match the project's existing naming, node choices, and structure.
246
265
  12. After a successful direct `build-workflow` result, if the tool output
247
266
  contains `postBuildFlow.required: true`, follow the inlined
248
267
  `postBuildFlow.instructions` from that output (do not load `post-build-flow`
@@ -269,9 +288,12 @@ Use the current turn's higher-priority instructions to decide who verifies:
269
288
  successful `build-workflow`. The checkpoint task owns verification.
270
289
 
271
290
  Build/save success is not workflow-quality evidence. When this turn is
272
- responsible for verification or repair, inspect the persisted workflow
273
- (`workflows(action="get-as-code", workflowId)` or the bound workspace source
274
- file) before reporting a verdict, judging the saved graph against the user's
291
+ responsible for verification or repair, inspect the persisted workflow before
292
+ reporting a verdict: read the bound workspace source file you just built, or call
293
+ `workflows(action="get-as-code", workflowId)` when the workflow may have changed
294
+ outside this conversation (it reports whether the file is still current, refreshes
295
+ it when the saved workflow changed, and returns `conflict` when the file holds
296
+ unbuilt edits — build or discard those first). Judge the saved graph against the user's
275
297
  requested outcome — not a hidden service-specific checklist. If it is a
276
298
  draft, misses the outcome, or the evidence is weak, edit the same source file,
277
299
  rebuild with the same `filePath`, then inspect and verify again.
@@ -343,10 +365,17 @@ decision after testing.
343
365
  that the credential (or Gateway credits) is being used.
344
366
  - Never use raw credential objects like `{ id: '...', name: '...' }` in SDK
345
367
  code; replace them with `newCredential()` when editing roundtripped code.
346
- - If a required credential type is not listed, call
347
- `credentials(action="search-types")` with the service name. Pick in this
348
- order:
368
+ - `credentials(action="list")` returns connected credential instances, not all
369
+ supported credential types. If it has no suitable instance for a named
370
+ service, call `credentials(action="search-types")` with the service name
371
+ before choosing generic authentication. Pick in this order:
349
372
  1. A **dedicated credential type** whenever search finds one.
373
+ For an HTTP Request node, use the most specific type for the target service
374
+ and operation. Set `authentication` to `'predefinedCredentialType'` and
375
+ `nodeCredentialType` to the returned type. If no credential instance
376
+ exists, leave `newCredential('Suggested Name')` unresolved for setup. Do
377
+ not use generic authentication only because the user has not connected an
378
+ account.
350
379
  2. **Simplified Custom Auth** (`httpTemplatedCustomAuth`) for any service
351
380
  without a dedicated type whose auth is expressible as header/query/body
352
381
  values — this covers API keys and bearer tokens. When the provider
@@ -384,6 +413,41 @@ decision after testing.
384
413
  - Always declare `output` on nodes that use unresolved credentials when mock
385
414
  data is needed for verification.
386
415
 
416
+ ## Credential Setup Preference
417
+
418
+ Discovery results can include a `setupPreference` array. Each entry has:
419
+
420
+ - `type`, the credential type
421
+ - `setupCompletionPercent`, a percentage from 0 to 100 rounded to the nearest
422
+ 5 percentage points, or `null`
423
+ - `popularityScore`, a relative adoption score from 0 to 1 rounded to one
424
+ decimal place, or `null`
425
+
426
+ Setup completion measures completion of an Instance AI setup step containing
427
+ the credential; it is not an activation or validity rate. For either metric,
428
+ `null` means there was not enough data. Popularity is relative recent adoption,
429
+ not a percentage. Treat both as coarse signals and ignore small differences.
430
+
431
+ When choosing a service:
432
+
433
+ 1. Honor explicit intent and existing workflow choices.
434
+ 2. Prefer a semantically suitable service with a usable existing credential,
435
+ then apply the existing Gateway credits rules.
436
+ 3. Compare setup preference only among the remaining semantically
437
+ interchangeable candidates. Before deciding, inspect discovery results for
438
+ every candidate the user named.
439
+
440
+ - When setup completion and popularity clearly support one candidate, choose it
441
+ and continue without asking.
442
+ - When the signals are close or conflict and the user has not delegated the
443
+ choice, ask exactly one `single` question. If skipped, choose a sensible default.
444
+ - When the user explicitly asks you to choose, make a sensible choice and
445
+ continue without asking.
446
+
447
+ Use judgment instead of calculating a combined score or applying a fixed
448
+ threshold. Never let this metadata override stronger semantic relevance or use
449
+ it to choose between authentication methods for the same service.
450
+
387
451
  ## Gateway credits Preference
388
452
 
389
453
  "Gateway credits" is the user-facing name of n8n's managed credential
@@ -485,6 +549,25 @@ via `load_skill` first (if not already loaded this turn), then follow that
485
549
  skill for schema/row guidance. Create or inspect tables directly with
486
550
  `data-tables`; do not invent table IDs, table names, or column names.
487
551
 
552
+ When diagnosing why a workflow's table lookup misses, keep every `data-tables`
553
+ query targeted: filter on the column under investigation (`ilike` for
554
+ case-insensitive partial matches; `like` is case-sensitive) with `limit` of 5
555
+ or fewer. Never pull a table unfiltered — rows can carry very large values
556
+ (inline base64 images, raw payloads), and a filter that matches every row
557
+ (`stock gte 0`) is an unfiltered pull. Results include the total matching
558
+ `count`, so `limit: 1` answers "does this table/filter match anything"; to see
559
+ stored values, sample at most 5 rows. After a 0-row or failed query, retry
560
+ only strictly narrower or switch to a different diagnostic step — a targeted
561
+ query returning 0 rows is evidence about the match condition (commonly an `eq`
562
+ condition against free-form input where only `ilike` — case-insensitive
563
+ contains — reliably matches user-typed text), not proof the data is missing.
564
+ Equal-breadth variants count as re-issues: swapping to a different always-true
565
+ column is the same query, and chasing casing with `like` is wasted turns — use
566
+ `ilike` once instead. Two targeted 0-row probes are enough evidence — stop
567
+ querying and fix the logic. When the user has confirmed the row exists, never
568
+ conclude the data is missing or stored elsewhere; state the matching-logic
569
+ cause, apply the fix, and ask them to re-test.
570
+
488
571
  When the ask is a summary, digest, or report over a period ("weekly summary of
489
572
  what was recorded", "digest of this week's rows"), the summary branch must
490
573
  read that period's rows back from where the workflow logs them (Data Table,
@@ -524,10 +607,11 @@ every reported error and warning before calling `build-workflow`.
524
607
  `{{ }}`. `$json` is only the current item from the immediate predecessor.
525
608
  - Use string values directly for discriminator fields like `resource` and
526
609
  `operation`, for example `resource: 'message'`.
527
- - When editing a pre-loaded workflow, remove every `position` array from node
528
- configs and from `sticky()` options alike. Positions are auto-calculated, and
529
- the saved workflow's own layout is restored on save, so nothing you drop here
530
- is lost. Leaving some in place is worse than dropping all of them.
610
+ - When editing a saved workflow, leave layout alone. The source `get-as-code`
611
+ writes carries no `position` arrays: the saved layout is restored on save by
612
+ node `id`, and nodes you add are placed by the layout engine. Do not add a
613
+ `position` to any node, and never run a whole-file substitution (for example
614
+ `sed`) over the source to change layout.
531
615
  - When editing a pre-loaded workflow, keep every `config.id` value **exactly** as
532
616
  `get-as-code` produced it, on the node it came with. `id` is the node's
533
617
  permanent identity in n8n — execution logs, poll cursors, deduplication state
@@ -535,8 +619,8 @@ every reported error and warning before calling `build-workflow`.
535
619
  Move it, rewire it, change its parameters — the `id` stays. Never invent, edit,
536
620
  renumber or reuse an `id`, and never copy one from a template, another workflow
537
621
  or another node. **Omit `id` entirely for any node you are adding** — one is
538
- assigned on save. Deleting a node means deleting its `id` line with it. This is
539
- the opposite of `position`: drop every `position`, keep every `id`.
622
+ assigned on save. Deleting a node means deleting its `id` line with it. Like
623
+ `position`, `id` is saved state: never write one by hand.
540
624
  - Use `placeholder('hint')` directly as the parameter value. Do not wrap
541
625
  placeholders in `expr()`, objects, or arrays unless the node definition
542
626
  explicitly expects an object and the placeholder is the direct value of one
@@ -1,31 +0,0 @@
1
- import { type RedactionOptions } from '@n8n/agents';
2
- import type { InstanceAiEvent } from '@n8n/api-types';
3
- import type { Logger } from '../logger';
4
- export declare const DEFAULT_OUTPUT_REDACTION_OPTIONS: RedactionOptions;
5
- interface OutputRedactorContext {
6
- logger: Logger;
7
- threadId: string;
8
- runId: string;
9
- agentId: string;
10
- options?: RedactionOptions | false;
11
- }
12
- export declare class OutputRedactor {
13
- private readonly context;
14
- private readonly enabled;
15
- private readonly options;
16
- private readonly text;
17
- private readonly reasoning;
18
- private matches;
19
- constructor(context: OutputRedactorContext);
20
- processEvent(event: InstanceAiEvent): InstanceAiEvent[];
21
- flush(): InstanceAiEvent[];
22
- private processDelta;
23
- private drainChannel;
24
- private makeDelta;
25
- private redactStructural;
26
- private redactConfirmation;
27
- private redactString;
28
- private recordMatches;
29
- private logSummary;
30
- }
31
- export {};
@@ -1,191 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.OutputRedactor = exports.DEFAULT_OUTPUT_REDACTION_OPTIONS = void 0;
4
- const agents_1 = require("@n8n/agents");
5
- const is_record_1 = require("@n8n/utils/is-record");
6
- exports.DEFAULT_OUTPUT_REDACTION_OPTIONS = {
7
- secrets: true,
8
- detect: ['credit-card'],
9
- };
10
- const MAX_TARGET_APPROVAL_ARG_DEPTH = 8;
11
- const WITHHELD_TARGET_APPROVAL_ARG = '[REDACTED]';
12
- function withholdDeepTargetApprovalArgs(value, depth = 0) {
13
- if (value === null || typeof value !== 'object')
14
- return value;
15
- if (depth >= MAX_TARGET_APPROVAL_ARG_DEPTH)
16
- return WITHHELD_TARGET_APPROVAL_ARG;
17
- if (Array.isArray(value)) {
18
- return value.map((item) => withholdDeepTargetApprovalArgs(item, depth + 1));
19
- }
20
- return Object.fromEntries(Object.entries(value).map(([key, item]) => [
21
- key,
22
- withholdDeepTargetApprovalArgs(item, depth + 1),
23
- ]));
24
- }
25
- class OutputRedactor {
26
- context;
27
- enabled;
28
- options;
29
- text;
30
- reasoning;
31
- matches = [];
32
- constructor(context) {
33
- this.context = context;
34
- this.enabled = context.options !== false;
35
- this.options =
36
- context.options === false || context.options === undefined
37
- ? exports.DEFAULT_OUTPUT_REDACTION_OPTIONS
38
- : context.options;
39
- this.text = { type: 'text-delta', redactor: new agents_1.StreamingRedactor(this.options) };
40
- this.reasoning = { type: 'reasoning-delta', redactor: new agents_1.StreamingRedactor(this.options) };
41
- }
42
- processEvent(event) {
43
- if (!this.enabled)
44
- return [event];
45
- if (event.type === 'text-delta')
46
- return this.processDelta(event, this.text, this.reasoning);
47
- if (event.type === 'reasoning-delta') {
48
- return this.processDelta(event, this.reasoning, this.text);
49
- }
50
- return [
51
- ...this.drainChannel(this.reasoning),
52
- ...this.drainChannel(this.text),
53
- this.redactStructural(event),
54
- ];
55
- }
56
- flush() {
57
- if (!this.enabled)
58
- return [];
59
- const events = [...this.drainChannel(this.reasoning), ...this.drainChannel(this.text)];
60
- this.logSummary();
61
- return events;
62
- }
63
- processDelta(event, channel, otherChannel) {
64
- const events = [];
65
- events.push(...this.drainChannel(otherChannel));
66
- if (channel.responseId !== undefined && channel.responseId !== event.responseId) {
67
- events.push(...this.drainChannel(channel));
68
- }
69
- channel.responseId = event.responseId;
70
- const { text, matches } = channel.redactor.push(event.payload.text);
71
- this.recordMatches(matches);
72
- if (text)
73
- events.push(this.makeDelta(channel, text));
74
- return events;
75
- }
76
- drainChannel(channel) {
77
- const { text, matches } = channel.redactor.flush();
78
- this.recordMatches(matches);
79
- return text ? [this.makeDelta(channel, text)] : [];
80
- }
81
- makeDelta(channel, text) {
82
- return {
83
- type: channel.type,
84
- runId: this.context.runId,
85
- agentId: this.context.agentId,
86
- ...(channel.responseId ? { responseId: channel.responseId } : {}),
87
- payload: { text },
88
- };
89
- }
90
- redactStructural(event) {
91
- if (event.type === 'tool-call') {
92
- const { value, matches } = (0, agents_1.redactDeep)(event.payload.args, this.options);
93
- this.recordMatches(matches);
94
- return {
95
- ...event,
96
- payload: { ...event.payload, args: (0, is_record_1.isRecord)(value) ? value : event.payload.args },
97
- };
98
- }
99
- if (event.type === 'tool-result') {
100
- const { value, matches } = (0, agents_1.redactDeep)(event.payload.result, this.options);
101
- this.recordMatches(matches);
102
- return { ...event, payload: { ...event.payload, result: value } };
103
- }
104
- if (event.type === 'tool-error') {
105
- return {
106
- ...event,
107
- payload: { ...event.payload, error: this.redactString(event.payload.error) },
108
- };
109
- }
110
- if (event.type === 'confirmation-request') {
111
- return this.redactConfirmation(event);
112
- }
113
- return event;
114
- }
115
- redactConfirmation(event) {
116
- const payload = event.payload;
117
- const questions = payload.questions?.map((question) => ({
118
- ...question,
119
- question: this.redactString(question.question),
120
- ...(question.options ? { options: question.options.map((o) => this.redactString(o)) } : {}),
121
- }));
122
- const tasks = payload.tasks
123
- ? {
124
- ...payload.tasks,
125
- tasks: payload.tasks.tasks.map((task) => ({
126
- ...task,
127
- description: this.redactString(task.description),
128
- ...(task.detail ? { detail: this.redactString(task.detail) } : {}),
129
- })),
130
- }
131
- : undefined;
132
- const planItems = payload.planItems?.map((item) => ({
133
- ...item,
134
- title: this.redactString(item.title),
135
- spec: this.redactString(item.spec),
136
- }));
137
- let targetApproval = payload.targetApproval;
138
- if (targetApproval) {
139
- const boundedArgs = withholdDeepTargetApprovalArgs(targetApproval.args);
140
- const { value, matches } = (0, agents_1.redactDeep)(boundedArgs, this.options);
141
- this.recordMatches(matches);
142
- targetApproval = {
143
- ...targetApproval,
144
- toolName: this.redactString(targetApproval.toolName),
145
- ...(targetApproval.displayName
146
- ? { displayName: this.redactString(targetApproval.displayName) }
147
- : {}),
148
- args: value,
149
- };
150
- }
151
- return {
152
- ...event,
153
- payload: {
154
- ...payload,
155
- message: this.redactString(payload.message),
156
- ...(payload.introMessage ? { introMessage: this.redactString(payload.introMessage) } : {}),
157
- ...(questions ? { questions } : {}),
158
- ...(tasks ? { tasks } : {}),
159
- ...(planItems ? { planItems } : {}),
160
- ...(targetApproval ? { targetApproval } : {}),
161
- },
162
- };
163
- }
164
- redactString(text) {
165
- const { text: redacted, matches } = (0, agents_1.redactText)(text, this.options);
166
- this.recordMatches(matches);
167
- return redacted;
168
- }
169
- recordMatches(matches) {
170
- for (const match of matches)
171
- this.matches.push(match.category);
172
- }
173
- logSummary() {
174
- if (this.matches.length === 0)
175
- return;
176
- const categories = {};
177
- for (const category of this.matches) {
178
- categories[category] = (categories[category] ?? 0) + 1;
179
- }
180
- this.context.logger.info('Instance AI redacted sensitive content from agent output', {
181
- threadId: this.context.threadId,
182
- runId: this.context.runId,
183
- agentId: this.context.agentId,
184
- count: this.matches.length,
185
- categories,
186
- });
187
- this.matches = [];
188
- }
189
- }
190
- exports.OutputRedactor = OutputRedactor;
191
- //# sourceMappingURL=output-redaction.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"output-redaction.js","sourceRoot":"","sources":["../../src/stream/output-redaction.ts"],"names":[],"mappings":"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"}