@convilyn/sdk-author 0.7.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/CHANGELOG.md +280 -0
- package/LICENSE +201 -0
- package/README.md +310 -0
- package/dist/chunk-ZNZXT5ZP.js +1311 -0
- package/dist/chunk-ZNZXT5ZP.js.map +1 -0
- package/dist/cli.cjs +1391 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.js +471 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +1627 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1158 -0
- package/dist/index.d.ts +1158 -0
- package/dist/index.js +279 -0
- package/dist/index.js.map +1 -0
- package/package.json +84 -0
package/README.md
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/CoreNovus/convilyn-author-js/main/docs/assets/corenovus-community-banner.png" alt="CoreNovus Community — Connected AI Workflows" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# @convilyn/sdk-author
|
|
6
|
+
|
|
7
|
+
[](https://github.com/CoreNovus/convilyn-author-js/actions/workflows/ci.yml)
|
|
8
|
+
|
|
9
|
+
Official Convilyn **Author SDK** for TypeScript / JavaScript — build and host
|
|
10
|
+
tool servers, author workflow specs, and create reusable AI workflow components
|
|
11
|
+
for the Convilyn AI platform. The counterpart to the consumer SDK
|
|
12
|
+
[`@convilyn/sdk`](https://www.npmjs.com/package/@convilyn/sdk): where the
|
|
13
|
+
consumer SDK *calls* Convilyn with a `ck_` key, the Author SDK lets you *extend*
|
|
14
|
+
the platform — authoring tools and workflows that the gateway calls back into,
|
|
15
|
+
secured by HMAC. The wire shapes match Convilyn's gateway and authoring APIs
|
|
16
|
+
exactly.
|
|
17
|
+
|
|
18
|
+
Convilyn Author helps builders turn tools, services, and repeated processes into
|
|
19
|
+
reusable workflow building blocks. It is part of the CoreNovus vision for
|
|
20
|
+
practical AI workflows across cloud services, local machines, AI PCs, edge
|
|
21
|
+
devices, and future IoT environments.
|
|
22
|
+
|
|
23
|
+
> **Public mirror** of Convilyn's monorepo (the source of truth). Contributions
|
|
24
|
+
> are welcome and land in the shipped package — see
|
|
25
|
+
> **[CONTRIBUTING.md](CONTRIBUTING.md)** (fork → PR → upstreamed, authorship
|
|
26
|
+
> preserved).
|
|
27
|
+
|
|
28
|
+
> **Status: feature-complete surface (0.x).** Ships the tool-server foundation,
|
|
29
|
+
> the `WorkflowSpec` builder, the `ToolServer` + JSON-RPC `/mcp` runtime, the
|
|
30
|
+
> `convilyn-author` CLI, confirmation-token signing, and the `ConvilynClient`
|
|
31
|
+
> platform client + local test harness. Only what is documented here is exported
|
|
32
|
+
> and covered by SemVer; while `0.x`, minor versions may still adjust the surface.
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install @convilyn/sdk-author
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Node 18+ (uses `node:crypto`). Ships ESM + CJS + type declarations. Runtime
|
|
41
|
+
dependencies are minimal — `commander` (CLI) and `zod-to-json-schema` — plus
|
|
42
|
+
`zod` as a peer dependency.
|
|
43
|
+
|
|
44
|
+
## Tool-server foundation
|
|
45
|
+
|
|
46
|
+
### HMAC inbound verification
|
|
47
|
+
|
|
48
|
+
The gateway signs every call it makes to your tool server; verify the signature
|
|
49
|
+
to reject forged requests (use this if you run your own HTTP framework — the
|
|
50
|
+
SDK's built-in runtime, `serve`, does it for you).
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import { verifySignature, InvalidSignatureError } from '@convilyn/sdk-author'
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
// `verifySignature` reads the `x-convilyn-signature` / `-timestamp` headers.
|
|
57
|
+
verifySignature(
|
|
58
|
+
process.env.CONVILYN_HMAC_SECRET!,
|
|
59
|
+
rawBodyBytes,
|
|
60
|
+
req.headers as Record<string, string | undefined>,
|
|
61
|
+
)
|
|
62
|
+
// ...handle the verified request
|
|
63
|
+
} catch (err) {
|
|
64
|
+
if (err instanceof InvalidSignatureError) {
|
|
65
|
+
// err.reason ∈ missing_secret | missing_header | invalid_timestamp |
|
|
66
|
+
// timestamp_out_of_range | signature_mismatch
|
|
67
|
+
res.writeHead(401).end()
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`signRequest(secret, body, unixSeconds)` produces the matching
|
|
73
|
+
`{ signature, timestamp }` pair — for tests, or for calling a developer-hosted
|
|
74
|
+
server directly.
|
|
75
|
+
|
|
76
|
+
### Manifest, data store, context, config
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import { ConvilynManifest, InMemoryDataStore, ToolResult, SDKConfig } from '@convilyn/sdk-author'
|
|
80
|
+
|
|
81
|
+
const manifest = new ConvilynManifest(
|
|
82
|
+
{ name: 'weather', version: '1.0.0', description: 'Weather tools' },
|
|
83
|
+
{
|
|
84
|
+
tools: [
|
|
85
|
+
{
|
|
86
|
+
name: 'get_weather',
|
|
87
|
+
description: 'Get current weather',
|
|
88
|
+
inputSchema: { type: 'object', properties: { location: { type: 'string' } } },
|
|
89
|
+
idempotent: true,
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
}
|
|
93
|
+
)
|
|
94
|
+
await manifest.save('convilyn.manifest.json')
|
|
95
|
+
|
|
96
|
+
const store = new InMemoryDataStore()
|
|
97
|
+
const refId = await store.store({ large: 'payload' }) // → "td_<12-hex>"
|
|
98
|
+
|
|
99
|
+
const result = ToolResult.ok({ refId, summary: 'Weather for Taipei' })
|
|
100
|
+
|
|
101
|
+
const config = SDKConfig.fromEnv() // reads CONVILYN_* env vars
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Tools return `{ ref_id, summary }` (build with `ToolResult.ok(...)` /
|
|
105
|
+
`ToolResult.fail(...)`) so the agent's context stays small and fetches the full
|
|
106
|
+
data by `ref_id` later.
|
|
107
|
+
|
|
108
|
+
## Workflow authoring
|
|
109
|
+
|
|
110
|
+
`WorkflowSpec` is an immutable fluent builder for a portable workflow — a
|
|
111
|
+
`specId` (the portal's `dev_<developer-id>.<name>` namespace), a name, a system
|
|
112
|
+
prompt, and a palette of `"server:tool"` references. It validates client-side
|
|
113
|
+
as you build (name ≤80, ≤20 tools, semver version, rejects the
|
|
114
|
+
`request_user_input` tool, …) and has one method per wire contract:
|
|
115
|
+
|
|
116
|
+
- `compile()` → the snake_case **`WorkflowBlueprint`** publish artifact
|
|
117
|
+
(`spec_id`/`version`/`public_schema_version`; cross-SDK parity with the
|
|
118
|
+
Python author SDK) — what `submitWorkflow` / `push` send to the portal.
|
|
119
|
+
- `toExportPayload()` → the camelCase user_workflows **`ExportPayload`**
|
|
120
|
+
(canvas/authoring contract; carries UI-only positions/notes/canvasLayout).
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
import { WorkflowSpec, buildWorkflowPolicies } from '@convilyn/sdk-author'
|
|
124
|
+
|
|
125
|
+
const spec = new WorkflowSpec('Invoice summariser', { specId: 'dev_abc123.invoice_summariser' })
|
|
126
|
+
.withDescription('Extracts totals from invoices')
|
|
127
|
+
.withSystemPrompt('You summarise invoices into a totals table.')
|
|
128
|
+
.useTools('doc-parser-mcp:extract_text', 'doc-parser-mcp:extract_tables')
|
|
129
|
+
.withTags(['finance'])
|
|
130
|
+
|
|
131
|
+
await spec.save('workflow.spec.json') // portable WorkflowBlueprint JSON
|
|
132
|
+
const reloaded = await WorkflowSpec.load('workflow.spec.json') // loads blueprint OR ExportPayload
|
|
133
|
+
|
|
134
|
+
// Optional high-level policies (attached when publishing a workflow):
|
|
135
|
+
const policies = buildWorkflowPolicies({
|
|
136
|
+
retry: { maxAttempts: 3, retryOn: ['transient'] },
|
|
137
|
+
timeout: { maxStepCount: 12 },
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
// Compile the blueprint locally, then publish it through the Developer Portal:
|
|
141
|
+
const compiled = spec.compile() // → pass to client.submitWorkflow({ workflow_spec, server_ids })
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Tool server
|
|
145
|
+
|
|
146
|
+
`defineTool` declares a tool from a [Zod](https://zod.dev/) schema — the single
|
|
147
|
+
source of truth for the manifest `input_schema`, the handler's argument types,
|
|
148
|
+
and runtime validation of inbound calls. `ToolServer` registers tools and
|
|
149
|
+
`serve` runs the JSON-RPC `/mcp` runtime (`/health`, `/manifest`, and an
|
|
150
|
+
HMAC-verified `POST /mcp`), interchangeable with the Python / Go author SDKs
|
|
151
|
+
behind the same gateway. `zod` is a peerDependency — install it alongside the
|
|
152
|
+
SDK and `import { z } from 'zod'` yourself.
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
import { defineTool, ToolServer, ToolResult, serve } from '@convilyn/sdk-author'
|
|
156
|
+
import { z } from 'zod'
|
|
157
|
+
|
|
158
|
+
const echo = defineTool({
|
|
159
|
+
name: 'echo',
|
|
160
|
+
description: 'Echo the input text back.',
|
|
161
|
+
input: z.object({ text: z.string().min(1) }),
|
|
162
|
+
idempotent: true,
|
|
163
|
+
handler: (args) => ToolResult.ok({ echoed: args.text }, `Echoed ${args.text.length} chars`),
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
const server = new ToolServer({ name: 'echo-server', version: '1.0.0', description: 'demo' })
|
|
167
|
+
server.register(echo)
|
|
168
|
+
|
|
169
|
+
// Run it (CONVILYN_HMAC_SECRET / CONVILYN_PORT come from the env via SDKConfig):
|
|
170
|
+
serve(server, { port: 8080 })
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## CLI
|
|
174
|
+
|
|
175
|
+
The package ships a `convilyn-author` binary:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
npx convilyn-author init my-server # scaffold a TS project
|
|
179
|
+
cd my-server && npm install && npm run build
|
|
180
|
+
npx convilyn-author dev # run the JSON-RPC /mcp server (serve)
|
|
181
|
+
npx convilyn-author synth # write convilyn.manifest.json
|
|
182
|
+
npx convilyn-author test # local compliance checks (runComplianceChecks)
|
|
183
|
+
npx convilyn-author push --endpoint-url https://my-server.example.com # publish
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
`synth` / `dev` / `test` load a **built** JS module (default `server.js`,
|
|
187
|
+
override with `--file dist/server.js`) that exports a `ToolServer` as its default
|
|
188
|
+
or a named `server` export.
|
|
189
|
+
|
|
190
|
+
`push` submits your server + workflow to the **Developer Portal** (wrapping
|
|
191
|
+
`ConvilynClient.submitServer` + `submitWorkflow`): set a `cvl_` key in
|
|
192
|
+
`CONVILYN_API_KEY`, then `push --endpoint-url <https://...>` (the HTTPS URL where
|
|
193
|
+
*you* host the server) with `--file` (built server, default `server.js`) and
|
|
194
|
+
`--workflow-file` (a `workflow.spec.json` or a built module, default
|
|
195
|
+
`workflow.spec.json`). The managed `deploy --hosted` provisions your server in
|
|
196
|
+
the **Convilyn-Hosted Author Runtime** (no infrastructure of your own):
|
|
197
|
+
`deploy --hosted [--region us-east-1]` hands over the manifest (plus the
|
|
198
|
+
compiled workflow when `workflow.spec.json` exists), then `logs <runtimeId>`
|
|
199
|
+
tails the runtime logs and `rollback <runtimeId>` flips back to the previous
|
|
200
|
+
version. Without `--hosted`, `deploy` errors and points at
|
|
201
|
+
`push --endpoint-url` (BYO). Both commands speak the same Developer Portal wire
|
|
202
|
+
contract as `ConvilynClient`.
|
|
203
|
+
|
|
204
|
+
## Developer Portal client
|
|
205
|
+
|
|
206
|
+
`ConvilynClient` is a `fetch`-based client for the **Developer Portal**
|
|
207
|
+
(`/api/v1/developers/*`) — the platform's third-party author/publish surface,
|
|
208
|
+
mirroring the Python `convilyn-author` SDK. You **build and test your own** tool
|
|
209
|
+
server + workflow locally (`ToolServer`, `WorkflowSpec`, `runComplianceChecks`),
|
|
210
|
+
then **integrate** them by registering through the portal. Authenticate with a
|
|
211
|
+
`cvl_` developer key as a Bearer token (`CONVILYN_API_KEY`); the base URL is
|
|
212
|
+
`${CONVILYN_PLATFORM_URL}/api/v1`.
|
|
213
|
+
|
|
214
|
+
> The SDK does **not** call the first-party console surfaces (`/user_workflows/*`,
|
|
215
|
+
> `/mcp/tools/catalog`) — those are JWT/session endpoints owned by the web UI, not
|
|
216
|
+
> an author-publishing API. Validate and cost-preview your work **locally** with
|
|
217
|
+
> `runComplianceChecks` / `WorkflowSpec.compile` before submitting.
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
import { ConvilynClient, ToolServer, WorkflowSpec } from '@convilyn/sdk-author'
|
|
221
|
+
|
|
222
|
+
// 1) Register once (no auth) → mint + capture a cvl_ key. Save it; shown once.
|
|
223
|
+
const client = new ConvilynClient()
|
|
224
|
+
const { api_key } = await client.register({ email: 'dev@example.com', name: 'Dev' })
|
|
225
|
+
// …or pass an existing cvl_ key: new ConvilynClient({ apiKey: myCvlKey })
|
|
226
|
+
// …or set it in the environment: export CONVILYN_API_KEY=cvl_your_key
|
|
227
|
+
|
|
228
|
+
// 2) Submit your own tool server for verification.
|
|
229
|
+
const server = await client.submitServer({
|
|
230
|
+
manifest: myToolServer.manifest().toWire(),
|
|
231
|
+
endpoint_url: 'https://my-server.example.com',
|
|
232
|
+
})
|
|
233
|
+
await client.testServer(server.server_id) // sandbox test
|
|
234
|
+
await client.serverStatus(server.server_id) // → verified / active / rejected
|
|
235
|
+
|
|
236
|
+
// 3) Submit your compiled workflow, referencing the server(s) it uses.
|
|
237
|
+
const spec = new WorkflowSpec('Invoice summariser', { specId: 'dev_abc123.invoice_summariser' })
|
|
238
|
+
.withSystemPrompt('…')
|
|
239
|
+
.useTools('my-server:extract_text')
|
|
240
|
+
const wf = await client.submitWorkflow({ workflow_spec: spec.compile(), server_ids: [server.server_id] })
|
|
241
|
+
await client.testWorkflow(wf.workflow_id)
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Also available: `listServers` / `deactivateServer`, `listWorkflows` /
|
|
245
|
+
`workflowStatus` / `deactivateWorkflow`, and the hosted-runtime surface
|
|
246
|
+
`deployHostedRuntime` / `rollbackHostedRuntime` / `getHostedRuntimeLogs`.
|
|
247
|
+
A non-2xx response throws
|
|
248
|
+
`ConvilynApiError` (with `.status` and `.body`); an authed call with no key throws
|
|
249
|
+
`ConvilynAuthorError` before any network call.
|
|
250
|
+
|
|
251
|
+
## Confirmation tokens
|
|
252
|
+
|
|
253
|
+
For tools that require a human confirmation handshake, the SDK signs and verifies
|
|
254
|
+
confirmation tokens byte-for-byte compatibly with the gateway and the Python / Go
|
|
255
|
+
author SDKs:
|
|
256
|
+
|
|
257
|
+
```ts
|
|
258
|
+
import { mintConfirmationToken, verifyConfirmationToken, CONFIRMATION_TTL_SECONDS } from '@convilyn/sdk-author'
|
|
259
|
+
|
|
260
|
+
const secret = process.env.CONVILYN_TOOL_CONFIRMATION_SECRET!
|
|
261
|
+
const expiresAtUnix = Math.floor(Date.now() / 1000) + CONFIRMATION_TTL_SECONDS
|
|
262
|
+
const token = mintConfirmationToken({ toolName: 'submit_order', arguments: args, expiresAtUnix, secret })
|
|
263
|
+
|
|
264
|
+
// On the confirming re-call, with `confirmation_token` present in arguments:
|
|
265
|
+
verifyConfirmationToken({ toolName: 'submit_order', arguments: argsWithToken, token, secret })
|
|
266
|
+
// throws ConfirmationInvalidError on a malformed / expired / mismatched token
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
The argument digest strips volatile presigned-URL params, so a re-presigned URL
|
|
270
|
+
still matches the originally-confirmed arguments.
|
|
271
|
+
|
|
272
|
+
## Local testing harness
|
|
273
|
+
|
|
274
|
+
`invokeTool` drives a `ToolServer` in-process (no HTTP), returning the same wire
|
|
275
|
+
envelope the gateway would receive — ideal for unit tests:
|
|
276
|
+
|
|
277
|
+
```ts
|
|
278
|
+
import { invokeTool } from '@convilyn/sdk-author'
|
|
279
|
+
|
|
280
|
+
const wire = await invokeTool(server, 'echo', { text: 'hi' })
|
|
281
|
+
expect(wire.status).toBe('ok')
|
|
282
|
+
expect(wire.data).toEqual({ echoed: 'hi' })
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## Authentication at a glance
|
|
286
|
+
|
|
287
|
+
| Secret (env) | Used for |
|
|
288
|
+
|---|---|
|
|
289
|
+
| `CONVILYN_API_KEY` | `cvl_` developer key — Bearer auth to the Developer Portal (`ConvilynClient`) |
|
|
290
|
+
| `CONVILYN_HMAC_SECRET` | Verifying inbound `POST /mcp` calls from the gateway (`serve` / `verifySignature`) |
|
|
291
|
+
| `CONVILYN_TOOL_CONFIRMATION_SECRET` | Minting / verifying confirmation tokens |
|
|
292
|
+
|
|
293
|
+
## Getting a runnable starter
|
|
294
|
+
|
|
295
|
+
`npx convilyn-author init my-server` scaffolds a complete TypeScript
|
|
296
|
+
tool-server project (`server.ts`, build config, `.env.example`) — the fastest
|
|
297
|
+
way to see the tool server, manifest, and compliance checks working together.
|
|
298
|
+
|
|
299
|
+
## Public API & Stability
|
|
300
|
+
|
|
301
|
+
This package follows [Semantic Versioning](https://semver.org/). **The SemVer
|
|
302
|
+
contract is exactly the set of names exported from the package root**; anything
|
|
303
|
+
not exported there is internal and may change in any release. The `package.json`
|
|
304
|
+
`exports` map blocks deep imports, and a packaging test pins the public surface.
|
|
305
|
+
While the package is `0.x` (pre-1.0), minor versions may still contain breaking
|
|
306
|
+
changes as the surface stabilises toward 1.0.
|
|
307
|
+
|
|
308
|
+
## License
|
|
309
|
+
|
|
310
|
+
Apache-2.0 — see [LICENSE](./LICENSE).
|