Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions skills/nutrient-document-processor-api/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
name: nutrient-document-processor-api
description: Execute common document-processing tasks with @nutrient-sdk/dws-client-typescript in Node.js scripts. Use when the user asks to convert, merge, split, OCR, extract text/tables/key-value pairs, watermark, redact, sign, optimize, protect, or reorder Document content, or when they need a custom multi-step document pipeline script built from Nutrient DWS workflow actions.
---

# Nutrient Document Processor API

## Quick Start

1. Ensure Node.js 18+ is available.
2. Install the latest client package in the target project:
- `node skills/nutrient-document-processor-api/scripts/setup-latest-client.mjs npm`
3. Export the API key before running scripts:
- `export NUTRIENT_API_KEY="nutr_sk_..."`
4. Run task scripts with `node` from the repository root.

## Task Scripts

Use one script per operation.

- Convert formats: `scripts/convert.mjs`
- Merge files: `scripts/merge.mjs`
- Split by ranges: `scripts/split.mjs`
- OCR documents: `scripts/ocr.mjs`
- Extract text: `scripts/extract-text.mjs`
- Extract tables: `scripts/extract-table.mjs`
- Extract key-value pairs: `scripts/extract-key-value-pairs.mjs`
- Add text watermark: `scripts/watermark-text.mjs`
- AI redaction: `scripts/redact-ai.mjs`
- Rotate pages: `scripts/rotate.mjs`
- Sign PDF: `scripts/sign.mjs`
- Optimize PDF: `scripts/optimize.mjs`
- Password protect PDF: `scripts/password-protect.mjs`
- Add blank pages: `scripts/add-pages.mjs`
- Delete pages: `scripts/delete-pages.mjs`
- Duplicate/reorder pages: `scripts/duplicate-pages.mjs`

Check exact arguments with `node <script> --help`.

## Custom Pipelines

When the user asks for a workflow not covered by the scripts above, create a new script rather than forcing ad hoc one-off commands.

1. Start from `assets/templates/custom-workflow-template.mjs`.
2. Save the new script in `scripts/` with a task-specific name (for example `scripts/redact-and-watermark.mjs`).
3. Keep API usage on `@nutrient-sdk/dws-client-typescript@latest`.
4. Prefer direct methods (`client.convert`, `client.merge`, etc.) for single-step tasks.
5. Use `client.workflow()` and `BuildActions` for multi-step tasks.
6. Keep every custom script CLI-driven (`--input`, `--out`, explicit options), deterministic, and runnable end-to-end.
7. Run the script with sample input to verify behavior before finalizing.

## Implementation Rules

- Fail fast when required arguments are missing.
- Require local input for operations that do not support URL input (`sign`).
- Write outputs to explicit paths and print created files.
- Do not log secrets.
- If the package import fails, install latest with `npm install @nutrient-sdk/dws-client-typescript@latest`.

## References

- Script matrix and method mapping: `references/script-catalog.md`
- Custom pipeline patterns: `references/custom-pipeline-guidelines.md`
4 changes: 4 additions & 0 deletions skills/nutrient-document-processor-api/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface:
display_name: "Nutrient DWS Processor API"
short_description: "Run common document automation scripts with Nutrient DWS"
default_prompt: "Use this skill to run existing scripts or generate new script-based document pipelines with @nutrient-sdk/dws-client-typescript."
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env node

import {
createClient,
handleError,
isHelpRequested,
parseArgs,
requireArg,
toFileInput,
writeWorkflowOutput,
} from './lib/common.mjs';

import { BuildActions } from '@nutrient-sdk/dws-client-typescript';

const USAGE = `
Template for multi-step custom workflows.

Usage:
node <script>.mjs --input <path-or-url> --out <output-pdf>
`;

const args = parseArgs();
if (isHelpRequested(args)) {
console.log(USAGE.trim());
process.exit(0);
}

