base64/url/hex encoding, common hashes, and UUID generation.
Install
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:omdsh-dev/dsh-tool-encoding
GitHub-sourced plugins run build scripts on your machine at install time. Only install sources you trust, and pin a commit (github:owner/repo#sha).
README
DSH encoding/hash tool plugin — base64/base64url/url/hex encode/decode + hash + UUID for UTF-8 text. Zero dependencies, zero subprocesses, pure functions.
Package name:
@deepseek-ai/dsh-tool-encoding(standalone bundle, not a monorepo-integrated form); thelib/output is generated bynpm run build(tsc) inside the repo and committed with the repository.
Motivation
Encoding/hashing is a high-frequency daily operation for agents: inspecting base64 fields in API responses (JWT payload), building query parameters, verifying file integrity (sha256), generating UUIDs. Problems with the current approach bash -c "echo ... | base64": subprocess overhead, quote-escaping hell (a base64 string embedded in a bash command then in a JSON argument — the double-escaping error rate is extremely high), and inconsistent cross-platform tool names (md5 vs md5sum vs shasum -a 256).
Security model
No eval, no new Function. All operations are pure-function compositions of Buffer/node:crypto/TextDecoder/encodeURIComponent:
- UTF-8 integrity: decoding uses fatal mode (
TextDecoder('utf-8', { fatal: true })); illegal bytes throwencoding: invalid UTF-8 output; legal U+FFFD/control characters are not rejected (00NUL,0anewline,efbfbdU+FFFD are all legal,ffis illegal) - Strict base64 validation: no whitespace,
=only at the end and ≤2, length must be a multiple of 4, RFC 4648 canonical unused bits (non-canonical encodings such asZh==are rejected, preventing multiple strings from mapping to the same text) - Unified rejection of lone surrogates: all text inputs pass through
String.prototype.isWellFormed(), avoiding silent replacement and inconsistent URIError behavior - Byte limits: 1 MB input / 4 MB output (1,000,000 / 4,000,000 bytes each,
Buffer.byteLength; the output limit is a fuse of pre-allocation estimate + final check) - Hash algorithm whitelist:
Object.hasOwnlookup table (md5/sha1/sha256/sha512) - Errors uniformly use the
encoding:prefix and never pass through the underlyingURIError/TypeError
Architecture
DSH Agent
│ ctx.tools.register()
▼
src/index.ts(Cordis 插件入口 + action 分发 + 独立校验)
│
▼
src/encoding.ts
├── b64Encode/b64Decode — 标准 base64(严格校验)
├── b64UrlEncode/b64UrlDecode — base64url(canonical 无 padding,解码兼容)
├── urlEncode/urlDecode — component 语义(URIError 包装)
├── hexEncode/hexDecode — UTF-8 字节 hex(fatal 解码)
├── digest — 白名单哈希
├── newUuid — crypto.randomUUID()
└── validateUnicode/assertInputBytes/decodeUtf8Strict — 校验器
Tool declaration
ctx.tools.register(defineTool({
name: 'encoding',
parameters: {
action: {
type: 'string', required: true,
enum: ['base64_encode','base64_decode','base64url_encode','base64url_decode',
'url_encode','url_decode','hex_encode','hex_decode','hash','uuid'],
},
input: { type: 'string', description: 'Input string for encode/decode/hash' },
algorithm: { type: 'string', enum: ['md5','sha1','sha256','sha512'], description: 'For hash' },
},
output: { schema: { type: 'json' }, render: (_a, v) => [{ type: 'text', text: JSON.stringify(v) }] },
execute: (args) => Promise.resolve(executeAction(args.action, args) as JsonValue),
timeoutMs: 1000,
}))
Supported operations
| action | description | example |
|---|---|---|
base64_encode / base64_decode |
RFC 4648 standard base64 (strict validation) | "foobar" → "Zm9vYmFy" |
base64url_encode / base64url_decode |
JWT-style, unpadded output, decoding accepts +/ and optional padding |
"\uFEFF" → "77u_" |
url_encode / url_decode |
component semantics (not full query): space is %20 not +, !'()* not escaped, decode("+") → "+" |
"a b" → "a%20b" |
hex_encode / hex_decode |
UTF-8 byte hex; the decoded result must be valid UTF-8 | "AB" → "4142" |
hash |
md5/sha1/sha256/sha512 hex digest; non-security use only | sha256("") → e3b0c442... |
uuid |
UUID v4 string (crypto.randomUUID()) |
"550e8400-..." |
Semantic contract:
- v1 is a UTF-8 text tool: all inputs and outputs are strings; binary content is represented as hex; decoded results must be valid UTF-8
- All actions return strings (including
uuid) - Do not use this tool on confidential material: tool arguments are recorded in session logs
npm 0.1.0-rc.6 compatibility (verified)
This plugin has been migrated to the npm 0.1.0-rc.6 dependency line and fully verified in an isolated consumer of @deepseek-ai/dsh@0.1.0-rc.6:
- Types/runtime:
@deepseek-ai/cordis@^4.0.1+@deepseek-ai/dsh-tools@>=0.0.1-rc.1 <0.2.0+@deepseek-ai/dsh-invariants@>=0.0.1-rc.1 <0.2.0(peer); no longer depends on unscopedcordis - Standalone build:
npm install(devDependencies are self-contained: typescript/vitest/@types/node) →npm run typecheck→npm test→npm run build→npm pack - Consumption verification: tarball installed into the 0.1.0-rc.6 consumer →
dsh --profile compat --dump-configshows this plugin's row → the tool actually registers and executes - Startup:
npx -p @deepseek-ai/dsh@0.1.0-rc.6 dsh web(lib production mode; do notinstall -gglobally)
Version adaptation
- DSH version adapted: DSH 0.1.0-rc.6 (npm)
- Bundle declaration:
dsh.bundleinpackage.json(patch points tocordis.patch.yml) +exportsfields - Patch format:
cordis.patch.ymluses the- insert:list (patches are id-targeted; a bare- id:entry reportsentry not found) - files: the published tarball contains
lib/,src/,cordis.patch.yml
Installation
Plugin source repository: https://github.com/omdsh-dev/dsh-tool-encoding (public).
Profile Bundle (recommended)
Install this plugin as a standalone bundle into a profile (DSH 0.1.0-rc.6, npm):
# 交互式(web)profile
dsh plugin --profile web add github:omdsh-dev/dsh-tool-encoding
# 一次性任务(headless)profile —— dsh run 默认使用 headless
dsh plugin --profile headless add github:omdsh-dev/dsh-tool-encoding
The dsh.bundle.patch inside the package (pointing to cordis.patch.yml) automatically adds the plugin to the profile's layer stack after installation; the plugin's cordis.patch.yml inserts the tool-encoding entry via - insert:.
⚠️ web and headless are different profiles: installing into web does not automatically cover headless;
dsh runuses the headless profile by default.
Install via npm pack tarball
npm pack # generates dsh-tool-encoding-*.tgz
dsh plugin --profile web add ./dsh-tool-encoding-*.tgz
dsh plugin --profile headless add ./dsh-tool-encoding-*.tgz
Verify installation
dsh --profile web --dump-config | grep tool-encoding
Run verification
dsh run "使用 encoding 工具把 hello 做 base64 编码"
Manual installation and legacy compatibility
Only for legacy snapshots that do not support Profile Bundle, or plugin development/debugging environments:
- Place into the monorepo:
cp -r encoding ~/.dsh/source/master/packages/tools/encoding(development/debugging) - Add
"@deepseek-ai/dsh-tool-encoding": "workspace:^"toapps/cli/package.json; add{ "path": "./packages/tools/encoding" }to thereferencesoftsconfig.host.json pnpm install && pnpm run build- Insert the plugin in the profile's user-layer patch (
~/.dsh/profiles/<name>/cordis.patch.yml):
- insert:
- id: tool-encoding
name: '@deepseek-ai/dsh-tool-encoding'
- Verify:
dsh --profile <name> --dump-config | grep tool-encoding
Note: patches are id-targeted — a bare
- id:entry reportsentry "xxx" not found; it must be wrapped in an- insert:list.
Known limitations
- Arbitrary binary (non-printable bytes) encode/decode requires v2's
output: "utf8" | "hex"mode hashprovides digests only, no HMAC/salting/key derivation; MD5/SHA-1 are for compatibility/non-security integrity checks only- URL uses component semantics; form encoding (space →
+) needs a separate action (v2)
Testing
pnpm test
41 test cases covering functionality/errors/attack payloads (RFC 4648/1321/6234 known vectors, UTF-8 boundary distinctions, canonical padding boundaries, unified surrogate rejection, etc.). See the locally maintained design document for the full list.
License
MIT
Links
More in this category
liustack/modlens★ 1199
Vision bridge for text-only models: paste an image, get structured JSON evidence (OCR, layout, semantics).
Anionex/dsh-vision-toolkit★ 308
Vision tasks for text-only models: intent-aware image Q&A, long-screenshot OCR, UI reproduction, grounding, and pixel diff.
zhaoolee/notes★ 138
Export DSH conversations as Smartisan Notes-style PNGs, or create and update Markdown notes in a configured account-scoped workspace.
liustack/modsearch★ 85
Web search bridge for text-only agents: ask the web or X, get structured JSON evidence (search, fetch, citations).
Lum1104/dsh-browser★ 80
Chrome sidebar extension that lets DSH operate your browser directly, no vision capabilities required.
taxueseek/argo★ 69
Search built for agents: multilingual coverage across web, academic, code, shopping, finance, news, and encyclopedias.