@tryvira/sdk 0.1.26 → 0.1.28
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/README.md +105 -49
- package/dist/index.js +12 -0
- package/dist/js-client.d.ts +14 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,94 +1,150 @@
|
|
|
1
1
|
# @tryvira/sdk
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
Typed JavaScript/TypeScript client for Vira's scoped control and runtime APIs.
|
|
3
|
+
The official JavaScript and TypeScript client for Vira. Use it to connect an AI
|
|
4
|
+
application, record observations, author governed behavior, evaluate changes, release
|
|
5
|
+
approved behavior, and resolve it at runtime.
|
|
7
6
|
|
|
8
7
|
## Install
|
|
9
8
|
|
|
10
9
|
```bash
|
|
11
|
-
npm install @tryvira/sdk
|
|
10
|
+
npm install @tryvira/sdk@0.1.28
|
|
12
11
|
```
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
Configure the organization, project, and environment for every request. Keep the API
|
|
14
|
+
key server-side.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
export VIRA_CONTROL_URL="https://api.tryvira.xyz"
|
|
18
|
+
export VIRA_API_KEY="<your-vira-api-key>"
|
|
19
|
+
export VIRA_ORGANIZATION_ID="<organization-id>"
|
|
20
|
+
export VIRA_PROJECT_ID="<project-id>"
|
|
21
|
+
export VIRA_ENVIRONMENT_ID="<environment-id>"
|
|
22
|
+
```
|
|
17
23
|
|
|
18
24
|
## Connect and record an observation
|
|
19
25
|
|
|
20
26
|
```ts
|
|
21
|
-
import {
|
|
27
|
+
import { randomUUID } from "node:crypto";
|
|
28
|
+
import { ViraClient } from "@tryvira/sdk";
|
|
29
|
+
|
|
30
|
+
const scope = {
|
|
31
|
+
organizationId: process.env.VIRA_ORGANIZATION_ID!,
|
|
32
|
+
projectId: process.env.VIRA_PROJECT_ID!,
|
|
33
|
+
environmentId: process.env.VIRA_ENVIRONMENT_ID!,
|
|
34
|
+
};
|
|
22
35
|
|
|
23
36
|
const vira = new ViraClient({
|
|
24
|
-
baseUrl: process.env.VIRA_CONTROL_URL
|
|
37
|
+
baseUrl: process.env.VIRA_CONTROL_URL!,
|
|
25
38
|
apiKey: process.env.VIRA_API_KEY,
|
|
26
39
|
});
|
|
27
40
|
|
|
28
41
|
const connected = await vira.connectOnce({
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
42
|
+
...scope,
|
|
43
|
+
name: "support-agent",
|
|
44
|
+
systemType: "custom-agent",
|
|
45
|
+
adapterType: "custom-node",
|
|
46
|
+
adapterVersion: "1.0.0",
|
|
47
|
+
idempotencyKey: "connect:support-agent:1",
|
|
32
48
|
});
|
|
33
49
|
|
|
34
|
-
const systemId = String(connected?.body.system?.id);
|
|
35
|
-
const connectionId = String(connected?.body.connection?.id);
|
|
36
50
|
await vira.observe({
|
|
37
|
-
eventId:
|
|
38
|
-
eventType:
|
|
39
|
-
aiSystemId:
|
|
40
|
-
connectionId,
|
|
41
|
-
payload: {
|
|
42
|
-
}, { idempotencyKey: `
|
|
51
|
+
eventId: randomUUID(),
|
|
52
|
+
eventType: "model.response",
|
|
53
|
+
aiSystemId: String(connected.body.system.id),
|
|
54
|
+
connectionId: String(connected.body.connection.id),
|
|
55
|
+
payload: { task: "billing question", outcome: "completed" },
|
|
56
|
+
}, { idempotencyKey: `observation:${randomUUID()}` });
|
|
43
57
|
```
|
|
44
58
|
|
|
45
|
-
|
|
59
|
+
`connectOnce` is idempotent when the same identity and idempotency key are retried.
|
|
60
|
+
Observations are evidence for authoring and evaluation; they do not grant runtime
|
|
61
|
+
authority.
|
|
62
|
+
|
|
63
|
+
## Resolve behavior at runtime
|
|
46
64
|
|
|
47
|
-
Semantic resolution
|
|
48
|
-
boundary and
|
|
65
|
+
Semantic resolution helps select a candidate. Runtime resolution is the enforcing
|
|
66
|
+
boundary and checks scope, policy, release state, and the requested behavior identity.
|
|
49
67
|
|
|
50
68
|
```ts
|
|
51
69
|
const semantic = await vira.resolveSemantic({
|
|
52
|
-
input:
|
|
53
|
-
profile: { domain:
|
|
70
|
+
input: "Answer a customer billing question",
|
|
71
|
+
profile: { domain: "support" },
|
|
54
72
|
});
|
|
55
73
|
|
|
56
74
|
const runtime = await vira.resolveRuntime({
|
|
57
|
-
behaviorPoint:
|
|
58
|
-
executionBoundary:
|
|
59
|
-
idempotencyKey:
|
|
75
|
+
behaviorPoint: "support.answer_billing",
|
|
76
|
+
executionBoundary: scope,
|
|
77
|
+
idempotencyKey: "runtime:billing:request-001",
|
|
60
78
|
});
|
|
79
|
+
|
|
80
|
+
if (runtime.body.decision !== "ALLOW") {
|
|
81
|
+
throw new Error(`Vira denied runtime resolution: ${runtime.body.reason ?? "unknown"}`);
|
|
82
|
+
}
|
|
61
83
|
```
|
|
62
84
|
|
|
63
|
-
Do not treat a semantic
|
|
64
|
-
|
|
85
|
+
Do not treat a semantic match, a score, or a strategy activation as a release. The
|
|
86
|
+
server may deny or abstain when no eligible immutable revision exists.
|
|
65
87
|
|
|
66
|
-
##
|
|
88
|
+
## Create and release a Pack
|
|
67
89
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
90
|
+
Use a Pack when a Task, Behavior Point, Program, Strategy, signals, and evaluation
|
|
91
|
+
material should move together. A Pack is a candidate until it has been evaluated,
|
|
92
|
+
approved, and released.
|
|
71
93
|
|
|
72
94
|
```ts
|
|
73
|
-
const packs = await vira.listPacks();
|
|
74
95
|
const imported = await vira.importPack({
|
|
75
|
-
manifest: { id:
|
|
76
|
-
objects: {
|
|
77
|
-
|
|
96
|
+
manifest: { id: "support.billing", name: "Billing support behavior", version: "1.0.0" },
|
|
97
|
+
objects: {
|
|
98
|
+
semanticTasks: [{
|
|
99
|
+
taskKey: "support.answer_billing",
|
|
100
|
+
description: "Answer billing questions using available account evidence",
|
|
101
|
+
examples: ["Why was I charged twice?"],
|
|
102
|
+
}],
|
|
103
|
+
behaviorPoints: [{
|
|
104
|
+
key: "support.answer_billing",
|
|
105
|
+
taskKey: "support.answer_billing",
|
|
106
|
+
requirement: "Be accurate, cite evidence, and ask for missing account context",
|
|
107
|
+
}],
|
|
108
|
+
},
|
|
109
|
+
idempotencyKey: "pack:import:support.billing:1.0.0",
|
|
78
110
|
});
|
|
79
|
-
console.log(packs?.body, imported?.body);
|
|
80
111
|
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
112
|
+
const packId = String(imported.body.pack.id);
|
|
113
|
+
await vira.installPack(packId, { variables: {} });
|
|
114
|
+
const evaluation = await vira.evaluatePack(packId, {
|
|
115
|
+
candidateExecutionRequired: true,
|
|
116
|
+
rubric: {
|
|
117
|
+
taskCorrectness: 1,
|
|
118
|
+
behaviorCompliance: 1,
|
|
119
|
+
groundedness: 1,
|
|
120
|
+
safetyAuthority: 1,
|
|
121
|
+
usefulSpecificity: 1,
|
|
122
|
+
},
|
|
123
|
+
idempotencyKey: "pack:evaluate:support.billing:1.0.0",
|
|
85
124
|
});
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
await vira.evaluatePack('pack-id', { evaluationId: 'evaluation-id' });
|
|
125
|
+
if (evaluation.body.passed !== true) throw new Error("Candidate evaluation failed");
|
|
126
|
+
await vira.approvePack(packId);
|
|
127
|
+
await vira.releasePack(packId);
|
|
90
128
|
```
|
|
91
129
|
|
|
130
|
+
Never submit a client-created `passed`, `score`, or receipt as release evidence. Vira
|
|
131
|
+
binds evaluation to the materialized Pack digest and immutable release identity. Use
|
|
132
|
+
`previewPackUpgrade` before changing an installed Pack so conflicts and preserved
|
|
133
|
+
overrides are visible first.
|
|
134
|
+
|
|
135
|
+
## Errors and retries
|
|
136
|
+
|
|
137
|
+
- Send an idempotency key with mutations.
|
|
138
|
+
- Treat `401`/`403` as credential or scope errors; do not retry blindly.
|
|
139
|
+
- Treat a runtime deny or abstain as a governed decision, not permission to bypass Vira.
|
|
140
|
+
- Persist request IDs and receipts with application logs for support and audit.
|
|
141
|
+
|
|
92
142
|
## Documentation
|
|
93
143
|
|
|
94
|
-
|
|
144
|
+
- [Developer guide](https://github.com/hrpering/tryvira/blob/main/docs/developer-guide.md)
|
|
145
|
+
- [Pack authoring](https://github.com/hrpering/tryvira/blob/main/docs/packs.md)
|
|
146
|
+
- [Runtime and release](https://github.com/hrpering/tryvira/blob/main/docs/runtime.md)
|
|
147
|
+
- [API reference](https://github.com/hrpering/tryvira/blob/main/docs/reference/api.md)
|
|
148
|
+
|
|
149
|
+
The client library is MIT licensed. The hosted Vira service and backend are governed
|
|
150
|
+
separately.
|
package/dist/index.js
CHANGED
|
@@ -142,6 +142,10 @@ var ViraClient = class {
|
|
|
142
142
|
required(systemId, "SDK_SYSTEM_ID_REQUIRED");
|
|
143
143
|
return this.request({ method: "DELETE", path: `/v1/ai-systems/${encodeURIComponent(systemId)}`, body: { confirm: options.confirm === true } }, { idempotencyKey: options.idempotencyKey ?? `sdk:delete:ai-system:${systemId}` });
|
|
144
144
|
}
|
|
145
|
+
deleteAISystemCascade(systemId, options = {}) {
|
|
146
|
+
required(systemId, "SDK_SYSTEM_ID_REQUIRED");
|
|
147
|
+
return this.request({ method: "DELETE", path: `/v1/ai-systems/${encodeURIComponent(systemId)}/cleanup`, body: { confirm: options.confirm === true, deleteObservations: options.deleteObservations === true } }, { idempotencyKey: options.idempotencyKey ?? `sdk:delete:ai-system-cascade:${systemId}` });
|
|
148
|
+
}
|
|
145
149
|
getAISystem(systemId) {
|
|
146
150
|
required(systemId, "SDK_SYSTEM_ID_REQUIRED");
|
|
147
151
|
return this.request({ method: "GET", path: `/v1/ai-systems/${encodeURIComponent(systemId)}` });
|
|
@@ -587,6 +591,14 @@ var ViraClient = class {
|
|
|
587
591
|
path: `/v1/behavior-programs/${encodeURIComponent(programId)}`
|
|
588
592
|
});
|
|
589
593
|
}
|
|
594
|
+
deleteBehaviorProgram(programId, options = {}) {
|
|
595
|
+
required(programId, "SDK_PROGRAM_ID_REQUIRED");
|
|
596
|
+
return this.request({ method: "DELETE", path: `/v1/behavior-programs/${encodeURIComponent(programId)}`, body: { confirm: options.confirm === true } }, { idempotencyKey: options.idempotencyKey ?? `sdk:delete:behavior-program:${programId}` });
|
|
597
|
+
}
|
|
598
|
+
deleteBehaviorProgramCascade(programId, options = {}) {
|
|
599
|
+
required(programId, "SDK_PROGRAM_ID_REQUIRED");
|
|
600
|
+
return this.request({ method: "DELETE", path: `/v1/behavior-programs/${encodeURIComponent(programId)}/cascade`, body: { confirm: options.confirm === true, purgeRuntime: options.purgeRuntime === true } }, { idempotencyKey: options.idempotencyKey ?? `sdk:delete:behavior-program-cascade:${programId}` });
|
|
601
|
+
}
|
|
590
602
|
createBehaviorProgram(program, options = {}) {
|
|
591
603
|
if (!program || typeof program !== "object")
|
|
592
604
|
throw new Error("SDK_PROGRAM_REQUIRED");
|
package/dist/js-client.d.ts
CHANGED
|
@@ -135,6 +135,11 @@ export declare class ViraClient {
|
|
|
135
135
|
confirm?: boolean;
|
|
136
136
|
idempotencyKey?: string;
|
|
137
137
|
}): Promise<ViraResponse<ClientBody> | null>;
|
|
138
|
+
deleteAISystemCascade(systemId: string, options?: {
|
|
139
|
+
confirm?: boolean;
|
|
140
|
+
deleteObservations?: boolean;
|
|
141
|
+
idempotencyKey?: string;
|
|
142
|
+
}): Promise<ViraResponse<ClientBody> | null>;
|
|
138
143
|
getAISystem(systemId: string): Promise<ViraResponse<ClientBody> | null>;
|
|
139
144
|
connectAdapter(systemId: string, input: {
|
|
140
145
|
adapterType: string;
|
|
@@ -357,6 +362,15 @@ export declare class ViraClient {
|
|
|
357
362
|
getBehaviorProgram(programId: string): Promise<ViraResponse<{
|
|
358
363
|
program: ClientBody;
|
|
359
364
|
}> | null>;
|
|
365
|
+
deleteBehaviorProgram(programId: string, options?: {
|
|
366
|
+
confirm?: boolean;
|
|
367
|
+
idempotencyKey?: string;
|
|
368
|
+
}): Promise<ViraResponse<ClientBody> | null>;
|
|
369
|
+
deleteBehaviorProgramCascade(programId: string, options?: {
|
|
370
|
+
confirm?: boolean;
|
|
371
|
+
purgeRuntime?: boolean;
|
|
372
|
+
idempotencyKey?: string;
|
|
373
|
+
}): Promise<ViraResponse<ClientBody> | null>;
|
|
360
374
|
createBehaviorProgram(program: ClientBody, options?: {
|
|
361
375
|
idempotencyKey?: string;
|
|
362
376
|
}): Promise<ViraResponse<{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tryvira/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.28",
|
|
4
4
|
"description": "Typed Vira SDK for connect-once, observation and governed runtime execution.",
|
|
5
5
|
"keywords": ["vira", "ai-governance", "ai-runtime", "semantic-routing"],
|
|
6
6
|
"engines": {"node": ">=20"},
|