@peers-app/peers-sdk 0.19.14 → 0.20.1
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/dist/contracts/__tests__/builder.test.js +24 -0
- package/dist/contracts/__tests__/contract-events.test.d.ts +1 -0
- package/dist/contracts/__tests__/contract-events.test.js +199 -0
- package/dist/contracts/__tests__/contract-observables.test.d.ts +1 -0
- package/dist/contracts/__tests__/contract-observables.test.js +290 -0
- package/dist/contracts/__tests__/contract-provider-router.test.d.ts +1 -0
- package/dist/contracts/__tests__/contract-provider-router.test.js +193 -0
- package/dist/contracts/__tests__/contract-proxy.test.d.ts +1 -0
- package/dist/contracts/__tests__/contract-proxy.test.js +424 -0
- package/dist/contracts/__tests__/contract-resolvers.test.d.ts +1 -0
- package/dist/contracts/__tests__/contract-resolvers.test.js +148 -0
- package/dist/contracts/__tests__/contract-subscription-lifecycle.test.d.ts +1 -0
- package/dist/contracts/__tests__/contract-subscription-lifecycle.test.js +353 -0
- package/dist/contracts/__tests__/contract-table-events.test.d.ts +1 -0
- package/dist/contracts/__tests__/contract-table-events.test.js +209 -0
- package/dist/contracts/__tests__/contract-transport.test.d.ts +1 -0
- package/dist/contracts/__tests__/contract-transport.test.js +163 -0
- package/dist/contracts/__tests__/persistent-registry.test.d.ts +1 -0
- package/dist/contracts/__tests__/persistent-registry.test.js +109 -0
- package/dist/contracts/__tests__/playground.test.d.ts +1 -0
- package/dist/contracts/__tests__/playground.test.js +213 -0
- package/dist/contracts/__tests__/validate.test.js +122 -0
- package/dist/contracts/builder.d.ts +9 -1
- package/dist/contracts/builder.js +13 -0
- package/dist/contracts/contract-provider-router.d.ts +72 -0
- package/dist/contracts/contract-provider-router.js +164 -0
- package/dist/contracts/contract-proxy.d.ts +333 -0
- package/dist/contracts/contract-proxy.js +663 -0
- package/dist/contracts/contract-resolvers.d.ts +66 -0
- package/dist/contracts/contract-resolvers.js +138 -0
- package/dist/contracts/contract-transport.d.ts +94 -0
- package/dist/contracts/contract-transport.js +159 -0
- package/dist/contracts/contracts.table.d.ts +1 -1
- package/dist/contracts/contracts.table.js +2 -2
- package/dist/contracts/index.d.ts +7 -1
- package/dist/contracts/index.js +34 -1
- package/dist/contracts/persistent-registry.js +3 -1
- package/dist/contracts/system/device-operations-contract.d.ts +72 -0
- package/dist/contracts/system/device-operations-contract.js +110 -0
- package/dist/contracts/system/logs-contract.d.ts +24 -0
- package/dist/contracts/system/logs-contract.js +60 -0
- package/dist/contracts/types.d.ts +27 -4
- package/dist/contracts/validate.d.ts +2 -2
- package/dist/contracts/validate.js +44 -2
- package/dist/data/assistants.d.ts +4 -4
- package/dist/data/channels.d.ts +1 -1
- package/dist/data/devices.d.ts +1 -1
- package/dist/data/embeddings.d.ts +1 -1
- package/dist/data/group-secret.d.ts +21 -0
- package/dist/data/group-secret.js +53 -0
- package/dist/data/index.d.ts +1 -0
- package/dist/data/index.js +1 -0
- package/dist/data/messages.d.ts +1 -1
- package/dist/data/orm/decorators.d.ts +6 -0
- package/dist/data/orm/decorators.js +21 -0
- package/dist/data/package-versions.d.ts +2 -2
- package/dist/data/peer-types.d.ts +1 -1
- package/dist/data/persistent-vars.d.ts +17 -0
- package/dist/data/persistent-vars.js +115 -35
- package/dist/data/persistent-vars.migration.test.d.ts +1 -0
- package/dist/data/persistent-vars.migration.test.js +133 -0
- package/dist/data/table-definitions-table.d.ts +1 -1
- package/dist/data/tool-tests.d.ts +1 -1
- package/dist/data/tools.d.ts +1 -1
- package/dist/data/user-trust-levels.d.ts +3 -1
- package/dist/data/user-trust-levels.js +2 -1
- package/dist/data/user-trust-levels.test.d.ts +1 -0
- package/dist/data/user-trust-levels.test.js +37 -0
- package/dist/data/voice-messages.d.ts +1 -1
- package/dist/data/workflow-logs.d.ts +1 -1
- package/dist/data/workflow-runs.d.ts +2 -2
- package/dist/data/workflows.d.ts +3 -3
- package/dist/device/binary-peer-connection-v2.d.ts +2 -0
- package/dist/device/binary-peer-connection-v2.js +12 -2
- package/dist/device/binary-peer-connection-v2.test.js +23 -0
- package/dist/device/get-trust-level-fn.d.ts +6 -0
- package/dist/device/get-trust-level-fn.js +12 -7
- package/dist/device/get-trust-level-fn.test.js +16 -2
- package/dist/logging/console-logs.table.d.ts +3 -0
- package/dist/logging/console-logs.table.js +2 -1
- package/dist/rpc-types.d.ts +37 -0
- package/dist/rpc-types.js +13 -0
- package/dist/system-ids.d.ts +25 -0
- package/dist/system-ids.js +26 -1
- package/dist/types/workflow.d.ts +4 -4
- package/package.json +1 -1
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { ITool } from "../../data/tools";
|
|
2
|
+
import type { IContractDefinition } from "../types";
|
|
3
|
+
/** Version of the built-in System Device Operations contract. */
|
|
4
|
+
export declare const DEVICE_OPERATIONS_CONTRACT_VERSION = 1;
|
|
5
|
+
/** Maximum SQL text accepted by the remote database operation. */
|
|
6
|
+
export declare const DEVICE_OPERATIONS_MAX_QUERY_LENGTH = 20000;
|
|
7
|
+
/** Maximum rows returned by one remote database operation. */
|
|
8
|
+
export declare const DEVICE_OPERATIONS_MAX_ROWS = 500;
|
|
9
|
+
/** Maximum serialized result size returned by one remote database operation. */
|
|
10
|
+
export declare const DEVICE_OPERATIONS_MAX_RESULT_BYTES = 1000000;
|
|
11
|
+
/** Maximum tools returned by one remote tool-list operation. */
|
|
12
|
+
export declare const DEVICE_OPERATIONS_MAX_TOOLS = 100;
|
|
13
|
+
/** Stable IDs for the live tools implementing System Device Operations v1. */
|
|
14
|
+
export declare const deviceOperationsToolIds: {
|
|
15
|
+
readonly getDeviceStatus: "00mriijkhr4iptdefp4a7ifcq";
|
|
16
|
+
readonly queryDatabase: "00mriijkhrd54n33ey0omeejo";
|
|
17
|
+
readonly listTools: "00mriijkhr4fpyd70nyo5iqlq";
|
|
18
|
+
readonly getTool: "00mriijkhrid4wpf89i4ikvay";
|
|
19
|
+
readonly runTool: "00mriijkhrfequch2qaeoihol";
|
|
20
|
+
};
|
|
21
|
+
/** Portable operations supported by System Device Operations v1. */
|
|
22
|
+
export type DeviceOperationCapability = "device-status" | "database-query" | "tool-list" | "tool-get" | "tool-run";
|
|
23
|
+
/** Status and capability information returned by a remote device. */
|
|
24
|
+
export interface IDeviceOperationStatus {
|
|
25
|
+
deviceId: string;
|
|
26
|
+
userId: string;
|
|
27
|
+
dataContextId: string;
|
|
28
|
+
contractVersion: number;
|
|
29
|
+
capabilities: DeviceOperationCapability[];
|
|
30
|
+
limits: {
|
|
31
|
+
maxQueryLength: number;
|
|
32
|
+
maxRows: number;
|
|
33
|
+
maxResultBytes: number;
|
|
34
|
+
maxTools: number;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** Input for a bounded, read-only remote SQLite query. */
|
|
38
|
+
export interface IDeviceDatabaseQueryInput {
|
|
39
|
+
query: string;
|
|
40
|
+
}
|
|
41
|
+
/** Serializable result from a bounded, read-only remote SQLite query. */
|
|
42
|
+
export interface IDeviceDatabaseQueryResult {
|
|
43
|
+
columns: string[];
|
|
44
|
+
rows: unknown[][];
|
|
45
|
+
rowCount: number;
|
|
46
|
+
truncated: boolean;
|
|
47
|
+
}
|
|
48
|
+
/** Input for listing tools available in the selected data context. */
|
|
49
|
+
export interface IDeviceToolListInput {
|
|
50
|
+
limit?: number;
|
|
51
|
+
}
|
|
52
|
+
/** Input for exact-ID, exact-name, or unambiguous-text tool lookup. */
|
|
53
|
+
export interface IDeviceToolLookupInput {
|
|
54
|
+
toolIdOrName: string;
|
|
55
|
+
}
|
|
56
|
+
/** Input for running a tool on the remote device. */
|
|
57
|
+
export interface IDeviceToolRunInput extends IDeviceToolLookupInput {
|
|
58
|
+
args?: Record<string, unknown>;
|
|
59
|
+
assistantId?: string;
|
|
60
|
+
}
|
|
61
|
+
/** Result of an unambiguous tool lookup, or `null` when no tool matched. */
|
|
62
|
+
export type IDeviceToolLookupResult = ITool | null;
|
|
63
|
+
/**
|
|
64
|
+
* Return the portable, owner-authorized device administration contract shape.
|
|
65
|
+
*
|
|
66
|
+
* The contract intentionally exposes explicit operations instead of arbitrary table,
|
|
67
|
+
* filesystem, shell, UI, or lifecycle access. Authorization is supplied by the verified
|
|
68
|
+
* connection host before the live resolver is invoked.
|
|
69
|
+
*/
|
|
70
|
+
export declare function getDeviceOperationsContractDefinition(): IContractDefinition;
|
|
71
|
+
/** Package ID used by live System Device Operations tool instances. */
|
|
72
|
+
export declare const deviceOperationsProviderPackageId = "000peers0system0000000001";
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deviceOperationsProviderPackageId = exports.deviceOperationsToolIds = exports.DEVICE_OPERATIONS_MAX_TOOLS = exports.DEVICE_OPERATIONS_MAX_RESULT_BYTES = exports.DEVICE_OPERATIONS_MAX_ROWS = exports.DEVICE_OPERATIONS_MAX_QUERY_LENGTH = exports.DEVICE_OPERATIONS_CONTRACT_VERSION = void 0;
|
|
4
|
+
exports.getDeviceOperationsContractDefinition = getDeviceOperationsContractDefinition;
|
|
5
|
+
const system_ids_1 = require("../../system-ids");
|
|
6
|
+
const field_type_1 = require("../../types/field-type");
|
|
7
|
+
/** Version of the built-in System Device Operations contract. */
|
|
8
|
+
exports.DEVICE_OPERATIONS_CONTRACT_VERSION = 1;
|
|
9
|
+
/** Maximum SQL text accepted by the remote database operation. */
|
|
10
|
+
exports.DEVICE_OPERATIONS_MAX_QUERY_LENGTH = 20_000;
|
|
11
|
+
/** Maximum rows returned by one remote database operation. */
|
|
12
|
+
exports.DEVICE_OPERATIONS_MAX_ROWS = 500;
|
|
13
|
+
/** Maximum serialized result size returned by one remote database operation. */
|
|
14
|
+
exports.DEVICE_OPERATIONS_MAX_RESULT_BYTES = 1_000_000;
|
|
15
|
+
/** Maximum tools returned by one remote tool-list operation. */
|
|
16
|
+
exports.DEVICE_OPERATIONS_MAX_TOOLS = 100;
|
|
17
|
+
/** Stable IDs for the live tools implementing System Device Operations v1. */
|
|
18
|
+
exports.deviceOperationsToolIds = {
|
|
19
|
+
getDeviceStatus: "00mriijkhr4iptdefp4a7ifcq",
|
|
20
|
+
queryDatabase: "00mriijkhrd54n33ey0omeejo",
|
|
21
|
+
listTools: "00mriijkhr4fpyd70nyo5iqlq",
|
|
22
|
+
getTool: "00mriijkhrid4wpf89i4ikvay",
|
|
23
|
+
runTool: "00mriijkhrfequch2qaeoihol",
|
|
24
|
+
};
|
|
25
|
+
const field = (name, type, description, opts = {}) => ({ name, type, description, ...opts });
|
|
26
|
+
let definition;
|
|
27
|
+
/**
|
|
28
|
+
* Return the portable, owner-authorized device administration contract shape.
|
|
29
|
+
*
|
|
30
|
+
* The contract intentionally exposes explicit operations instead of arbitrary table,
|
|
31
|
+
* filesystem, shell, UI, or lifecycle access. Authorization is supplied by the verified
|
|
32
|
+
* connection host before the live resolver is invoked.
|
|
33
|
+
*/
|
|
34
|
+
function getDeviceOperationsContractDefinition() {
|
|
35
|
+
definition ??= {
|
|
36
|
+
contractId: system_ids_1.deviceOperationsContractId,
|
|
37
|
+
version: exports.DEVICE_OPERATIONS_CONTRACT_VERSION,
|
|
38
|
+
devTag: "dev",
|
|
39
|
+
name: "System Device Operations",
|
|
40
|
+
description: "Owner-authorized status, bounded read-only database, and installed-tool operations.",
|
|
41
|
+
tables: [],
|
|
42
|
+
tools: [
|
|
43
|
+
{
|
|
44
|
+
name: "getDeviceStatus",
|
|
45
|
+
usageDescription: "Return this device's identity, supported operations, and limits.",
|
|
46
|
+
inputFields: [],
|
|
47
|
+
outputFields: [
|
|
48
|
+
field("deviceId", field_type_1.FieldType.id, "The provider device ID."),
|
|
49
|
+
field("userId", field_type_1.FieldType.id, "The provider user ID."),
|
|
50
|
+
field("dataContextId", field_type_1.FieldType.id, "The selected data context ID."),
|
|
51
|
+
field("contractVersion", field_type_1.FieldType.number, "The supported contract version."),
|
|
52
|
+
field("capabilities", field_type_1.FieldType.string, "Supported portable operations.", {
|
|
53
|
+
isArray: true,
|
|
54
|
+
}),
|
|
55
|
+
field("limits", field_type_1.FieldType.object, "Provider-enforced request and result limits."),
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: "queryDatabase",
|
|
60
|
+
usageDescription: "Run one bounded read-only SELECT or approved PRAGMA query.",
|
|
61
|
+
inputFields: [field("query", field_type_1.FieldType.string, "One read-only SQLite statement.")],
|
|
62
|
+
outputFields: [
|
|
63
|
+
field("columns", field_type_1.FieldType.string, "Result column names.", { isArray: true }),
|
|
64
|
+
field("rows", field_type_1.FieldType.any, "Serializable result rows.", { isArray: true }),
|
|
65
|
+
field("rowCount", field_type_1.FieldType.number, "Number of returned rows."),
|
|
66
|
+
field("truncated", field_type_1.FieldType.boolean, "Whether rows were omitted by provider limits."),
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: "listTools",
|
|
71
|
+
usageDescription: "List installed tools in the selected data context.",
|
|
72
|
+
inputFields: [
|
|
73
|
+
field("limit", field_type_1.FieldType.number, "Maximum tools to return.", { optional: true }),
|
|
74
|
+
],
|
|
75
|
+
outputFields: [
|
|
76
|
+
field("tools", field_type_1.FieldType.object, "Installed tool definitions.", { isArray: true }),
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
name: "getTool",
|
|
81
|
+
usageDescription: "Resolve a tool by exact ID, exact name, or unambiguous text.",
|
|
82
|
+
inputFields: [
|
|
83
|
+
field("toolIdOrName", field_type_1.FieldType.string, "Tool ID, exact name, or search text."),
|
|
84
|
+
],
|
|
85
|
+
outputFields: [
|
|
86
|
+
field("tool", field_type_1.FieldType.object, "The matching tool definition, or null.", {
|
|
87
|
+
optional: true,
|
|
88
|
+
}),
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: "runTool",
|
|
93
|
+
usageDescription: "Resolve and run an installed tool in the selected data context.",
|
|
94
|
+
inputFields: [
|
|
95
|
+
field("toolIdOrName", field_type_1.FieldType.string, "Tool ID, exact name, or search text."),
|
|
96
|
+
field("args", field_type_1.FieldType.object, "Tool input arguments.", { optional: true }),
|
|
97
|
+
field("assistantId", field_type_1.FieldType.id, "Optional assistant execution context.", {
|
|
98
|
+
optional: true,
|
|
99
|
+
}),
|
|
100
|
+
],
|
|
101
|
+
outputFields: [field("result", field_type_1.FieldType.any, "The tool execution result.")],
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
observables: [],
|
|
105
|
+
events: [],
|
|
106
|
+
};
|
|
107
|
+
return definition;
|
|
108
|
+
}
|
|
109
|
+
/** Package ID used by live System Device Operations tool instances. */
|
|
110
|
+
exports.deviceOperationsProviderPackageId = system_ids_1.peersSystemPackageId;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { DataContext } from "../../context/data-context";
|
|
2
|
+
import type { IContractResolution } from "../contract-proxy";
|
|
3
|
+
import type { IContractDefinition } from "../types";
|
|
4
|
+
/** Version of the built-in System Logs contract. */
|
|
5
|
+
export declare const LOGS_CONTRACT_VERSION = 1;
|
|
6
|
+
/**
|
|
7
|
+
* The first built-in **system contract**: read and write the local device's console logs.
|
|
8
|
+
*
|
|
9
|
+
* It declares only the `ConsoleLogs` table — the table's own methods (`list`, `count`,
|
|
10
|
+
* `deleteOldLogs`, …) are the entire surface we need, so no bespoke tools are required.
|
|
11
|
+
* The table shape is derived from {@link consoleLogSchema} so the contract stays accurate.
|
|
12
|
+
*
|
|
13
|
+
* Built lazily and memoized: reading `consoleLogsMetaData` / `consoleLogSchema` at module
|
|
14
|
+
* load would race the import cycle between the logging table and the SDK barrel, so we defer
|
|
15
|
+
* construction until first use (well after all modules have finished initializing).
|
|
16
|
+
*/
|
|
17
|
+
export declare function getLogsContractDefinition(): IContractDefinition;
|
|
18
|
+
/**
|
|
19
|
+
* Resolve the logs contract to its live implementation for a data context: the
|
|
20
|
+
* `ConsoleLogs` table backing that context.
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveLogsContract(ctx: {
|
|
23
|
+
dataContext: DataContext;
|
|
24
|
+
}): IContractResolution;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LOGS_CONTRACT_VERSION = void 0;
|
|
4
|
+
exports.getLogsContractDefinition = getLogsContractDefinition;
|
|
5
|
+
exports.resolveLogsContract = resolveLogsContract;
|
|
6
|
+
const user_context_singleton_1 = require("../../context/user-context-singleton");
|
|
7
|
+
const types_1 = require("../../data/orm/types");
|
|
8
|
+
const console_logs_table_1 = require("../../logging/console-logs.table");
|
|
9
|
+
const system_ids_1 = require("../../system-ids");
|
|
10
|
+
const contract_resolvers_1 = require("../contract-resolvers");
|
|
11
|
+
/** Version of the built-in System Logs contract. */
|
|
12
|
+
exports.LOGS_CONTRACT_VERSION = 1;
|
|
13
|
+
let _definition;
|
|
14
|
+
/**
|
|
15
|
+
* The first built-in **system contract**: read and write the local device's console logs.
|
|
16
|
+
*
|
|
17
|
+
* It declares only the `ConsoleLogs` table — the table's own methods (`list`, `count`,
|
|
18
|
+
* `deleteOldLogs`, …) are the entire surface we need, so no bespoke tools are required.
|
|
19
|
+
* The table shape is derived from {@link consoleLogSchema} so the contract stays accurate.
|
|
20
|
+
*
|
|
21
|
+
* Built lazily and memoized: reading `consoleLogsMetaData` / `consoleLogSchema` at module
|
|
22
|
+
* load would race the import cycle between the logging table and the SDK barrel, so we defer
|
|
23
|
+
* construction until first use (well after all modules have finished initializing).
|
|
24
|
+
*/
|
|
25
|
+
function getLogsContractDefinition() {
|
|
26
|
+
if (!_definition) {
|
|
27
|
+
_definition = {
|
|
28
|
+
contractId: system_ids_1.logsContractId,
|
|
29
|
+
version: exports.LOGS_CONTRACT_VERSION,
|
|
30
|
+
devTag: "dev",
|
|
31
|
+
name: "System Logs",
|
|
32
|
+
description: "Read and write the local device's console logs.",
|
|
33
|
+
tables: [
|
|
34
|
+
{
|
|
35
|
+
name: console_logs_table_1.consoleLogsMetaData.name,
|
|
36
|
+
description: console_logs_table_1.consoleLogsMetaData.description,
|
|
37
|
+
primaryKeyName: console_logs_table_1.consoleLogsMetaData.primaryKeyName,
|
|
38
|
+
fields: (0, types_1.schemaToFields)(console_logs_table_1.consoleLogSchema),
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
tools: [],
|
|
42
|
+
observables: [],
|
|
43
|
+
events: [],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return _definition;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Resolve the logs contract to its live implementation for a data context: the
|
|
50
|
+
* `ConsoleLogs` table backing that context.
|
|
51
|
+
*/
|
|
52
|
+
function resolveLogsContract(ctx) {
|
|
53
|
+
const consoleLogs = (0, user_context_singleton_1.getTableContainer)(ctx.dataContext).getTable(console_logs_table_1.consoleLogsMetaData, console_logs_table_1.consoleLogSchema, console_logs_table_1.ConsoleLogsTable);
|
|
54
|
+
return {
|
|
55
|
+
contractId: system_ids_1.logsContractId,
|
|
56
|
+
version: exports.LOGS_CONTRACT_VERSION,
|
|
57
|
+
tables: { [console_logs_table_1.consoleLogsMetaData.name]: consoleLogs },
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
(0, contract_resolvers_1.registerContractResolver)(system_ids_1.logsContractId, exports.LOGS_CONTRACT_VERSION, resolveLogsContract);
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { Table } from "../data/orm/table";
|
|
2
2
|
import type { ITableDefinition } from "../data/orm/table-definitions.type";
|
|
3
3
|
import type { IToolInstance } from "../data/tools";
|
|
4
|
+
import type { Event } from "../events";
|
|
4
5
|
import type { Observable } from "../observable";
|
|
5
6
|
import type { FieldType, IField } from "../types/field-type";
|
|
6
7
|
/**
|
|
7
|
-
* A versioned interface definition declaring the shape of tables, tools,
|
|
8
|
-
* observables that a package provides. Pure data — no executable code.
|
|
8
|
+
* A versioned interface definition declaring the shape of tables, tools,
|
|
9
|
+
* observables, and events that a package provides. Pure data — no executable code.
|
|
9
10
|
*/
|
|
10
11
|
export interface IContractDefinition {
|
|
11
12
|
contractId: string;
|
|
@@ -17,6 +18,12 @@ export interface IContractDefinition {
|
|
|
17
18
|
tables: IContractTable[];
|
|
18
19
|
tools: IContractTool[];
|
|
19
20
|
observables: IContractObservable[];
|
|
21
|
+
/**
|
|
22
|
+
* Events a provider may emit and consumers may subscribe to. Optional so
|
|
23
|
+
* existing contract definitions stay valid; the {@link ContractBuilder} always
|
|
24
|
+
* emits an array (possibly empty) and consumers read `contract.events ?? []`.
|
|
25
|
+
*/
|
|
26
|
+
events?: IContractEvent[];
|
|
20
27
|
}
|
|
21
28
|
/** Table shape within a contract — derived from ITableMetaData + IField[]. */
|
|
22
29
|
export interface IContractTable {
|
|
@@ -39,6 +46,18 @@ export interface IContractObservable {
|
|
|
39
46
|
valueType: FieldType;
|
|
40
47
|
writable: boolean;
|
|
41
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* A generic event a contract provider may emit. Consumers subscribe by name; the
|
|
51
|
+
* provider only forwards payloads over the transport while at least one consumer
|
|
52
|
+
* has an active subscription (see the provider session). Pure shape — the live
|
|
53
|
+
* {@link Event} is supplied at resolution time in {@link IContractResolution.events}.
|
|
54
|
+
*/
|
|
55
|
+
export interface IContractEvent {
|
|
56
|
+
name: string;
|
|
57
|
+
description: string;
|
|
58
|
+
/** Shape of the payload delivered to subscribers when the event fires. */
|
|
59
|
+
payloadFields: IField[];
|
|
60
|
+
}
|
|
42
61
|
/**
|
|
43
62
|
* A reference to a contract that a package wants to consume.
|
|
44
63
|
* Recorded during `definePackage` and checked at install time.
|
|
@@ -46,6 +65,7 @@ export interface IContractObservable {
|
|
|
46
65
|
export interface IConsumedContract {
|
|
47
66
|
contractId: string;
|
|
48
67
|
version: number;
|
|
68
|
+
optional?: boolean;
|
|
49
69
|
}
|
|
50
70
|
/**
|
|
51
71
|
* Declares that the owning contract's implementation also satisfies another
|
|
@@ -86,15 +106,18 @@ export interface IResolvedContract {
|
|
|
86
106
|
tables: Record<string, Table<any>>;
|
|
87
107
|
tools: Record<string, IToolInstance>;
|
|
88
108
|
observables: Record<string, Observable<any>>;
|
|
109
|
+
/** Live events the provider forwards from, keyed by contract event name. */
|
|
110
|
+
events?: Record<string, Event<any>>;
|
|
89
111
|
}
|
|
90
112
|
/** Outcome of a validation check. */
|
|
91
113
|
export interface IValidationResult {
|
|
92
114
|
valid: boolean;
|
|
93
115
|
errors: IValidationError[];
|
|
94
116
|
}
|
|
117
|
+
/** One incompatibility found while validating a contract definition or provider. */
|
|
95
118
|
export interface IValidationError {
|
|
96
|
-
/** Which element failed
|
|
97
|
-
kind: "table" | "tool" | "observable" | "contract" | "field";
|
|
119
|
+
/** Which contract element failed validation. */
|
|
120
|
+
kind: "table" | "tool" | "observable" | "event" | "contract" | "field";
|
|
98
121
|
/** Name of the element (table name, tool name, etc.) */
|
|
99
122
|
name: string;
|
|
100
123
|
message: string;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { IAlsoImplementsDeclaration, IContractDefinition, IValidationResult } from "./types";
|
|
2
2
|
/**
|
|
3
3
|
* Validate that an implementation contract satisfies a target contract shape.
|
|
4
|
-
* The implementation must be a superset: all contract tables, tools,
|
|
5
|
-
* observables must be present with compatible shapes.
|
|
4
|
+
* The implementation must be a superset: all contract tables, tools,
|
|
5
|
+
* observables, and events must be present with compatible shapes.
|
|
6
6
|
*/
|
|
7
7
|
export declare function validateProviderSatisfiesContract(impl: IContractDefinition, contract: IContractDefinition): IValidationResult;
|
|
8
8
|
/**
|
|
@@ -114,10 +114,36 @@ function validateToolFields(contractTool, implTool, direction) {
|
|
|
114
114
|
}
|
|
115
115
|
return errors;
|
|
116
116
|
}
|
|
117
|
+
function validateEventFields(contractEvent, implEvent) {
|
|
118
|
+
const errors = [];
|
|
119
|
+
const implFieldMap = new Map(implEvent.payloadFields.map((field) => [field.name, field]));
|
|
120
|
+
for (const contractField of contractEvent.payloadFields) {
|
|
121
|
+
const implField = implFieldMap.get(contractField.name);
|
|
122
|
+
if (!implField) {
|
|
123
|
+
if (!contractField.optional) {
|
|
124
|
+
errors.push({
|
|
125
|
+
kind: "field",
|
|
126
|
+
name: `${contractEvent.name}.payload.${contractField.name}`,
|
|
127
|
+
message: `Required payload field '${contractField.name}' missing from implementation event '${implEvent.name}'`,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const compat = isFieldCompatible(contractField, implField);
|
|
133
|
+
if (compat) {
|
|
134
|
+
errors.push({
|
|
135
|
+
kind: "field",
|
|
136
|
+
name: `${contractEvent.name}.payload.${contractField.name}`,
|
|
137
|
+
message: `Payload field '${contractField.name}' in event '${implEvent.name}': ${compat}`,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return errors;
|
|
142
|
+
}
|
|
117
143
|
/**
|
|
118
144
|
* Validate that an implementation contract satisfies a target contract shape.
|
|
119
|
-
* The implementation must be a superset: all contract tables, tools,
|
|
120
|
-
* observables must be present with compatible shapes.
|
|
145
|
+
* The implementation must be a superset: all contract tables, tools,
|
|
146
|
+
* observables, and events must be present with compatible shapes.
|
|
121
147
|
*/
|
|
122
148
|
function validateProviderSatisfiesContract(impl, contract) {
|
|
123
149
|
const errors = [];
|
|
@@ -184,6 +210,20 @@ function validateProviderSatisfiesContract(impl, contract) {
|
|
|
184
210
|
});
|
|
185
211
|
}
|
|
186
212
|
}
|
|
213
|
+
// Events
|
|
214
|
+
const implEventMap = new Map((impl.events ?? []).map((event) => [event.name, event]));
|
|
215
|
+
for (const contractEvent of contract.events ?? []) {
|
|
216
|
+
const implEvent = implEventMap.get(contractEvent.name);
|
|
217
|
+
if (!implEvent) {
|
|
218
|
+
errors.push({
|
|
219
|
+
kind: "event",
|
|
220
|
+
name: contractEvent.name,
|
|
221
|
+
message: `Event '${contractEvent.name}' required by contract but not provided by implementation`,
|
|
222
|
+
});
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
errors.push(...validateEventFields(contractEvent, implEvent));
|
|
226
|
+
}
|
|
187
227
|
return errors.length === 0 ? ok() : fail(errors);
|
|
188
228
|
}
|
|
189
229
|
/**
|
|
@@ -212,11 +252,13 @@ function validateImmutability(existing, incoming) {
|
|
|
212
252
|
tables: existing.tables,
|
|
213
253
|
tools: existing.tools,
|
|
214
254
|
observables: existing.observables,
|
|
255
|
+
events: existing.events ?? [],
|
|
215
256
|
});
|
|
216
257
|
const incomingShape = JSON.stringify({
|
|
217
258
|
tables: incoming.tables,
|
|
218
259
|
tools: incoming.tools,
|
|
219
260
|
observables: incoming.observables,
|
|
261
|
+
events: incoming.events ?? [],
|
|
220
262
|
});
|
|
221
263
|
if (existingShape !== incomingShape) {
|
|
222
264
|
return fail([
|
|
@@ -18,8 +18,8 @@ export declare const assistantSchema: z.ZodObject<{
|
|
|
18
18
|
packageId: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
|
|
19
19
|
}, "strip", z.ZodTypeAny, {
|
|
20
20
|
name: string;
|
|
21
|
-
createdAt: Date;
|
|
22
21
|
assistantId: string;
|
|
22
|
+
createdAt: Date;
|
|
23
23
|
assistantRunnerToolId: string;
|
|
24
24
|
assistantRunnerConfig: {} & {
|
|
25
25
|
[k: string]: any;
|
|
@@ -42,10 +42,10 @@ export declare const assistantSchema: z.ZodObject<{
|
|
|
42
42
|
toolInclusionStrategy?: ToolInclusionStrategy | undefined;
|
|
43
43
|
}>;
|
|
44
44
|
export type IAssistant = z.infer<typeof assistantSchema>;
|
|
45
|
-
export declare function Assistants(dataContext?: DataContext): import("
|
|
45
|
+
export declare function Assistants(dataContext?: DataContext): import("..").Table<{
|
|
46
46
|
name: string;
|
|
47
|
-
createdAt: Date;
|
|
48
47
|
assistantId: string;
|
|
48
|
+
createdAt: Date;
|
|
49
49
|
assistantRunnerToolId: string;
|
|
50
50
|
assistantRunnerConfig: {} & {
|
|
51
51
|
[k: string]: any;
|
|
@@ -68,8 +68,8 @@ export declare const userPrimaryAssistantVar: import("./persistent-vars").Persis
|
|
|
68
68
|
export declare const groupPrimaryAssistantVar: import("./persistent-vars").PersistentVar<string | undefined>;
|
|
69
69
|
export declare const getPrimaryAssistant: (dataContext?: DataContext) => Promise<{
|
|
70
70
|
name: string;
|
|
71
|
-
createdAt: Date;
|
|
72
71
|
assistantId: string;
|
|
72
|
+
createdAt: Date;
|
|
73
73
|
assistantRunnerToolId: string;
|
|
74
74
|
assistantRunnerConfig: {} & {
|
|
75
75
|
[k: string]: any;
|
package/dist/data/channels.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export declare const channelSchema: z.ZodObject<{
|
|
|
20
20
|
owningGroupId: string;
|
|
21
21
|
}>;
|
|
22
22
|
export type IChannel = z.infer<typeof channelSchema>;
|
|
23
|
-
export declare function Channels(dataContext?: DataContext): import("
|
|
23
|
+
export declare function Channels(dataContext?: DataContext): import("..").Table<{
|
|
24
24
|
name: string;
|
|
25
25
|
description: string;
|
|
26
26
|
createdAt: Date;
|
package/dist/data/devices.d.ts
CHANGED
|
@@ -38,7 +38,7 @@ export interface IDeviceHandshake extends IDeviceInfo {
|
|
|
38
38
|
serverAddress: string;
|
|
39
39
|
timestamp: number;
|
|
40
40
|
}
|
|
41
|
-
export declare function Devices(dataContext?: DataContext): import("
|
|
41
|
+
export declare function Devices(dataContext?: DataContext): import("..").Table<{
|
|
42
42
|
userId: string;
|
|
43
43
|
deviceId: string;
|
|
44
44
|
firstSeen: Date;
|
|
@@ -34,7 +34,7 @@ export declare const embeddingSchema: z.ZodObject<{
|
|
|
34
34
|
embeddingType: string;
|
|
35
35
|
}>;
|
|
36
36
|
export type IEmbedding = z.infer<typeof embeddingSchema>;
|
|
37
|
-
export declare function Embeddings(dataContext?: DataContext): import("
|
|
37
|
+
export declare function Embeddings(dataContext?: DataContext): import("..").Table<{
|
|
38
38
|
metadata: {
|
|
39
39
|
fkId?: string | undefined;
|
|
40
40
|
} & {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { DataContext } from "../context/data-context";
|
|
2
|
+
import { type IPublicKeys, type IPublicPrivateKeys } from "../keys";
|
|
3
|
+
import { type IPersistentVar } from "./persistent-vars";
|
|
4
|
+
/** Prefix used for each group's encrypted secret-key persistent variable. */
|
|
5
|
+
export declare const GROUP_SECRET_KEY_PVAR_PREFIX = "groupSecretKey_";
|
|
6
|
+
/** Return the personal-context persistent-variable name for a group secret key. */
|
|
7
|
+
export declare function groupSecretKeyPvarName(groupId: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Derive a group secret's public keys and verify they match the signed group record.
|
|
10
|
+
*
|
|
11
|
+
* @throws When the secret is malformed or derives different signing/box public keys.
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateGroupSecretKey(secretKey: string, expected: IPublicKeys): IPublicPrivateKeys;
|
|
14
|
+
/**
|
|
15
|
+
* Save a known-valid group secret in the user's personal context.
|
|
16
|
+
*
|
|
17
|
+
* Legacy random IDs and duplicate name rows are canonicalized before the replacement is
|
|
18
|
+
* encrypted and saved. The caller must supply the expected signed group public keys, so this
|
|
19
|
+
* function cannot silently install unrelated key material.
|
|
20
|
+
*/
|
|
21
|
+
export declare function saveGroupSecretKey(userDataContext: DataContext, groupId: string, secretKey: string, expected: IPublicKeys): Promise<IPersistentVar>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GROUP_SECRET_KEY_PVAR_PREFIX = void 0;
|
|
4
|
+
exports.groupSecretKeyPvarName = groupSecretKeyPvarName;
|
|
5
|
+
exports.validateGroupSecretKey = validateGroupSecretKey;
|
|
6
|
+
exports.saveGroupSecretKey = saveGroupSecretKey;
|
|
7
|
+
const keys_1 = require("../keys");
|
|
8
|
+
const utils_1 = require("../utils");
|
|
9
|
+
const persistent_vars_1 = require("./persistent-vars");
|
|
10
|
+
/** Prefix used for each group's encrypted secret-key persistent variable. */
|
|
11
|
+
exports.GROUP_SECRET_KEY_PVAR_PREFIX = "groupSecretKey_";
|
|
12
|
+
/** Return the personal-context persistent-variable name for a group secret key. */
|
|
13
|
+
function groupSecretKeyPvarName(groupId) {
|
|
14
|
+
return `${exports.GROUP_SECRET_KEY_PVAR_PREFIX}${groupId}`;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Derive a group secret's public keys and verify they match the signed group record.
|
|
18
|
+
*
|
|
19
|
+
* @throws When the secret is malformed or derives different signing/box public keys.
|
|
20
|
+
*/
|
|
21
|
+
function validateGroupSecretKey(secretKey, expected) {
|
|
22
|
+
const derived = (0, keys_1.hydrateKeys)(secretKey);
|
|
23
|
+
if (derived.publicKey !== expected.publicKey || derived.publicBoxKey !== expected.publicBoxKey) {
|
|
24
|
+
throw new Error("Group secret key does not match the group's public keys");
|
|
25
|
+
}
|
|
26
|
+
return derived;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Save a known-valid group secret in the user's personal context.
|
|
30
|
+
*
|
|
31
|
+
* Legacy random IDs and duplicate name rows are canonicalized before the replacement is
|
|
32
|
+
* encrypted and saved. The caller must supply the expected signed group public keys, so this
|
|
33
|
+
* function cannot silently install unrelated key material.
|
|
34
|
+
*/
|
|
35
|
+
async function saveGroupSecretKey(userDataContext, groupId, secretKey, expected) {
|
|
36
|
+
validateGroupSecretKey(secretKey, expected);
|
|
37
|
+
const name = groupSecretKeyPvarName(groupId);
|
|
38
|
+
const table = (0, persistent_vars_1.PersistentVars)(userDataContext);
|
|
39
|
+
const records = await table.list({ name });
|
|
40
|
+
let canonical = records.find((record) => record.persistentVarId === (0, utils_1.deterministicPvarId)(name));
|
|
41
|
+
for (const record of records) {
|
|
42
|
+
if (record !== canonical) {
|
|
43
|
+
canonical = await table.migrateLegacyId(record);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return table.save({
|
|
47
|
+
persistentVarId: canonical?.persistentVarId ?? "",
|
|
48
|
+
name,
|
|
49
|
+
scope: "groupUser",
|
|
50
|
+
isSecret: true,
|
|
51
|
+
value: { value: secretKey },
|
|
52
|
+
});
|
|
53
|
+
}
|
package/dist/data/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export * from "./files";
|
|
|
8
8
|
export * from "./group-member-roles";
|
|
9
9
|
export * from "./group-members";
|
|
10
10
|
export * from "./group-permissions";
|
|
11
|
+
export * from "./group-secret";
|
|
11
12
|
export * from "./group-share";
|
|
12
13
|
export * from "./groups";
|
|
13
14
|
export * from "./messages";
|
package/dist/data/index.js
CHANGED
|
@@ -24,6 +24,7 @@ __exportStar(require("./files"), exports);
|
|
|
24
24
|
__exportStar(require("./group-member-roles"), exports);
|
|
25
25
|
__exportStar(require("./group-members"), exports);
|
|
26
26
|
__exportStar(require("./group-permissions"), exports);
|
|
27
|
+
__exportStar(require("./group-secret"), exports);
|
|
27
28
|
__exportStar(require("./group-share"), exports);
|
|
28
29
|
__exportStar(require("./groups"), exports);
|
|
29
30
|
__exportStar(require("./messages"), exports);
|
package/dist/data/messages.d.ts
CHANGED
|
@@ -35,7 +35,7 @@ export declare const messageSchema: z.ZodObject<{
|
|
|
35
35
|
fileIds?: string[] | undefined;
|
|
36
36
|
}>;
|
|
37
37
|
export type IMessage = z.infer<typeof messageSchema>;
|
|
38
|
-
export declare function Messages(dataContext?: DataContext): import("
|
|
38
|
+
export declare function Messages(dataContext?: DataContext): import("..").Table<{
|
|
39
39
|
message: string;
|
|
40
40
|
userId: string;
|
|
41
41
|
createdAt: Date;
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Return whether a table method was explicitly marked for remote invocation by
|
|
3
|
+
* {@link ProxyClientTableMethodCalls}. Client proxies are recognized through their
|
|
4
|
+
* marked `__original` implementation as well.
|
|
5
|
+
*/
|
|
6
|
+
export declare function isContractRemoteTableMethod(method: unknown): boolean;
|
|
1
7
|
/**
|
|
2
8
|
* Decorator that marks a table method as server-side only.
|
|
3
9
|
* When used on the client side, these methods will be automatically proxied
|
|
@@ -1,7 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isContractRemoteTableMethod = isContractRemoteTableMethod;
|
|
3
4
|
exports.ProxyClientTableMethodCalls = ProxyClientTableMethodCalls;
|
|
4
5
|
const rpc_types_1 = require("../../rpc-types");
|
|
6
|
+
const contractRemoteTableMethod = Symbol("contractRemoteTableMethod");
|
|
7
|
+
function markContractRemoteTableMethod(method) {
|
|
8
|
+
Object.defineProperty(method, contractRemoteTableMethod, { value: true });
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Return whether a table method was explicitly marked for remote invocation by
|
|
12
|
+
* {@link ProxyClientTableMethodCalls}. Client proxies are recognized through their
|
|
13
|
+
* marked `__original` implementation as well.
|
|
14
|
+
*/
|
|
15
|
+
function isContractRemoteTableMethod(method) {
|
|
16
|
+
if (typeof method !== "function") {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
const candidate = method;
|
|
20
|
+
return Boolean(candidate[contractRemoteTableMethod] || candidate.__original?.[contractRemoteTableMethod]);
|
|
21
|
+
}
|
|
5
22
|
/**
|
|
6
23
|
* Decorator that marks a table method as server-side only.
|
|
7
24
|
* When used on the client side, these methods will be automatically proxied
|
|
@@ -13,6 +30,9 @@ const rpc_types_1 = require("../../rpc-types");
|
|
|
13
30
|
*/
|
|
14
31
|
function ProxyClientTableMethodCalls() {
|
|
15
32
|
return (target, context) => {
|
|
33
|
+
if (context.kind === "method") {
|
|
34
|
+
markContractRemoteTableMethod(target);
|
|
35
|
+
}
|
|
16
36
|
if (context.kind === "method" && rpc_types_1.isClient) {
|
|
17
37
|
const methodName = context.name;
|
|
18
38
|
// WARNING: Using typescript's magical `this` param
|
|
@@ -21,6 +41,7 @@ function ProxyClientTableMethodCalls() {
|
|
|
21
41
|
return rpc_types_1.rpcServerCalls.tableMethodCall(dataContextId, this.tableName, methodName, ...args);
|
|
22
42
|
};
|
|
23
43
|
proxyFn.__original = target;
|
|
44
|
+
markContractRemoteTableMethod(proxyFn);
|
|
24
45
|
return proxyFn;
|
|
25
46
|
}
|
|
26
47
|
return target;
|