try {
const input = requireArg(args, 'input', USAGE);
const out = requireArg(args, 'out', USAGE);

const client = await createClient();

// Customize this action list for the requested pipeline.
const actions = [
BuildActions.ocr('english'),
BuildActions.watermarkText('DRAFT', { opacity: 0.25, rotation: 45 }),
];

const result = await client
.workflow()
.addFilePart(toFileInput(input), undefined, actions)
.outputPdf()
.execute();

await writeWorkflowOutput(result, out);
} catch (error) {
handleError(error);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Custom Pipeline Guidelines

## When to Build a New Script

Build a custom script when the user needs:
- Multiple actions in one run (for example OCR + redact + watermark + optimize)
- Conditional logic around extraction results
- Organization-specific defaults or output layout

## Preferred Construction Order

1. Validate CLI inputs and parse options.
2. Create client with `NUTRIENT_API_KEY`.
3. Build workflow using either:
- Direct methods for single operation
- `client.workflow()` for multi-step actions
4. Execute and write outputs to deterministic paths.
5. Print file outputs and exit non-zero on failures.

## Script Quality Requirements

- Keep scripts non-interactive.
- Accept all runtime values by args/env vars.
- Avoid hard-coded secrets and absolute local paths.
- Emit structured output files (PDF/JSON/TXT) instead of console-only output.
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Script Catalog

## Setup

- `scripts/setup-latest-client.mjs`
- Install `@nutrient-sdk/dws-client-typescript@latest` with npm/pnpm/yarn.

## Core Document Operations

- `scripts/convert.mjs`
- Method: `client.convert(input, format)`
- Common use: office-to-pdf, pdf-to-markdown/html/image

- `scripts/merge.mjs`
- Method: `client.merge(files)`
- Common use: combine reports, append cover pages

- `scripts/split.mjs`
- Method: `client.split(file, ranges)`
- Common use: split sections into separate files

- `scripts/ocr.mjs`
- Method: `client.ocr(file, language|language[])`
- Common use: searchable text from scanned PDFs

- `scripts/extract-text.mjs`
- Method: `client.extractText(file, pages?)`
- Common use: content indexing and summarization input

- `scripts/extract-table.mjs`
- Method: `client.extractTable(file, pages?)`
- Common use: analytics ingest from PDFs

- `scripts/extract-key-value-pairs.mjs`
- Method: `client.extractKeyValuePairs(file, pages?)`
- Common use: forms, invoices, claims data extraction

## PDF Editing and Security

- `scripts/watermark-text.mjs`
- Method: `client.watermarkText(file, text, options?)`

- `scripts/redact-ai.mjs`
- Method: `client.createRedactionsAI(file, criteria, mode, pages?)`

- `scripts/rotate.mjs`
- Method: `client.rotate(file, angle, pages?)`

- `scripts/sign.mjs`
- Method: `client.sign(file, signatureData?, options?)`
- Note: input must be local file path

- `scripts/optimize.mjs`
- Method: `client.optimize(file, options?)`

- `scripts/password-protect.mjs`
- Method: `client.passwordProtect(file, userPassword, ownerPassword, permissions?)`

- `scripts/add-pages.mjs`
- Method: `client.addPage(file, count, index?)`

- `scripts/delete-pages.mjs`
- Method: `client.deletePages(file, pageIndices)`

- `scripts/duplicate-pages.mjs`
- Method: `client.duplicatePages(file, pageIndices)`

## Page Range Conventions

Use `start:end` and comma-separated lists for multi-range inputs.

Examples:
- `0:2` -> first three pages
- `-3:-1` -> last three pages
- `0:2,3:5` -> two segments
41 changes: 41 additions & 0 deletions skills/nutrient-document-processor-api/scripts/add-pages.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env node

import {
createClient,
handleError,
isHelpRequested,
parseArgs,
requireArg,
toFileInput,
writeWorkflowOutput,
} from './lib/common.mjs';

const USAGE = `
Add blank pages to a PDF.

Usage:
node scripts/add-pages.mjs --input <path-or-url> --count <n> --out <output-pdf> [--index <insert-index>]
`;

const args = parseArgs();
if (isHelpRequested(args)) {
console.log(USAGE.trim());
process.exit(0);
}

try {
const input = requireArg(args, 'input', USAGE);
const count = Number.parseInt(requireArg(args, 'count', USAGE), 10);
if (!Number.isInteger(count) || count <= 0) {
throw new Error('--count must be a positive integer.');
}

const out = requireArg(args, 'out', USAGE);
const index = args.index !== undefined ? Number.parseInt(String(args.index), 10) : undefined;

const client = await createClient();
const result = await client.addPage(toFileInput(input), count, index);
await writeWorkflowOutput(result, out);
} catch (error) {
handleError(error);
}
36 changes: 36 additions & 0 deletions skills/nutrient-document-processor-api/scripts/convert.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env node

import {
createClient,
handleError,
isHelpRequested,
parseArgs,
requireArg,
toFileInput,
writeWorkflowOutput,
} from './lib/common.mjs';

const USAGE = `
Convert a document to another format.

Usage:
node scripts/convert.mjs --input <path-or-url> --format <pdf|pdfa|pdfua|docx|xlsx|pptx|png|jpeg|jpg|webp|html|markdown> --out <output-file>
`;

const args = parseArgs();
if (isHelpRequested(args)) {
console.log(USAGE.trim());
process.exit(0);
}

try {
const input = requireArg(args, 'input', USAGE);
const format = requireArg(args, 'format', USAGE);
const out = requireArg(args, 'out', USAGE);

const client = await createClient();
const result = await client.convert(toFileInput(input), format);
await writeWorkflowOutput(result, out);
} catch (error) {
handleError(error);
}
46 changes: 46 additions & 0 deletions skills/nutrient-document-processor-api/scripts/delete-pages.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env node

import {
createClient,
handleError,
isHelpRequested,
parseArgs,
parseIntegerCsv,
requireArg,
toFileInput,
usageError,
writeWorkflowOutput,
} from './lib/common.mjs';

const USAGE = `
Delete specific pages from a PDF.

Usage:
node scripts/delete-pages.mjs --input <path-or-url> --pages <index,index,...> --out <output-pdf>

Examples:
node scripts/delete-pages.mjs --input doc.pdf --pages 0,2,-1 --out doc-without-pages.pdf
`;

const args = parseArgs();
if (isHelpRequested(args)) {
console.log(USAGE.trim());
process.exit(0);
}

try {
const input = requireArg(args, 'input', USAGE);
const pagesRaw = requireArg(args, 'pages', USAGE);
const out = requireArg(args, 'out', USAGE);

const pageIndices = parseIntegerCsv(pagesRaw, 'pages');
if (pageIndices.length === 0) {
throw usageError('--pages must include at least one index.', USAGE);
}

const client = await createClient();
const result = await client.deletePages(toFileInput(input), pageIndices);
await writeWorkflowOutput(result, out);
} catch (error) {
handleError(error);
}
46 changes: 46 additions & 0 deletions skills/nutrient-document-processor-api/scripts/duplicate-pages.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env node

import {
createClient,
handleError,
isHelpRequested,
parseArgs,
parseIntegerCsv,
requireArg,
toFileInput,
usageError,
writeWorkflowOutput,
} from './lib/common.mjs';

const USAGE = `
Create a new PDF from specific page indices (supports duplicates/reordering).

Usage:
node scripts/duplicate-pages.mjs --input <path-or-url> --pages <index,index,...> --out <output-pdf>

Examples:
node scripts/duplicate-pages.mjs --input doc.pdf --pages 2,0,1,1 --out reordered.pdf
`;

const args = parseArgs();
if (isHelpRequested(args)) {
console.log(USAGE.trim());
process.exit(0);
}

try {
const input = requireArg(args, 'input', USAGE);
const pagesRaw = requireArg(args, 'pages', USAGE);
const out = requireArg(args, 'out', USAGE);

const pageIndices = parseIntegerCsv(pagesRaw, 'pages');
if (pageIndices.length === 0) {
throw usageError('--pages must include at least one index.', USAGE);
}

const client = await createClient();
const result = await client.duplicatePages(toFileInput(input), pageIndices);
await writeWorkflowOutput(result, out);
} catch (error) {
handleError(error);
}
Loading