Skip to content

CoreNovus/convilyn-author-js

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

CoreNovus Community — Connected AI Workflows

@convilyn/sdk-author

CI

Official Convilyn Author SDK for TypeScript / JavaScript — build and host tool servers, author workflow specs, and create reusable AI workflow components for the Convilyn AI platform. The counterpart to the consumer SDK @convilyn/sdk: where the consumer SDK calls Convilyn with a ck_ key, the Author SDK lets you extend the platform — authoring tools and workflows that the gateway calls back into, secured by HMAC. The wire shapes match Convilyn's gateway and authoring APIs exactly.

Convilyn Author helps builders turn tools, services, and repeated processes into reusable workflow building blocks. It is part of the CoreNovus vision for practical AI workflows across cloud services, local machines, AI PCs, edge devices, and future IoT environments.

Public mirror of Convilyn's monorepo (the source of truth). Contributions are welcome and land in the shipped package — see CONTRIBUTING.md (fork → PR → upstreamed, authorship preserved).

Status: feature-complete surface (0.x). Ships the tool-server foundation, the WorkflowSpec builder, the ToolServer + JSON-RPC /mcp runtime, the convilyn-author CLI, confirmation-token signing, and the ConvilynClient platform client + local test harness. Only what is documented here is exported and covered by SemVer; while 0.x, minor versions may still adjust the surface.

Install

npm install @convilyn/sdk-author

Node 18+ (uses node:crypto). Ships ESM + CJS + type declarations. Runtime dependencies are minimal — commander (CLI) and zod-to-json-schema — plus zod as a peer dependency.

Tool-server foundation

HMAC inbound verification

