@arnilo/prism 0.0.12 → 0.0.14
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 +23 -0
- package/README.md +8 -2
- package/dist/agents.js +21 -2
- package/dist/artifacts.d.ts +78 -0
- package/dist/artifacts.js +24 -0
- package/dist/contracts.d.ts +35 -1
- package/dist/contracts.js +8 -0
- package/dist/conversations.d.ts +50 -0
- package/dist/conversations.js +97 -0
- package/dist/credentials.d.ts +14 -0
- package/dist/credentials.js +9 -0
- package/dist/devices.d.ts +94 -0
- package/dist/devices.js +138 -0
- package/dist/extensions.d.ts +11 -0
- package/dist/extensions.js +15 -0
- package/dist/identity.d.ts +92 -0
- package/dist/identity.js +257 -0
- package/dist/index.d.ts +15 -5
- package/dist/index.js +8 -3
- package/dist/persistence-lifecycle.d.ts +103 -0
- package/dist/persistence-lifecycle.js +204 -0
- package/dist/providers/openai-compatible.d.ts +5 -1
- package/dist/providers/openai-compatible.js +15 -6
- package/dist/providers/openai-primitives.js +5 -2
- package/dist/secure-agent.js +7 -1
- package/dist/testing/persistence-schema.d.ts +2 -2
- package/dist/testing/persistence-schema.js +35 -2
- package/dist/tools.d.ts +2 -0
- package/dist/tools.js +6 -0
- package/docs/a2a.md +2 -0
- package/docs/ag-ui.md +5 -0
- package/docs/agent-identity.md +111 -0
- package/docs/browser-automation.md +3 -0
- package/docs/conversations.md +135 -0
- package/docs/credential-storage.md +31 -1
- package/docs/credentials-and-redaction.md +2 -0
- package/docs/database-persistence.md +22 -7
- package/docs/device-adapters.md +97 -0
- package/docs/extensions.md +1 -0
- package/docs/guardrails.md +3 -0
- package/docs/host-security.md +9 -3
- package/docs/index.md +26 -13
- package/docs/mcp-tools.md +2 -0
- package/docs/migration.md +48 -0
- package/docs/model-routing.md +102 -0
- package/docs/observability.md +2 -0
- package/docs/performance.md +21 -0
- package/docs/policy-and-audit.md +128 -0
- package/docs/postgres-persistence.md +1 -1
- package/docs/provider-caching.md +4 -0
- package/docs/provider-packages.md +12 -2
- package/docs/provider-request-policies.md +2 -0
- package/docs/providers/alibaba.md +179 -0
- package/docs/providers/azure.md +74 -0
- package/docs/providers/bedrock.md +72 -0
- package/docs/providers/google.md +1 -0
- package/docs/providers/ollama.md +166 -0
- package/docs/providers/openai-compatible.md +3 -1
- package/docs/providers/openrouter.md +2 -0
- package/docs/providers/vertex.md +71 -0
- package/docs/public-contracts.md +3 -1
- package/docs/release-and-install.md +149 -7
- package/docs/review-coverage-2026-07-23-phase-8.md +245 -0
- package/docs/review-coverage-2026-07-25-phase-9.md +256 -0
- package/docs/runs-and-usage.md +2 -0
- package/docs/server.md +37 -4
- package/docs/sqlite-persistence.md +1 -1
- package/docs/supervisors.md +2 -0
- package/docs/work-artifacts-and-review.md +100 -0
- package/docs/work-connectors.md +32 -0
- package/docs/work-tools.md +117 -0
- package/docs/workflows.md +4 -0
- package/docs/working-and-semantic-memory.md +20 -5
- package/package.json +4 -1
- package/templates/init/providers.json +22 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.14] - 2026-07-26
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Phase 9 personal/work-agent surfaces: durable conversation service (`createConversationService`), durable artifact service with review/approval/authorized delivery (`createArtifactService`), memory consent + lifecycle (`setConsent`/`correct`/`forget`/`applyRetention`), AG-UI co-work events (`mapCoWork` + ACP parity), scoped M365/GWS OAuth connectors (`revokeOAuthCredential`, `createOAuthWorkTokenProvider`), a browser verified-state checkpoint ledger, and a deny-by-default device adapter contract (`resolveDevicePolicy`/`assertDeviceAdmit`).
|
|
8
|
+
- New optional provider packages `@arnilo/prism-provider-alibaba` (Model Studio / DashScope + Coding Plan) and `@arnilo/prism-provider-ollama` (cloud/local), both with dynamic model discovery; enrolled via `@arnilo/prism-providers`.
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Versioned all **43** first-party manifests and exact internal ranges to `0.0.14` (41 → 43; only the two provider packages are new).
|
|
13
|
+
- Network-free Phase 9 evidence: `scripts/benchmark-0.0.14.mjs`.
|
|
14
|
+
|
|
15
|
+
## [0.0.13] - 2026-07-24
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Enterprise identity (`Principal` / `AgentIdentity`), optional `@arnilo/prism-policy`, `@arnilo/prism-model-router`, enterprise cloud providers (Azure/Bedrock/Vertex), server deployment seams, persistence schema v5 lifecycle hooks, and `@arnilo/prism-work-tools` (M365 + GWS).
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- Versioned all **41** first-party manifests and exact internal ranges to `0.0.13`; Phase 8 optional packages enroll in `@arnilo/prism-all` only.
|
|
24
|
+
- Network-free enterprise evidence: `scripts/benchmark-0.0.13.mjs`.
|
|
25
|
+
|
|
3
26
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
4
27
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
5
28
|
|
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ packages. Prism defines contracts, not apps.
|
|
|
17
17
|
OpenAI/OpenRouter use best-effort explicit cache hints, NeuralWatt uses
|
|
18
18
|
best-effort implicit prefix caching, and other providers have route/model-specific
|
|
19
19
|
or no cache-control support; see [docs/provider-caching.md](docs/provider-caching.md).
|
|
20
|
-
- **First-party packages**:
|
|
20
|
+
- **First-party packages**: fourteen provider adapters, two compaction strategies,
|
|
21
21
|
coding tools/security, JSON Schema validation, MCP, workflows, OpenTelemetry,
|
|
22
22
|
encrypted credentials, SQLite/PostgreSQL persistence, and manifest-only install profiles.
|
|
23
23
|
- **Tools, context, skills**: host-owned tool registry with allow/deny filtering
|
|
@@ -34,6 +34,10 @@ packages. Prism defines contracts, not apps.
|
|
|
34
34
|
- **Config, settings, security**: layered config merge, settings providers,
|
|
35
35
|
credential resolvers, trust/permission policies, and secret redaction.
|
|
36
36
|
- **CLI/RPC/server**: `prism --mode print|json|rpc`, `prism init`, optional framework-free authorized Web agent/workflow routes, and explicit MCP server exposure.
|
|
37
|
+
- **Co-work contracts (0.0.14)**: conversation thread and artifact/review types, a
|
|
38
|
+
deny-by-default device-adapter contract (`resolveDevicePolicy`/`assertDeviceAdmit`),
|
|
39
|
+
and OAuth refresh/revoke helpers; services ship in `@arnilo/prism-server` and
|
|
40
|
+
`@arnilo/prism-credentials-node`.
|
|
37
41
|
|
|
38
42
|
## Install
|
|
39
43
|
|
|
@@ -150,6 +154,8 @@ printf '{"id":"1","command":"prompt","params":{"input":"Hi"}}\n' \
|
|
|
150
154
|
| `@arnilo/prism-provider-zai` | ZAI GLM provider |
|
|
151
155
|
| `@arnilo/prism-provider-kimi` | Kimi For Coding provider |
|
|
152
156
|
| `@arnilo/prism-provider-neuralwatt` | NeuralWatt provider with implicit vLLM prefix caching |
|
|
157
|
+
| `@arnilo/prism-provider-alibaba` | Alibaba Cloud (Model Studio / DashScope + Coding Plan) provider with dynamic discovery and explicit/implicit caching |
|
|
158
|
+
| `@arnilo/prism-provider-ollama` | Ollama Cloud / local provider with dynamic discovery and implicit-only caching |
|
|
153
159
|
| `@arnilo/prism-compaction-llm` | provider-backed compaction strategy |
|
|
154
160
|
| `@arnilo/prism-compaction-observational-memory` | source-backed memory + recall tool |
|
|
155
161
|
| `@arnilo/prism-coding-agent` | bounded shell/read/write/edit tools |
|
|
@@ -163,7 +169,7 @@ printf '{"id":"1","command":"prompt","params":{"input":"Hi"}}\n' \
|
|
|
163
169
|
| `@arnilo/prism-credentials-node` | encrypted-file and keychain credentials |
|
|
164
170
|
| `@arnilo/prism-session-store-sqlite` | SQLite persistence/checkpoints/leases/owned run feedback |
|
|
165
171
|
| `@arnilo/prism-session-store-postgres` | PostgreSQL persistence/checkpoints/leases/owned run feedback |
|
|
166
|
-
| `@arnilo/prism-providers` | family: all
|
|
172
|
+
| `@arnilo/prism-providers` | family: all 11 provider adapters, including AI SDK interoperability |
|
|
167
173
|
| `@arnilo/prism-compaction` | family: both compaction strategies |
|
|
168
174
|
| `@arnilo/prism-base` | profile: core + compaction + JSON Schema validation |
|
|
169
175
|
| `@arnilo/prism-code` | profile: base + coding tools/security + MCP |
|
package/dist/agents.js
CHANGED
|
@@ -17,6 +17,7 @@ import { createToolRegistry, dispatchToolCall } from "./tools.js";
|
|
|
17
17
|
import { RunLimitError, RunLimitTracker, resolveRunLimits } from "./run-limits.js";
|
|
18
18
|
import { agentFingerprint, initialAgentRunState, loadAgentRunState, publicState, saveAgentRunState, validateRunStateOptions } from "./agent-run-state.js";
|
|
19
19
|
import { resolveActiveSkills } from "./skills.js";
|
|
20
|
+
import { identityTelemetryAttributes, ownershipFromIdentity, resolveRunIdentity, } from "./identity.js";
|
|
20
21
|
export function createAgent(config) {
|
|
21
22
|
return {
|
|
22
23
|
config,
|
|
@@ -154,6 +155,7 @@ class RuntimeAgentSession {
|
|
|
154
155
|
activeProvider;
|
|
155
156
|
activeLedger;
|
|
156
157
|
activeOwnership;
|
|
158
|
+
activeIdentity;
|
|
157
159
|
activeIdempotencyKey;
|
|
158
160
|
activeGuardrails;
|
|
159
161
|
activeMetadata;
|
|
@@ -261,6 +263,9 @@ class RuntimeAgentSession {
|
|
|
261
263
|
this.activeRedactor = options.redactor ?? this.agent.config.redactor;
|
|
262
264
|
this.activeLedger = options.runLedger ?? this.agent.config.runLedger;
|
|
263
265
|
this.activeOwnership = options.ownership ?? this.agent.config.ownership;
|
|
266
|
+
this.activeIdentity = resolveRunIdentity(options.identity, this.agent.config.identity, this.activeOwnership);
|
|
267
|
+
if (this.activeIdentity && !this.activeOwnership)
|
|
268
|
+
this.activeOwnership = ownershipFromIdentity(this.activeIdentity);
|
|
264
269
|
this.activeIdempotencyKey = options.idempotencyKey ?? this.agent.config.idempotencyKey;
|
|
265
270
|
this.activeGuardrails = mergeGuardrails(this.agent.config.guardrails, options.guardrails);
|
|
266
271
|
this.activeDurable = resumed ?? (durableOptions ? { options: durableOptions, version: 0 } : undefined);
|
|
@@ -272,7 +277,12 @@ class RuntimeAgentSession {
|
|
|
272
277
|
let runStatus = "succeeded";
|
|
273
278
|
const runUsage = createUsageAccumulator();
|
|
274
279
|
let usage;
|
|
275
|
-
const metadata = {
|
|
280
|
+
const metadata = {
|
|
281
|
+
...this.agent.config.metadata,
|
|
282
|
+
...this.metadata,
|
|
283
|
+
...options.metadata,
|
|
284
|
+
...(this.activeIdentity ? identityTelemetryAttributes(this.activeIdentity) : {}),
|
|
285
|
+
};
|
|
276
286
|
this.activeMetadata = metadata;
|
|
277
287
|
const limits = new RunLimitTracker(resolvedLimits, {
|
|
278
288
|
onExceeded: (breach) => {
|
|
@@ -434,7 +444,14 @@ class RuntimeAgentSession {
|
|
|
434
444
|
dispatchToolCall: (call) => dispatchToolCall({
|
|
435
445
|
call,
|
|
436
446
|
registry,
|
|
437
|
-
context: {
|
|
447
|
+
context: {
|
|
448
|
+
sessionId: this.id,
|
|
449
|
+
runId,
|
|
450
|
+
toolCallId: call.id,
|
|
451
|
+
signal: controller.signal,
|
|
452
|
+
metadata,
|
|
453
|
+
identity: this.activeIdentity,
|
|
454
|
+
},
|
|
438
455
|
middleware: this.agent.config.middleware,
|
|
439
456
|
emit: (event) => this.emit(event),
|
|
440
457
|
permission: this.agent.config.permission,
|
|
@@ -442,6 +459,7 @@ class RuntimeAgentSession {
|
|
|
442
459
|
redactor: this.activeRedactor,
|
|
443
460
|
ledger: this.activeLedger,
|
|
444
461
|
ownership: this.activeOwnership,
|
|
462
|
+
identity: this.activeIdentity,
|
|
445
463
|
guardrails: this.activeGuardrails,
|
|
446
464
|
limitTracker: limits,
|
|
447
465
|
beforeExecute: async (mediatedCall) => {
|
|
@@ -577,6 +595,7 @@ class RuntimeAgentSession {
|
|
|
577
595
|
finally {
|
|
578
596
|
this.activeLedger = undefined;
|
|
579
597
|
this.activeOwnership = undefined;
|
|
598
|
+
this.activeIdentity = undefined;
|
|
580
599
|
this.activeIdempotencyKey = undefined;
|
|
581
600
|
this.activeGuardrails = undefined;
|
|
582
601
|
this.activeMetadata = undefined;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { OwnershipScope } from "./contracts.js";
|
|
2
|
+
/**
|
|
3
|
+
* Durable artifact co-work review types (Phase 9 / 0.0.14). Core exports types only;
|
|
4
|
+
* the service + delivery-link signer live in `@arnilo/prism-server`. Prism persists bounded
|
|
5
|
+
* metadata, revisions, approvals, and delivery references — never file bodies (hosts own blobs).
|
|
6
|
+
*/
|
|
7
|
+
/** Review state of an artifact's latest revision. */
|
|
8
|
+
export type ArtifactApprovalState = "pending" | "approved" | "rejected";
|
|
9
|
+
/** A resolved decision on one revision (pending is the absence of a decision). */
|
|
10
|
+
export type ArtifactDecisionState = Exclude<ArtifactApprovalState, "pending">;
|
|
11
|
+
/** Bounded citation / data-source reference. Host resolves the body; Prism stores the ref only. */
|
|
12
|
+
export interface ArtifactCitation {
|
|
13
|
+
readonly uri: string;
|
|
14
|
+
readonly title?: string;
|
|
15
|
+
/** Data-source kind (e.g. "web", "database", "upload"); host-defined, bounded. */
|
|
16
|
+
readonly kind?: string;
|
|
17
|
+
}
|
|
18
|
+
/** One immutable revision of an artifact. `uri`/`hash` reference host-owned content. */
|
|
19
|
+
export interface ArtifactRevision {
|
|
20
|
+
/** 1-based, monotonic within the artifact. */
|
|
21
|
+
readonly version: number;
|
|
22
|
+
/** Host-owned blob reference (redacted; never a local filesystem path). */
|
|
23
|
+
readonly uri: string;
|
|
24
|
+
readonly mime: string;
|
|
25
|
+
/** Host-computed content hash for integrity compare. */
|
|
26
|
+
readonly hash: string;
|
|
27
|
+
readonly changeNote?: string;
|
|
28
|
+
/** Run that produced this revision, if any. */
|
|
29
|
+
readonly producerRunId?: string;
|
|
30
|
+
readonly citations?: readonly ArtifactCitation[];
|
|
31
|
+
/** Preview metadata only; the host renders content. */
|
|
32
|
+
readonly preview?: Readonly<Record<string, unknown>>;
|
|
33
|
+
readonly createdAt: string;
|
|
34
|
+
}
|
|
35
|
+
/** A reviewer decision on a specific revision. */
|
|
36
|
+
export interface ArtifactApproval {
|
|
37
|
+
readonly version: number;
|
|
38
|
+
readonly state: ArtifactDecisionState;
|
|
39
|
+
/** Redacted reviewer actor reference. */
|
|
40
|
+
readonly reviewer: string;
|
|
41
|
+
/** Change-request / rejection note. */
|
|
42
|
+
readonly note?: string;
|
|
43
|
+
readonly decidedAt: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Durable artifact record. Stored as a versioned checkpoint value; the checkpoint version
|
|
47
|
+
* is the CAS counter for concurrent reviewers, distinct from revision numbers.
|
|
48
|
+
*/
|
|
49
|
+
export interface ArtifactRecord extends OwnershipScope {
|
|
50
|
+
readonly id: string;
|
|
51
|
+
readonly threadId: string;
|
|
52
|
+
readonly title?: string;
|
|
53
|
+
readonly revisions: readonly ArtifactRevision[];
|
|
54
|
+
readonly approvals: readonly ArtifactApproval[];
|
|
55
|
+
/** Last approved revision; remains recoverable after a later rejection. */
|
|
56
|
+
readonly lastValidatedVersion?: number;
|
|
57
|
+
readonly createdAt: string;
|
|
58
|
+
readonly updatedAt: string;
|
|
59
|
+
}
|
|
60
|
+
/** Signed, expiring delivery authorization. Reauthorized per download; never a bearer secret. */
|
|
61
|
+
export interface ArtifactDeliveryToken extends OwnershipScope {
|
|
62
|
+
readonly artifactId: string;
|
|
63
|
+
readonly threadId: string;
|
|
64
|
+
readonly version: number;
|
|
65
|
+
readonly issuedAt: string;
|
|
66
|
+
readonly expiresAt: string;
|
|
67
|
+
}
|
|
68
|
+
/** Well-known checkpoint namespace for artifact records. */
|
|
69
|
+
export declare const ARTIFACT_CHECKPOINT_NAMESPACE = "prism.artifact";
|
|
70
|
+
export declare class ArtifactError extends Error {
|
|
71
|
+
readonly reason: string;
|
|
72
|
+
readonly code = "ERR_PRISM_ARTIFACT";
|
|
73
|
+
constructor(message: string, reason: string);
|
|
74
|
+
}
|
|
75
|
+
/** Checkpoint key for an artifact: thread-scoped so per-thread listing uses a key prefix. */
|
|
76
|
+
export declare function artifactCheckpointKey(threadId: string, artifactId: string): string;
|
|
77
|
+
/** Current review state: the decision on the latest revision, or pending when undecided. */
|
|
78
|
+
export declare function artifactApprovalState(record: ArtifactRecord): ArtifactApprovalState;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Well-known checkpoint namespace for artifact records. */
|
|
2
|
+
export const ARTIFACT_CHECKPOINT_NAMESPACE = "prism.artifact";
|
|
3
|
+
export class ArtifactError extends Error {
|
|
4
|
+
reason;
|
|
5
|
+
code = "ERR_PRISM_ARTIFACT";
|
|
6
|
+
constructor(message, reason) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.reason = reason;
|
|
9
|
+
this.name = "ArtifactError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** Checkpoint key for an artifact: thread-scoped so per-thread listing uses a key prefix. */
|
|
13
|
+
export function artifactCheckpointKey(threadId, artifactId) {
|
|
14
|
+
return `${threadId}:${artifactId}`;
|
|
15
|
+
}
|
|
16
|
+
/** Current review state: the decision on the latest revision, or pending when undecided. */
|
|
17
|
+
export function artifactApprovalState(record) {
|
|
18
|
+
const latest = record.revisions[record.revisions.length - 1];
|
|
19
|
+
if (latest === undefined)
|
|
20
|
+
return "pending";
|
|
21
|
+
const decision = record.approvals.find((approval) => approval.version === latest.version);
|
|
22
|
+
return decision?.state ?? "pending";
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=artifacts.js.map
|
package/dist/contracts.d.ts
CHANGED
|
@@ -287,6 +287,8 @@ export interface RunOptions {
|
|
|
287
287
|
readonly redactor?: SecretRedactor;
|
|
288
288
|
readonly runLedger?: RunLedger;
|
|
289
289
|
readonly ownership?: OwnershipScope;
|
|
290
|
+
/** Host-verified identity; when set, must project onto `ownership` without widening. */
|
|
291
|
+
readonly identity?: import("./identity.js").AgentIdentity;
|
|
290
292
|
readonly idempotencyKey?: string;
|
|
291
293
|
readonly validate?: ToolValidator;
|
|
292
294
|
readonly activeSkills?: readonly string[];
|
|
@@ -352,6 +354,8 @@ export interface AgentConfig {
|
|
|
352
354
|
readonly redactor?: SecretRedactor;
|
|
353
355
|
readonly runLedger?: RunLedger;
|
|
354
356
|
readonly ownership?: OwnershipScope;
|
|
357
|
+
/** Host-verified identity default for sessions created from this agent. */
|
|
358
|
+
readonly identity?: import("./identity.js").AgentIdentity;
|
|
355
359
|
readonly idempotencyKey?: string;
|
|
356
360
|
readonly compaction?: false | CompactionOptions;
|
|
357
361
|
readonly retry?: false | RetryOptions;
|
|
@@ -369,7 +373,7 @@ export interface AgentConfig {
|
|
|
369
373
|
readonly secure?: true;
|
|
370
374
|
}
|
|
371
375
|
/** Opt-in fail-closed composition over the normal explicit AgentConfig API. */
|
|
372
|
-
export interface SecureAgentOptions extends Omit<AgentConfig, "tools" | "validator" | "redactor" | "permission" | "trust" | "ownership" | "limits" | "runState" | "secure"> {
|
|
376
|
+
export interface SecureAgentOptions extends Omit<AgentConfig, "tools" | "validator" | "redactor" | "permission" | "trust" | "ownership" | "identity" | "limits" | "runState" | "secure"> {
|
|
373
377
|
readonly id: string;
|
|
374
378
|
readonly tools: readonly ToolDefinition[];
|
|
375
379
|
readonly toolArgumentValidator: import("./tools.js").ToolArgumentValidator;
|
|
@@ -377,6 +381,8 @@ export interface SecureAgentOptions extends Omit<AgentConfig, "tools" | "validat
|
|
|
377
381
|
readonly permission: PermissionPolicy;
|
|
378
382
|
readonly trust: TrustPolicy;
|
|
379
383
|
readonly ownership: OwnershipScope;
|
|
384
|
+
/** Optional host-verified identity; when set must match `ownership`. */
|
|
385
|
+
readonly identity?: import("./identity.js").AgentIdentity;
|
|
380
386
|
readonly limits: RunLimits;
|
|
381
387
|
readonly definitionRevision: string;
|
|
382
388
|
readonly runState: Omit<AgentRunStateOptions, "definitionRevision" | "interruptBeforeTool">;
|
|
@@ -750,6 +756,8 @@ export interface ToolExecutionContext {
|
|
|
750
756
|
readonly toolCallId: string;
|
|
751
757
|
readonly signal?: AbortSignal;
|
|
752
758
|
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
759
|
+
/** Host-verified identity for this tool invocation, when enterprise identity is active. */
|
|
760
|
+
readonly identity?: import("./identity.js").AgentIdentity;
|
|
753
761
|
progress?(progress?: unknown, metadata?: Readonly<Record<string, unknown>>): void | Promise<void>;
|
|
754
762
|
}
|
|
755
763
|
export interface ToolResult {
|
|
@@ -900,6 +908,9 @@ export interface ExtensionEvent {
|
|
|
900
908
|
export interface Extension {
|
|
901
909
|
readonly name: string;
|
|
902
910
|
setup(api: ExtensionAPI): void | Promise<void>;
|
|
911
|
+
/** Host-attested signature/digest for `ExtensionLoadPolicy.verifySignature`. */
|
|
912
|
+
readonly signature?: string;
|
|
913
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
903
914
|
}
|
|
904
915
|
export interface ProviderPackage {
|
|
905
916
|
readonly name: string;
|
|
@@ -957,6 +968,8 @@ export interface OAuthProvider {
|
|
|
957
968
|
readonly id: string;
|
|
958
969
|
login(callbacks?: OAuthLoginCallbacks): Promise<OAuthCredentials> | OAuthCredentials;
|
|
959
970
|
refresh?(credentials: OAuthCredentials): Promise<OAuthCredentials> | OAuthCredentials;
|
|
971
|
+
/** Best-effort upstream revocation; the store delete is what fails closed locally. */
|
|
972
|
+
revoke?(credentials: OAuthCredentials): Promise<void> | void;
|
|
960
973
|
getCredential?(credentials: OAuthCredentials): Promise<Credential | undefined> | Credential | undefined;
|
|
961
974
|
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
962
975
|
}
|
|
@@ -1482,16 +1495,21 @@ export interface MigrationRecord {
|
|
|
1482
1495
|
}
|
|
1483
1496
|
/** Query for sessions. */
|
|
1484
1497
|
export interface SessionQuery extends PersistenceQuery, OwnershipScope {
|
|
1498
|
+
readonly id?: string;
|
|
1485
1499
|
readonly parentSessionId?: string;
|
|
1486
1500
|
readonly agentDefinitionId?: string;
|
|
1487
1501
|
readonly agentDefinitionVersion?: string;
|
|
1488
1502
|
readonly retentionPolicyId?: string;
|
|
1503
|
+
/** Match sessions whose `metadata` object contains this top-level key (e.g. conversation marker). */
|
|
1504
|
+
readonly metadataKey?: string;
|
|
1489
1505
|
readonly fromCreatedAt?: string;
|
|
1490
1506
|
readonly toCreatedAt?: string;
|
|
1491
1507
|
readonly fromUpdatedAt?: string;
|
|
1492
1508
|
readonly toUpdatedAt?: string;
|
|
1493
1509
|
readonly hasExpired?: boolean;
|
|
1494
1510
|
}
|
|
1511
|
+
/** Validate a top-level `SessionRecord.metadata` key used by `SessionQuery.metadataKey` filters. */
|
|
1512
|
+
export declare function assertSessionMetadataKey(key: string): string;
|
|
1495
1513
|
/** Query for session entries. */
|
|
1496
1514
|
export interface SessionEntryQuery extends PersistenceQuery, OwnershipScope {
|
|
1497
1515
|
readonly sessionId?: string;
|
|
@@ -1602,9 +1620,17 @@ export interface ProductionPersistenceStore {
|
|
|
1602
1620
|
queryAgentDefinitions(query: AgentDefinitionQuery): Promise<PersistencePage<AgentDefinitionRecord>>;
|
|
1603
1621
|
queryRetentionPolicies(query: RetentionPolicyQuery): Promise<PersistencePage<RetentionPolicy>>;
|
|
1604
1622
|
queryMigrations(query: MigrationQuery): Promise<PersistencePage<MigrationRecord>>;
|
|
1623
|
+
/** Optional session-record write capability (conversation threads, host-managed sessions).
|
|
1624
|
+
* Upserts by id; ownership columns are set on create, `metadata`/`updatedAt` on update. */
|
|
1625
|
+
appendSession?(record: SessionRecord): Promise<void>;
|
|
1605
1626
|
/** DB-friendly branch read (mirrors `SessionStore.readBranchPath`): one ancestor-chain
|
|
1606
1627
|
* query instead of `queryEntries({ sessionId })` + in-memory walk. Optional. */
|
|
1607
1628
|
readBranchPath?(query: SessionBranchRead): Promise<PersistencePage<SessionEntry>>;
|
|
1629
|
+
/**
|
|
1630
|
+
* Optional Phase 8 retention / legal-hold / export / tenant-quota lifecycle.
|
|
1631
|
+
* Prefer attaching `createMemoryPersistenceLifecycle()` or adapter-native methods.
|
|
1632
|
+
*/
|
|
1633
|
+
readonly lifecycle?: import("./persistence-lifecycle.js").PersistenceLifecycleStore;
|
|
1608
1634
|
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
1609
1635
|
}
|
|
1610
1636
|
export interface CompactionStrategy {
|
|
@@ -1796,3 +1822,11 @@ export interface ArtifactParseResult<T> {
|
|
|
1796
1822
|
export type ArtifactParser<T> = (text: string, ctx: ArtifactContext) => ArtifactParseResult<T> | Promise<ArtifactParseResult<T>>;
|
|
1797
1823
|
export type ArtifactValidator<T> = (value: T, ctx: ArtifactContext) => ArtifactValidation | Promise<ArtifactValidation>;
|
|
1798
1824
|
export type ArtifactRepairer<T> = (value: T | undefined, failure: ArtifactValidation, ctx: ArtifactContext) => AgentInput | Promise<AgentInput>;
|
|
1825
|
+
/** Alias re-exports so `dist/contracts.d.ts` exposes implementer contract names. */
|
|
1826
|
+
export type AgentIdentity = import("./identity.js").AgentIdentity;
|
|
1827
|
+
export type Principal = import("./identity.js").Principal;
|
|
1828
|
+
export type IdentityVerifier = import("./identity.js").IdentityVerifier;
|
|
1829
|
+
export type PersistenceLifecycleStore = import("./persistence-lifecycle.js").PersistenceLifecycleStore;
|
|
1830
|
+
export type LegalHoldRecord = import("./persistence-lifecycle.js").LegalHoldRecord;
|
|
1831
|
+
export type TenantQuota = import("./persistence-lifecycle.js").TenantQuota;
|
|
1832
|
+
export type PersistenceResourceKind = import("./persistence-lifecycle.js").PersistenceResourceKind;
|
package/dist/contracts.js
CHANGED
|
@@ -128,4 +128,12 @@ export class SessionAppendConflictError extends Error {
|
|
|
128
128
|
export function isSessionAppendConflict(error) {
|
|
129
129
|
return error instanceof Error && error.code === SESSION_APPEND_CONFLICT_CODE;
|
|
130
130
|
}
|
|
131
|
+
const SESSION_METADATA_KEY_PATTERN = /^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/;
|
|
132
|
+
/** Validate a top-level `SessionRecord.metadata` key used by `SessionQuery.metadataKey` filters. */
|
|
133
|
+
export function assertSessionMetadataKey(key) {
|
|
134
|
+
if (typeof key !== "string" || !SESSION_METADATA_KEY_PATTERN.test(key)) {
|
|
135
|
+
throw new RangeError("metadataKey must match /^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/");
|
|
136
|
+
}
|
|
137
|
+
return key;
|
|
138
|
+
}
|
|
131
139
|
//# sourceMappingURL=contracts.js.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { OwnershipScope, SessionRecord } from "./contracts.js";
|
|
2
|
+
/** Conversation thread lifecycle state. Archive is soft; deletion goes through persistence lifecycle. */
|
|
3
|
+
export type ConversationThreadState = "active" | "archived";
|
|
4
|
+
/** Well-known `SessionRecord.metadata` key marking conversation threads. */
|
|
5
|
+
export declare const CONVERSATION_METADATA_KEY = "prismConversation";
|
|
6
|
+
export declare const DEFAULT_MAX_CONVERSATION_CURSOR_BYTES: number;
|
|
7
|
+
export declare const HARD_MAX_CONVERSATION_CURSOR_BYTES: number;
|
|
8
|
+
export interface ConversationBranchRef {
|
|
9
|
+
readonly leafId: string;
|
|
10
|
+
readonly createdAt: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Durable user-scoped conversation thread. A thread is an ownership-scoped session
|
|
14
|
+
* branch plus metadata; content lives in session entries and the redacted event ledger.
|
|
15
|
+
*/
|
|
16
|
+
export interface ConversationThread extends OwnershipScope {
|
|
17
|
+
readonly id: string;
|
|
18
|
+
readonly title?: string;
|
|
19
|
+
readonly state: ConversationThreadState;
|
|
20
|
+
readonly createdAt: string;
|
|
21
|
+
readonly updatedAt: string;
|
|
22
|
+
/** Branch leaves recorded by the conversation service; the entry tree remains the content source of truth. */
|
|
23
|
+
readonly branches: readonly ConversationBranchRef[];
|
|
24
|
+
/** Host-supplied create metadata; never credentials or raw transcripts. */
|
|
25
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
26
|
+
}
|
|
27
|
+
/** Opaque thread-bound replay cursor; prevents replaying a cursor minted for another thread. */
|
|
28
|
+
export interface ConversationReplayCursor {
|
|
29
|
+
readonly v: 1;
|
|
30
|
+
readonly threadId: string;
|
|
31
|
+
/** Opaque store keyset cursor; undefined means the start of the thread. */
|
|
32
|
+
readonly cursor?: string;
|
|
33
|
+
}
|
|
34
|
+
export declare class ConversationError extends Error {
|
|
35
|
+
readonly reason: string;
|
|
36
|
+
readonly code = "ERR_PRISM_CONVERSATION";
|
|
37
|
+
constructor(message: string, reason: string);
|
|
38
|
+
}
|
|
39
|
+
export declare function encodeConversationReplayCursor(cursor: ConversationReplayCursor): string;
|
|
40
|
+
export declare function decodeConversationReplayCursor(encoded: string, expectedThreadId: string, maxBytes?: number): ConversationReplayCursor;
|
|
41
|
+
/** Project a persisted session record into a conversation thread. Undefined for non-conversation sessions. */
|
|
42
|
+
export declare function conversationThreadFromRecord(record: SessionRecord): ConversationThread | undefined;
|
|
43
|
+
/** Serialize conversation marker metadata for `SessionRecord.metadata`. */
|
|
44
|
+
export declare function conversationMarkerMetadata(marker: {
|
|
45
|
+
readonly title?: string;
|
|
46
|
+
readonly state: ConversationThreadState;
|
|
47
|
+
readonly branches?: readonly ConversationBranchRef[];
|
|
48
|
+
readonly requestId?: string;
|
|
49
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
50
|
+
}): Readonly<Record<string, unknown>>;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/** Well-known `SessionRecord.metadata` key marking conversation threads. */
|
|
2
|
+
export const CONVERSATION_METADATA_KEY = "prismConversation";
|
|
3
|
+
export const DEFAULT_MAX_CONVERSATION_CURSOR_BYTES = 4 * 1024;
|
|
4
|
+
export const HARD_MAX_CONVERSATION_CURSOR_BYTES = 16 * 1024;
|
|
5
|
+
export class ConversationError extends Error {
|
|
6
|
+
reason;
|
|
7
|
+
code = "ERR_PRISM_CONVERSATION";
|
|
8
|
+
constructor(message, reason) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.reason = reason;
|
|
11
|
+
this.name = "ConversationError";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function encodeConversationReplayCursor(cursor) {
|
|
15
|
+
return Buffer.from(JSON.stringify(cursor), "utf8").toString("base64url");
|
|
16
|
+
}
|
|
17
|
+
export function decodeConversationReplayCursor(encoded, expectedThreadId, maxBytes = DEFAULT_MAX_CONVERSATION_CURSOR_BYTES) {
|
|
18
|
+
if (typeof encoded !== "string" || encoded.length === 0) {
|
|
19
|
+
throw new ConversationError("Replay cursor is required", "invalid_cursor");
|
|
20
|
+
}
|
|
21
|
+
if (Buffer.byteLength(encoded, "utf8") > maxBytes) {
|
|
22
|
+
throw new ConversationError("Replay cursor exceeds byte limit", "cursor_too_large");
|
|
23
|
+
}
|
|
24
|
+
let parsed;
|
|
25
|
+
try {
|
|
26
|
+
parsed = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8"));
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
throw new ConversationError("Replay cursor is invalid", "invalid_cursor");
|
|
30
|
+
}
|
|
31
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
32
|
+
throw new ConversationError("Replay cursor is invalid", "invalid_cursor");
|
|
33
|
+
}
|
|
34
|
+
const cursor = parsed;
|
|
35
|
+
if (cursor.v !== 1 || typeof cursor.threadId !== "string" || cursor.threadId.length === 0) {
|
|
36
|
+
throw new ConversationError("Replay cursor is invalid", "invalid_cursor");
|
|
37
|
+
}
|
|
38
|
+
if (cursor.threadId !== expectedThreadId) {
|
|
39
|
+
throw new ConversationError("Replay cursor belongs to another thread", "cursor_thread_mismatch");
|
|
40
|
+
}
|
|
41
|
+
if (cursor.cursor !== undefined && (typeof cursor.cursor !== "string" || cursor.cursor.length === 0)) {
|
|
42
|
+
throw new ConversationError("Replay cursor is invalid", "invalid_cursor");
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
v: 1,
|
|
46
|
+
threadId: cursor.threadId,
|
|
47
|
+
...(cursor.cursor === undefined ? {} : { cursor: cursor.cursor }),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** Project a persisted session record into a conversation thread. Undefined for non-conversation sessions. */
|
|
51
|
+
export function conversationThreadFromRecord(record) {
|
|
52
|
+
const marker = record.metadata?.[CONVERSATION_METADATA_KEY];
|
|
53
|
+
if (!marker || typeof marker !== "object" || Array.isArray(marker))
|
|
54
|
+
return undefined;
|
|
55
|
+
const value = marker;
|
|
56
|
+
const branches = [];
|
|
57
|
+
if (Array.isArray(value.branches)) {
|
|
58
|
+
for (const item of value.branches) {
|
|
59
|
+
if (item && typeof item === "object" &&
|
|
60
|
+
typeof item.leafId === "string" &&
|
|
61
|
+
typeof item.createdAt === "string") {
|
|
62
|
+
branches.push({
|
|
63
|
+
leafId: item.leafId,
|
|
64
|
+
createdAt: item.createdAt,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const metadata = value.metadata && typeof value.metadata === "object" && !Array.isArray(value.metadata)
|
|
70
|
+
? value.metadata
|
|
71
|
+
: undefined;
|
|
72
|
+
return {
|
|
73
|
+
id: record.id,
|
|
74
|
+
...(record.tenantId !== undefined ? { tenantId: record.tenantId } : {}),
|
|
75
|
+
...(record.accountId !== undefined ? { accountId: record.accountId } : {}),
|
|
76
|
+
...(record.userId !== undefined ? { userId: record.userId } : {}),
|
|
77
|
+
...(typeof value.title === "string" && value.title.length > 0 ? { title: value.title } : {}),
|
|
78
|
+
state: value.state === "archived" ? "archived" : "active",
|
|
79
|
+
createdAt: record.createdAt,
|
|
80
|
+
updatedAt: record.updatedAt,
|
|
81
|
+
branches: Object.freeze(branches),
|
|
82
|
+
...(metadata === undefined ? {} : { metadata }),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/** Serialize conversation marker metadata for `SessionRecord.metadata`. */
|
|
86
|
+
export function conversationMarkerMetadata(marker) {
|
|
87
|
+
return {
|
|
88
|
+
[CONVERSATION_METADATA_KEY]: {
|
|
89
|
+
...(marker.title === undefined ? {} : { title: marker.title }),
|
|
90
|
+
state: marker.state,
|
|
91
|
+
...(marker.branches === undefined || marker.branches.length === 0 ? {} : { branches: marker.branches }),
|
|
92
|
+
...(marker.requestId === undefined ? {} : { requestId: marker.requestId }),
|
|
93
|
+
...(marker.metadata === undefined ? {} : { metadata: marker.metadata }),
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=conversations.js.map
|
package/dist/credentials.d.ts
CHANGED
|
@@ -19,4 +19,18 @@ export declare function refreshOAuthCredential(options: {
|
|
|
19
19
|
readonly credentials: OAuthCredentials;
|
|
20
20
|
readonly store?: OAuthCredentialStore;
|
|
21
21
|
}): Promise<OAuthCredentials>;
|
|
22
|
+
/** A credential store that can also remove entries (revocation fails closed on the delete). */
|
|
23
|
+
export interface RevocableOAuthCredentialStore extends OAuthCredentialStore {
|
|
24
|
+
delete(provider: string, accountId?: string): Promise<boolean> | boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Revokes an OAuth credential: best-effort upstream revocation, then a mandatory local
|
|
28
|
+
* store delete so subsequent connector calls fail closed. The local delete is the trust
|
|
29
|
+
* boundary — an upstream revoke failure never leaves a stored token usable.
|
|
30
|
+
*/
|
|
31
|
+
export declare function revokeOAuthCredential(options: {
|
|
32
|
+
readonly provider: OAuthProvider;
|
|
33
|
+
readonly credentials: OAuthCredentials;
|
|
34
|
+
readonly store?: RevocableOAuthCredentialStore;
|
|
35
|
+
}): Promise<void>;
|
|
22
36
|
export declare function resolveCredentialValue(source: CredentialValueSource | undefined, request: CredentialRequest): Promise<string | undefined>;
|
package/dist/credentials.js
CHANGED
|
@@ -48,6 +48,15 @@ export async function refreshOAuthCredential(options) {
|
|
|
48
48
|
await options.store?.set(options.provider.id, refreshed);
|
|
49
49
|
return refreshed;
|
|
50
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Revokes an OAuth credential: best-effort upstream revocation, then a mandatory local
|
|
53
|
+
* store delete so subsequent connector calls fail closed. The local delete is the trust
|
|
54
|
+
* boundary — an upstream revoke failure never leaves a stored token usable.
|
|
55
|
+
*/
|
|
56
|
+
export async function revokeOAuthCredential(options) {
|
|
57
|
+
await options.provider.revoke?.(options.credentials);
|
|
58
|
+
await options.store?.delete(options.provider.id, options.credentials.accountId);
|
|
59
|
+
}
|
|
51
60
|
function credentialMapKey(name, provider) {
|
|
52
61
|
return provider ? `${provider}:${name}` : name;
|
|
53
62
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device adapter contract (realtime voice / desktop OS control) — 0.0.14.
|
|
3
|
+
*
|
|
4
|
+
* Contracts + deny-by-default policy ONLY. No vendor voice or desktop-control
|
|
5
|
+
* implementation ships in 0.0.14 (demand-gated to 0.1.x). This module composes
|
|
6
|
+
* over the existing `PermissionPolicy` / `RunLimits` / redactor seams; it adds
|
|
7
|
+
* no second approval runtime and no device framework. Hosts implement
|
|
8
|
+
* `DeviceAdapter`, resolve a policy, and admit sessions through the fail-closed
|
|
9
|
+
* gate below. Conformance fixtures (denial/approval/stream-bounds/redaction)
|
|
10
|
+
* live in `runDevicePolicyConformance` for future vendor adapters to run.
|
|
11
|
+
*/
|
|
12
|
+
import type { RunLimits } from "./contracts.js";
|
|
13
|
+
import { type SecretRedactor } from "./redaction.js";
|
|
14
|
+
/** Audio / screenshot / stream chunk: 1 MiB default / 8 MiB hard. */
|
|
15
|
+
export declare const DEFAULT_DEVICE_MAX_CHUNK_BYTES: number;
|
|
16
|
+
export declare const HARD_DEVICE_MAX_CHUNK_BYTES: number;
|
|
17
|
+
/** Concurrent device sessions per identity: 1 default / 4 hard. */
|
|
18
|
+
export declare const DEFAULT_DEVICE_MAX_CONCURRENT_SESSIONS = 1;
|
|
19
|
+
export declare const HARD_DEVICE_MAX_CONCURRENT_SESSIONS = 4;
|
|
20
|
+
export type DeviceKind = "voice" | "desktop-control";
|
|
21
|
+
export type DevicePolicyErrorCode = "ERR_PRISM_DEVICE_INPUT" | "ERR_PRISM_DEVICE_DISABLED" | "ERR_PRISM_DEVICE_APPROVAL" | "ERR_PRISM_DEVICE_SESSIONS" | "ERR_PRISM_DEVICE_CHUNK" | "ERR_PRISM_DEVICE_RUN_LIMITS";
|
|
22
|
+
export declare class DevicePolicyError extends Error {
|
|
23
|
+
readonly code: DevicePolicyErrorCode;
|
|
24
|
+
constructor(code: DevicePolicyErrorCode, message: string);
|
|
25
|
+
}
|
|
26
|
+
export interface DeviceStreamLimits {
|
|
27
|
+
readonly maxChunkBytes?: number;
|
|
28
|
+
readonly maxConcurrentSessions?: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Host-declared device adapter. `enabled` is deny-by-default: a device is
|
|
32
|
+
* admitted only when the host explicitly sets it `true` AND supplies a sandbox
|
|
33
|
+
* AND (when `requireApproval`) explicit per-side-effect approval.
|
|
34
|
+
*/
|
|
35
|
+
export interface DeviceAdapter {
|
|
36
|
+
readonly kind: DeviceKind;
|
|
37
|
+
readonly enabled: boolean;
|
|
38
|
+
readonly requireApproval: boolean;
|
|
39
|
+
readonly limits?: DeviceStreamLimits;
|
|
40
|
+
/** Host-owned sandbox identifier; admission fails closed without it. */
|
|
41
|
+
readonly sandbox?: string;
|
|
42
|
+
/** Host-owned network/egress policy identifier. */
|
|
43
|
+
readonly network?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface ResolvedDevicePolicy {
|
|
46
|
+
readonly kind: DeviceKind;
|
|
47
|
+
readonly enabled: boolean;
|
|
48
|
+
readonly requireApproval: boolean;
|
|
49
|
+
readonly maxChunkBytes: number;
|
|
50
|
+
readonly maxConcurrentSessions: number;
|
|
51
|
+
readonly sandbox?: string;
|
|
52
|
+
readonly network?: string;
|
|
53
|
+
/** Shared run accounting the device session must consume. */
|
|
54
|
+
readonly runLimits?: RunLimits;
|
|
55
|
+
}
|
|
56
|
+
export interface DevicePolicyOptions {
|
|
57
|
+
readonly maxChunkBytes?: number;
|
|
58
|
+
readonly maxConcurrentSessions?: number;
|
|
59
|
+
readonly runLimits?: RunLimits;
|
|
60
|
+
}
|
|
61
|
+
export declare function resolveDevicePolicy(adapter: DeviceAdapter, options?: DevicePolicyOptions): ResolvedDevicePolicy;
|
|
62
|
+
export interface DeviceAdmitRequest {
|
|
63
|
+
/** Explicit host approval for this device side effect. */
|
|
64
|
+
readonly approved: boolean;
|
|
65
|
+
/** Currently active device sessions for this identity. */
|
|
66
|
+
readonly activeSessions: number;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Fail-closed admission gate. Denies unless the device is explicitly enabled,
|
|
70
|
+
* sandboxed, approved (when required), under the concurrent-session budget, and
|
|
71
|
+
* bound to shared run accounting. Side effects never replay after reconnect:
|
|
72
|
+
* hosts must re-admit on every resume.
|
|
73
|
+
*/
|
|
74
|
+
export declare function assertDeviceAdmit(policy: ResolvedDevicePolicy, request: DeviceAdmitRequest): void;
|
|
75
|
+
export interface DeviceChunkResult {
|
|
76
|
+
readonly accepted: boolean;
|
|
77
|
+
readonly bytes: number;
|
|
78
|
+
/** Present when the chunk exceeded the stream bound and was dropped. */
|
|
79
|
+
readonly marker?: "dropped_oversize";
|
|
80
|
+
}
|
|
81
|
+
/** Stream bound: oversize audio/screenshot/stream chunks are dropped with a marker, never forwarded. */
|
|
82
|
+
export declare function acceptDeviceChunk(policy: ResolvedDevicePolicy, bytes: number): DeviceChunkResult;
|
|
83
|
+
/** Telemetry must be metadata-safe: apply the host redactor before any emit/persist. */
|
|
84
|
+
export declare function redactDeviceTelemetry<T>(redactor: SecretRedactor | undefined, telemetry: T): T;
|
|
85
|
+
export interface DeviceConformanceResult {
|
|
86
|
+
readonly passed: readonly string[];
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Conformance pair for future voice / desktop-control adapters. Runs the
|
|
90
|
+
* deny-by-default fixtures (denial, approval, stream bounds, session budget,
|
|
91
|
+
* run accounting, redaction) against a resolved policy and throws on any
|
|
92
|
+
* regression. Tested in 0.0.14 via fixtures only.
|
|
93
|
+
*/
|
|
94
|
+
export declare function runDevicePolicyConformance(adapter: DeviceAdapter, options?: DevicePolicyOptions): DeviceConformanceResult;
|