Skip to content
Merged
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"build": "electron-vite build",
"preview": "electron-vite preview",
"postinstall": "electron-rebuild -f -w better-sqlite3",
"sdk:build": "npm --prefix sdk/js run build && cargo build -p kestrel-sdk",
"sdk:build": "npm --prefix sdk/js run build && npm --prefix sdk/js run typecheck:examples && cargo build -p kestrel-sdk",
"sdk:package": "npm --prefix sdk/js run pack:dry && cargo package -p kestrel-sdk --allow-dirty",
"sdk:publish:npm": "npm --prefix sdk/js run publish:npm",
"sdk:publish:crate": "cargo publish -p kestrel-sdk",
Expand Down
29 changes: 29 additions & 0 deletions sdk/js/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,39 @@ The required conformance checks cover:
Optional checks cover local retry queues, `evalops://` deep links, and explicit
offline fallback reporting.

### Kestrel Adopter Inventory

The kit is extracted from Kestrel's current EvalOps integration surface:

| Surface | Kestrel role | Consumer kit contract |
| --- | --- | --- |
| Auth/session | Desktop auth context forwards tenant, workspace, and agent identity. | Build scoped headers with organization, workspace, agent, and trace IDs. |
| Service discovery/config | Runtime config selects Platform service URLs and feature flags. | Keep endpoint overrides in one bootstrap object. |
| Agent registration | Desktop agent identity is durable across app restarts. | Require stable agent and workspace IDs before Platform calls. |
| Prompts | Assistant flows can resolve shared prompts before local fallback. | Score prompt resolution as a required capability. |
| Memory | Recall and writes are scoped to workspace/user/agent privacy intent. | Treat read and write paths as separate required capabilities. |
| Approvals | Human decisions should link back to Platform approval records. | Include approvals as a required consumer boundary. |
| Traces | Wide events need correlation IDs for audit joins. | Preserve trace IDs in headers and conformance evidence. |
| LLM Gateway | Model calls route through EvalOps provider refs. | Require an EvalOps gateway base URL and provider binding. |
| Local retry queue | Offline desktop writes are retried with bounded local state. | Expose retry queue behavior as an optional but scored capability. |
| Deep links | `evalops://` routes can return users to desktop context. | Score deep links as optional adopter evidence. |

### Second Adopter Fixture

`examples/node-agent-adopter.ts` proves the kit shape against a non-Kestrel
background worker. It builds a scoped client config, declares the same required
Platform capabilities, and fails fast if a required conformance check is missing.

```bash
npm run build
npm run typecheck:examples
```

## Publish

```bash
npm run build
npm run typecheck:examples
npm run pack:dry
npm publish --access public
```
67 changes: 67 additions & 0 deletions sdk/js/examples/node-agent-adopter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import {
type EvalOpsConsumerCapability,
buildEvalOpsConsumerClientConfig,
scoreEvalOpsConsumerConformance
} from '@evalops/kestrel-sdk'

export interface NodeAgentAdopterInput {
organizationId: string
workspaceId: string
agentId?: string
evalopsBaseUrl?: string
token?: string
}

export function buildNodeAgentAdopter(input: NodeAgentAdopterInput) {
const config = buildEvalOpsConsumerClientConfig({
organizationId: input.organizationId,
workspaceId: input.workspaceId,
agentId: input.agentId ?? 'node-agent-worker',
token: input.token,
endpoints: {
baseUrl: input.evalopsBaseUrl,
agentRegistryBaseUrl: serviceUrl(input.evalopsBaseUrl, 'agent-registry'),
approvalsBaseUrl: serviceUrl(input.evalopsBaseUrl, 'approvals'),
llmGatewayBaseUrl: serviceUrl(input.evalopsBaseUrl, 'llm-gateway'),
memoryBaseUrl: serviceUrl(input.evalopsBaseUrl, 'memory'),
promptsBaseUrl: serviceUrl(input.evalopsBaseUrl, 'prompts'),
tracesBaseUrl: serviceUrl(input.evalopsBaseUrl, 'traces')
},
featureFlags: {
backgroundAgent: true,
platformConsumerKit: true
},
offlineFallback: true
})

const capabilities: EvalOpsConsumerCapability[] = [
'auth-session',
'service-discovery',
'agent-registration',
'prompts',
'memory-read',
'memory-write',
'approvals',
'traces',
'llm-gateway',
'local-retry-queue',
'offline-fallback'
]

const conformance = scoreEvalOpsConsumerConformance(capabilities)
if (!conformance.complete) {
throw new Error(
`Node agent adopter is missing required EvalOps capabilities: ${conformance.missingRequired.join(', ')}`
)
}

return {
config,
conformance
}
}

function serviceUrl(baseUrl: string | undefined, service: string): string | undefined {
const trimmed = baseUrl?.trim().replace(/\/+$/u, '')
return trimmed ? `${trimmed}/${service}` : undefined
}
4 changes: 3 additions & 1 deletion sdk/js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
"types": "./dist/index.d.ts",
"files": [
"dist",
"examples",
"README.md"
],
"scripts": {
"build": "tsc -p tsconfig.json",
"typecheck:examples": "tsc -p tsconfig.examples.json",
"pack:dry": "npm pack --dry-run",
"publish:npm": "npm publish --access public",
"prepublishOnly": "npm run build"
"prepublishOnly": "npm run build && npm run typecheck:examples"
},
"publishConfig": {
"access": "public",
Expand Down
13 changes: 13 additions & 0 deletions sdk/js/tsconfig.examples.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"declaration": false,
"declarationMap": false,
"noEmit": true,
"paths": {
"@evalops/kestrel-sdk": ["./src/index.ts"]
},
"rootDir": "."
},
"include": ["src/**/*.ts", "examples/**/*.ts"]
}