The gateway signs every call it makes to your tool server; verify the signature to reject forged requests (use this if you run your own HTTP framework — the SDK's built-in runtime, serve, does it for you).

import { verifySignature, InvalidSignatureError } from '@convilyn/sdk-author'

try {
  // `verifySignature` reads the `x-convilyn-signature` / `-timestamp` headers.
  verifySignature(
    process.env.CONVILYN_HMAC_SECRET!,
    rawBodyBytes,
    req.headers as Record<string, string | undefined>,
  )
  // ...handle the verified request
} catch (err) {
  if (err instanceof InvalidSignatureError) {
    // err.reason ∈ missing_secret | missing_header | invalid_timestamp |
    //              timestamp_out_of_range | signature_mismatch
    res.writeHead(401).end()
  }
}

signRequest(secret, body, unixSeconds) produces the matching { signature, timestamp } pair — for tests, or for calling a developer-hosted server directly.

Manifest, data store, context, config

import { ConvilynManifest, InMemoryDataStore, ToolResult, SDKConfig } from '@convilyn/sdk-author'

const manifest = new ConvilynManifest(
  { name: 'weather', version: '1.0.0', description: 'Weather tools' },
  {
    tools: [
      {
        name: 'get_weather',
        description: 'Get current weather',
        inputSchema: { type: 'object', properties: { location: { type: 'string' } } },
        idempotent: true,
      },
    ],
  }
)
await manifest.save('convilyn.manifest.json')

const store = new InMemoryDataStore()
const refId = await store.store({ large: 'payload' }) // → "td_<12-hex>"

const result = ToolResult.ok({ refId, summary: 'Weather for Taipei' })

const config = SDKConfig.fromEnv() // reads CONVILYN_* env vars

Tools return { ref_id, summary } (build with ToolResult.ok(...) / ToolResult.fail(...)) so the agent's context stays small and fetches the full data by ref_id later.

Workflow authoring

WorkflowSpec is an immutable fluent builder for a portable workflow — a specId (the portal's dev_<developer-id>.<name> namespace), a name, a system prompt, and a palette of "server:tool" references. It validates client-side as you build (name ≤80, ≤20 tools, semver version, rejects the request_user_input tool, …) and has one method per wire contract:

  • compile() → the snake_case WorkflowBlueprint publish artifact (spec_id/version/public_schema_version; cross-SDK parity with the Python author SDK) — what submitWorkflow / push send to the portal.
  • toExportPayload() → the camelCase user_workflows ExportPayload (canvas/authoring contract; carries UI-only positions/notes/canvasLayout).
import { WorkflowSpec, buildWorkflowPolicies } from '@convilyn/sdk-author'

const spec = new WorkflowSpec('Invoice summariser', { specId: 'dev_abc123.invoice_summariser' })
  .withDescription('Extracts totals from invoices')
  .withSystemPrompt('You summarise invoices into a totals table.')
  .useTools('doc-parser-mcp:extract_text', 'doc-parser-mcp:extract_tables')
  .withTags(['finance'])

await spec.save('workflow.spec.json') // portable WorkflowBlueprint JSON
const reloaded = await WorkflowSpec.load('workflow.spec.json') // loads blueprint OR ExportPayload

// Optional high-level policies (attached when publishing a workflow):
const policies = buildWorkflowPolicies({
  retry: { maxAttempts: 3, retryOn: ['transient'] },
  timeout: { maxStepCount: 12 },
})

// Compile the blueprint locally, then publish it through the Developer Portal:
const compiled = spec.compile() // → pass to client.submitWorkflow({ workflow_spec, server_ids })

Tool server

defineTool declares a tool from a Zod schema — the single source of truth for the manifest input_schema, the handler's argument types, and runtime validation of inbound calls. ToolServer registers tools and serve runs the JSON-RPC /mcp runtime (/health, /manifest, and an HMAC-verified POST /mcp), interchangeable with the Python / Go author SDKs behind the same gateway. zod is a peerDependency — install it alongside the SDK and import { z } from 'zod' yourself.

import { defineTool, ToolServer, ToolResult, serve } from '@convilyn/sdk-author'
import { z } from 'zod'

const echo = defineTool({
  name: 'echo',
  description: 'Echo the input text back.',
  input: z.object({ text: z.string().min(1) }),
  idempotent: true,
  handler: (args) => ToolResult.ok({ echoed: args.text }, `Echoed ${args.text.length} chars`),
})

const server = new ToolServer({ name: 'echo-server', version: '1.0.0', description: 'demo' })
server.register(echo)

// Run it (CONVILYN_HMAC_SECRET / CONVILYN_PORT come from the env via SDKConfig):
serve(server, { port: 8080 })

CLI

The package ships a convilyn-author binary:

npx convilyn-author init my-server   # scaffold a TS project
cd my-server && npm install && npm run build
npx convilyn-author dev      # run the JSON-RPC /mcp server (serve)
npx convilyn-author synth    # write convilyn.manifest.json
npx convilyn-author test     # local compliance checks (runComplianceChecks)
npx convilyn-author push --endpoint-url https://my-server.example.com  # publish

synth / dev / test load a built JS module (default server.js, override with --file dist/server.js) that exports a ToolServer as its default or a named server export.

push submits your server + workflow to the Developer Portal (wrapping ConvilynClient.submitServer + submitWorkflow): set a cvl_ key in CONVILYN_API_KEY, then push --endpoint-url <https://...> (the HTTPS URL where you host the server) with --file (built server, default server.js) and --workflow-file (a workflow.spec.json or a built module, default workflow.spec.json). The managed deploy --hosted provisions your server in the Convilyn-Hosted Author Runtime (no infrastructure of your own): deploy --hosted [--region us-east-1] hands over the manifest (plus the compiled workflow when workflow.spec.json exists), then logs <runtimeId> tails the runtime logs and rollback <runtimeId> flips back to the previous version. Without --hosted, deploy errors and points at push --endpoint-url (BYO). Both commands speak the same Developer Portal wire contract as ConvilynClient.

Developer Portal client

ConvilynClient is a fetch-based client for the Developer Portal (/api/v1/developers/*) — the platform's third-party author/publish surface, mirroring the Python convilyn-author SDK. You build and test your own tool server + workflow locally (ToolServer, WorkflowSpec, runComplianceChecks), then integrate them by registering through the portal. Authenticate with a cvl_ developer key as a Bearer token (CONVILYN_API_KEY); the base URL is ${CONVILYN_PLATFORM_URL}/api/v1.

The SDK does not call the first-party console surfaces (/user_workflows/*, /mcp/tools/catalog) — those are JWT/session endpoints owned by the web UI, not an author-publishing API. Validate and cost-preview your work locally with runComplianceChecks / WorkflowSpec.compile before submitting.

import { ConvilynClient, ToolServer, WorkflowSpec } from '@convilyn/sdk-author'

// 1) Register once (no auth) → mint + capture a cvl_ key. Save it; shown once.
const client = new ConvilynClient()
const { api_key } = await client.register({ email: 'dev@example.com', name: 'Dev' })
// …or pass an existing cvl_ key: new ConvilynClient({ apiKey: myCvlKey })
// …or set it in the environment: export CONVILYN_API_KEY=cvl_your_key

// 2) Submit your own tool server for verification.
const server = await client.submitServer({
  manifest: myToolServer.manifest().toWire(),
  endpoint_url: 'https://my-server.example.com',
})
await client.testServer(server.server_id) // sandbox test
await client.serverStatus(server.server_id) // → verified / active / rejected

// 3) Submit your compiled workflow, referencing the server(s) it uses.
const spec = new WorkflowSpec('Invoice summariser', { specId: 'dev_abc123.invoice_summariser' })
  .withSystemPrompt('…')
  .useTools('my-server:extract_text')
const wf = await client.submitWorkflow({ workflow_spec: spec.compile(), server_ids: [server.server_id] })
await client.testWorkflow(wf.workflow_id)

Also available: listServers / deactivateServer, listWorkflows / workflowStatus / deactivateWorkflow, and the hosted-runtime surface deployHostedRuntime / rollbackHostedRuntime / getHostedRuntimeLogs. A non-2xx response throws ConvilynApiError (with .status and .body); an authed call with no key throws ConvilynAuthorError before any network call.

Confirmation tokens

For tools that require a human confirmation handshake, the SDK signs and verifies confirmation tokens byte-for-byte compatibly with the gateway and the Python / Go author SDKs:

import { mintConfirmationToken, verifyConfirmationToken, CONFIRMATION_TTL_SECONDS } from '@convilyn/sdk-author'

const secret = process.env.CONVILYN_TOOL_CONFIRMATION_SECRET!
const expiresAtUnix = Math.floor(Date.now() / 1000) + CONFIRMATION_TTL_SECONDS
const token = mintConfirmationToken({ toolName: 'submit_order', arguments: args, expiresAtUnix, secret })

// On the confirming re-call, with `confirmation_token` present in arguments:
verifyConfirmationToken({ toolName: 'submit_order', arguments: argsWithToken, token, secret })
// throws ConfirmationInvalidError on a malformed / expired / mismatched token

The argument digest strips volatile presigned-URL params, so a re-presigned URL still matches the originally-confirmed arguments.

Local testing harness

invokeTool drives a ToolServer in-process (no HTTP), returning the same wire envelope the gateway would receive — ideal for unit tests:

import { invokeTool } from '@convilyn/sdk-author'

const wire = await invokeTool(server, 'echo', { text: 'hi' })
expect(wire.status).toBe('ok')
expect(wire.data).toEqual({ echoed: 'hi' })

Authentication at a glance

Secret (env) Used for
CONVILYN_API_KEY cvl_ developer key — Bearer auth to the Developer Portal (ConvilynClient)
CONVILYN_HMAC_SECRET Verifying inbound POST /mcp calls from the gateway (serve / verifySignature)
CONVILYN_TOOL_CONFIRMATION_SECRET Minting / verifying confirmation tokens

Getting a runnable starter

npx convilyn-author init my-server scaffolds a complete TypeScript tool-server project (server.ts, build config, .env.example) — the fastest way to see the tool server, manifest, and compliance checks working together.

Public API & Stability

This package follows Semantic Versioning. The SemVer contract is exactly the set of names exported from the package root; anything not exported there is internal and may change in any release. The package.json exports map blocks deep imports, and a packaging test pins the public surface. While the package is 0.x (pre-1.0), minor versions may still contain breaking changes as the surface stabilises toward 1.0.

License

Apache-2.0 — see LICENSE.

About

Official Convilyn author SDK for TypeScript / JavaScript (@convilyn/sdk-author) — public mirror of the monorepo

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors