@peers-app/peers-sdk 0.27.3 → 0.27.4
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/contract-proxy.d.ts +7 -0
- package/dist/contracts/contract-proxy.js +19 -2
- package/dist/contracts/create-local-consumer.js +16 -1
- package/dist/contracts/index.d.ts +2 -0
- package/dist/contracts/index.js +2 -0
- package/dist/contracts/system/index.d.ts +2 -0
- package/dist/contracts/system/index.js +2 -0
- package/dist/contracts/system/invites-contract.js +2 -1
- package/dist/contracts/system/sync-check-contract.d.ts +97 -0
- package/dist/contracts/system/sync-check-contract.js +115 -0
- package/dist/contracts/tool-arguments.d.ts +15 -0
- package/dist/contracts/tool-arguments.js +41 -0
- package/dist/contracts/tool-catalog-service.js +2 -12
- package/dist/data/change-tracking.d.ts +40 -0
- package/dist/data/change-tracking.js +89 -0
- package/dist/data/orm/types.d.ts +24 -7
- package/dist/data/orm/types.js +97 -24
- package/dist/define/manifest.js +6 -34
- package/dist/package-loader/package-loader.js +27 -22
- package/dist/system-ids.d.ts +5 -0
- package/dist/system-ids.js +6 -1
- package/package.json +4 -2
- package/dist/context/user-context-identity.test.d.ts +0 -1
- package/dist/context/user-context-identity.test.js +0 -220
- package/dist/contracts/__tests__/action-dispatch.test.d.ts +0 -1
- package/dist/contracts/__tests__/action-dispatch.test.js +0 -319
- package/dist/contracts/__tests__/also-implements.test.d.ts +0 -1
- package/dist/contracts/__tests__/also-implements.test.js +0 -110
- package/dist/contracts/__tests__/builder.test.d.ts +0 -1
- package/dist/contracts/__tests__/builder.test.js +0 -669
- package/dist/contracts/__tests__/contract-events.test.d.ts +0 -1
- package/dist/contracts/__tests__/contract-events.test.js +0 -199
- package/dist/contracts/__tests__/contract-observables.test.d.ts +0 -1
- package/dist/contracts/__tests__/contract-observables.test.js +0 -290
- package/dist/contracts/__tests__/contract-provider-router.test.d.ts +0 -1
- package/dist/contracts/__tests__/contract-provider-router.test.js +0 -315
- package/dist/contracts/__tests__/contract-proxy.test.d.ts +0 -1
- package/dist/contracts/__tests__/contract-proxy.test.js +0 -657
- package/dist/contracts/__tests__/contract-resolvers.test.d.ts +0 -1
- package/dist/contracts/__tests__/contract-resolvers.test.js +0 -758
- package/dist/contracts/__tests__/contract-subscription-lifecycle.test.d.ts +0 -1
- package/dist/contracts/__tests__/contract-subscription-lifecycle.test.js +0 -353
- package/dist/contracts/__tests__/contract-table-events.test.d.ts +0 -1
- package/dist/contracts/__tests__/contract-table-events.test.js +0 -209
- package/dist/contracts/__tests__/contract-transport.test.d.ts +0 -1
- package/dist/contracts/__tests__/contract-transport.test.js +0 -163
- package/dist/contracts/__tests__/extract.test.d.ts +0 -1
- package/dist/contracts/__tests__/extract.test.js +0 -145
- package/dist/contracts/__tests__/frozen-contracts.test.d.ts +0 -1
- package/dist/contracts/__tests__/frozen-contracts.test.js +0 -191
- package/dist/contracts/__tests__/generic-tool-dispatch.test.d.ts +0 -1
- package/dist/contracts/__tests__/generic-tool-dispatch.test.js +0 -130
- package/dist/contracts/__tests__/host-contract-client.test.d.ts +0 -1
- package/dist/contracts/__tests__/host-contract-client.test.js +0 -793
- package/dist/contracts/__tests__/host-contract-consumer.test.d.ts +0 -1
- package/dist/contracts/__tests__/host-contract-consumer.test.js +0 -163
- package/dist/contracts/__tests__/host-contract-transport.test.d.ts +0 -1
- package/dist/contracts/__tests__/host-contract-transport.test.js +0 -66
- package/dist/contracts/__tests__/integration.test.d.ts +0 -1
- package/dist/contracts/__tests__/integration.test.js +0 -348
- package/dist/contracts/__tests__/legacy-removal.test.d.ts +0 -1
- package/dist/contracts/__tests__/legacy-removal.test.js +0 -128
- package/dist/contracts/__tests__/persistent-registry.test.d.ts +0 -1
- package/dist/contracts/__tests__/persistent-registry.test.js +0 -109
- package/dist/contracts/__tests__/playground.test.d.ts +0 -1
- package/dist/contracts/__tests__/playground.test.js +0 -216
- package/dist/contracts/__tests__/registry.test.d.ts +0 -1
- package/dist/contracts/__tests__/registry.test.js +0 -238
- package/dist/contracts/__tests__/remote-contract-transport.test.d.ts +0 -1
- package/dist/contracts/__tests__/remote-contract-transport.test.js +0 -119
- package/dist/contracts/__tests__/system-contracts.test.d.ts +0 -1
- package/dist/contracts/__tests__/system-contracts.test.js +0 -247
- package/dist/contracts/__tests__/target-dispatch.d.ts +0 -11
- package/dist/contracts/__tests__/target-dispatch.js +0 -24
- package/dist/contracts/__tests__/tool-catalog-inventory.test.d.ts +0 -1
- package/dist/contracts/__tests__/tool-catalog-inventory.test.js +0 -44
- package/dist/contracts/__tests__/tool-catalog-service.test.d.ts +0 -1
- package/dist/contracts/__tests__/tool-catalog-service.test.js +0 -482
- package/dist/contracts/__tests__/tool-catalog.test.d.ts +0 -1
- package/dist/contracts/__tests__/tool-catalog.test.js +0 -1199
- package/dist/contracts/__tests__/validate.test.d.ts +0 -1
- package/dist/contracts/__tests__/validate.test.js +0 -991
- package/dist/contracts/__tests__/workflow-context.test.d.ts +0 -1
- package/dist/contracts/__tests__/workflow-context.test.js +0 -50
- package/dist/data/access-level.test.d.ts +0 -1
- package/dist/data/access-level.test.js +0 -53
- package/dist/data/change-tracking.test.d.ts +0 -1
- package/dist/data/change-tracking.test.js +0 -62
- package/dist/data/files/files.test.d.ts +0 -1
- package/dist/data/files/files.test.js +0 -770
- package/dist/data/group-members.test.d.ts +0 -1
- package/dist/data/group-members.test.js +0 -336
- package/dist/data/group-share.test.d.ts +0 -1
- package/dist/data/group-share.test.js +0 -110
- package/dist/data/groups.test.d.ts +0 -1
- package/dist/data/groups.test.js +0 -153
- package/dist/data/orm/cursor.test.d.ts +0 -1
- package/dist/data/orm/cursor.test.js +0 -314
- package/dist/data/orm/data-query.mongo.test.d.ts +0 -1
- package/dist/data/orm/data-query.mongo.test.js +0 -367
- package/dist/data/orm/data-query.sqlite.test.d.ts +0 -1
- package/dist/data/orm/data-query.sqlite.test.js +0 -365
- package/dist/data/orm/data-query.test.d.ts +0 -1
- package/dist/data/orm/data-query.test.js +0 -545
- package/dist/data/orm/dependency-injection.test.d.ts +0 -1
- package/dist/data/orm/dependency-injection.test.js +0 -171
- package/dist/data/orm/event-registry.test.d.ts +0 -1
- package/dist/data/orm/event-registry.test.js +0 -44
- package/dist/data/orm/multi-cursors.test.d.ts +0 -1
- package/dist/data/orm/multi-cursors.test.js +0 -463
- package/dist/data/orm/sql.data-source.test.d.ts +0 -1
- package/dist/data/orm/sql.data-source.test.js +0 -731
- package/dist/data/orm/table-container-events.test.d.ts +0 -1
- package/dist/data/orm/table-container-events.test.js +0 -101
- package/dist/data/orm/table-container.test.d.ts +0 -1
- package/dist/data/orm/table-container.test.js +0 -273
- package/dist/data/orm/table.event-source.test.d.ts +0 -1
- package/dist/data/orm/table.event-source.test.js +0 -331
- package/dist/data/orm/types.test.d.ts +0 -1
- package/dist/data/orm/types.test.js +0 -409
- package/dist/data/package-table-identity.test.d.ts +0 -1
- package/dist/data/package-table-identity.test.js +0 -46
- package/dist/data/package-version-permissions.test.d.ts +0 -1
- package/dist/data/package-version-permissions.test.js +0 -107
- package/dist/data/package-version-resolver.test.d.ts +0 -4
- package/dist/data/package-version-resolver.test.js +0 -543
- package/dist/data/package-versions.test.d.ts +0 -1
- package/dist/data/package-versions.test.js +0 -227
- package/dist/data/persistent-vars.conflict.test.d.ts +0 -1
- package/dist/data/persistent-vars.conflict.test.js +0 -126
- package/dist/data/persistent-vars.migration.test.d.ts +0 -1
- package/dist/data/persistent-vars.migration.test.js +0 -133
- package/dist/data/persistent-vars.package-scope.test.d.ts +0 -1
- package/dist/data/persistent-vars.package-scope.test.js +0 -27
- package/dist/data/sync-recovery-queue.test.d.ts +0 -1
- package/dist/data/sync-recovery-queue.test.js +0 -215
- package/dist/data/table-signing.test.d.ts +0 -1
- package/dist/data/table-signing.test.js +0 -118
- package/dist/data/tool-access.test.d.ts +0 -1
- package/dist/data/tool-access.test.js +0 -166
- package/dist/data/user-permissions.test.d.ts +0 -1
- package/dist/data/user-permissions.test.js +0 -305
- package/dist/data/user-trust-levels.test.d.ts +0 -1
- package/dist/data/user-trust-levels.test.js +0 -37
- package/dist/define/also-implements.test.d.ts +0 -1
- package/dist/define/also-implements.test.js +0 -123
- package/dist/define/declare-contract.test.d.ts +0 -1
- package/dist/define/declare-contract.test.js +0 -573
- package/dist/define/define.test.d.ts +0 -1
- package/dist/define/define.test.js +0 -1010
- package/dist/define/empty-fields.test.d.ts +0 -1
- package/dist/define/empty-fields.test.js +0 -55
- package/dist/define/events-observables.test.d.ts +0 -1
- package/dist/define/events-observables.test.js +0 -1013
- package/dist/define/serve-members.test.d.ts +0 -1
- package/dist/define/serve-members.test.js +0 -630
- package/dist/define/vars.test.d.ts +0 -1
- package/dist/define/vars.test.js +0 -39
- package/dist/device/binary-peer-connection-v2.test.d.ts +0 -1
- package/dist/device/binary-peer-connection-v2.test.js +0 -730
- package/dist/device/binary-peer-connection.test.d.ts +0 -1
- package/dist/device/binary-peer-connection.test.js +0 -184
- package/dist/device/connection.test.d.ts +0 -1
- package/dist/device/connection.test.js +0 -613
- package/dist/device/device-election.test.d.ts +0 -1
- package/dist/device/device-election.test.js +0 -516
- package/dist/device/device.test.d.ts +0 -1
- package/dist/device/device.test.js +0 -243
- package/dist/device/frame-cipher.test.d.ts +0 -1
- package/dist/device/frame-cipher.test.js +0 -219
- package/dist/device/get-trust-level-fn.test.d.ts +0 -1
- package/dist/device/get-trust-level-fn.test.js +0 -685
- package/dist/device/streamed-socket.test.d.ts +0 -1
- package/dist/device/streamed-socket.test.js +0 -216
- package/dist/device/tx-encoding.test.d.ts +0 -1
- package/dist/device/tx-encoding.test.js +0 -295
- package/dist/device-pairing/cpace.test.d.ts +0 -1
- package/dist/device-pairing/cpace.test.js +0 -116
- package/dist/device-pairing/device-pairing.test.d.ts +0 -1
- package/dist/device-pairing/device-pairing.test.js +0 -211
- package/dist/hlc.test.d.ts +0 -1
- package/dist/hlc.test.js +0 -45
- package/dist/host-credentials.test.d.ts +0 -1
- package/dist/host-credentials.test.js +0 -88
- package/dist/identity/account-email.test.d.ts +0 -1
- package/dist/identity/account-email.test.js +0 -59
- package/dist/identity/anchor-document.test.d.ts +0 -1
- package/dist/identity/anchor-document.test.js +0 -16
- package/dist/identity/anchor-resolution.test.d.ts +0 -1
- package/dist/identity/anchor-resolution.test.js +0 -130
- package/dist/identity/key-change.test.d.ts +0 -1
- package/dist/identity/key-change.test.js +0 -811
- package/dist/invites/group-approval.test.d.ts +0 -1
- package/dist/invites/group-approval.test.js +0 -223
- package/dist/invites/invite-token.test.d.ts +0 -1
- package/dist/invites/invite-token.test.js +0 -123
- package/dist/keys.test.d.ts +0 -1
- package/dist/keys.test.js +0 -336
- package/dist/logging/console-logger.test.d.ts +0 -1
- package/dist/logging/console-logger.test.js +0 -300
- package/dist/logging/console-logs.table.test.d.ts +0 -1
- package/dist/logging/console-logs.table.test.js +0 -156
- package/dist/observable.test.d.ts +0 -1
- package/dist/observable.test.js +0 -309
- package/dist/package-build/build-package.test.d.ts +0 -1
- package/dist/package-build/build-package.test.js +0 -204
- package/dist/package-build/contract-add.test.d.ts +0 -1
- package/dist/package-build/contract-add.test.js +0 -467
- package/dist/package-build/freeze-contracts.test.d.ts +0 -1
- package/dist/package-build/freeze-contracts.test.js +0 -355
- package/dist/package-installer/package-author-signing.test.d.ts +0 -1
- package/dist/package-installer/package-author-signing.test.js +0 -200
- package/dist/package-installer/package-cloner.test.d.ts +0 -1
- package/dist/package-installer/package-cloner.test.js +0 -278
- package/dist/package-installer/package-creator.test.d.ts +0 -1
- package/dist/package-installer/package-creator.test.js +0 -908
- package/dist/package-installer/package-dev-tools.test.d.ts +0 -1
- package/dist/package-installer/package-dev-tools.test.js +0 -64
- package/dist/package-installer/package-installer.test.d.ts +0 -1
- package/dist/package-installer/package-installer.test.js +0 -882
- package/dist/package-installer/package-propagation.test.d.ts +0 -1
- package/dist/package-installer/package-propagation.test.js +0 -1269
- package/dist/package-installer/package-publisher.test.d.ts +0 -1
- package/dist/package-installer/package-publisher.test.js +0 -153
- package/dist/package-installer/package-remote-checker.test.d.ts +0 -1
- package/dist/package-installer/package-remote-checker.test.js +0 -334
- package/dist/package-installer/package-seed-installer.test.d.ts +0 -1
- package/dist/package-installer/package-seed-installer.test.js +0 -123
- package/dist/package-installer/package-tarball.test.d.ts +0 -1
- package/dist/package-installer/package-tarball.test.js +0 -75
- package/dist/package-installer/peers-core-installer.test.d.ts +0 -1
- package/dist/package-installer/peers-core-installer.test.js +0 -49
- package/dist/package-installer/peers-core-trust-anchor.test.d.ts +0 -1
- package/dist/package-installer/peers-core-trust-anchor.test.js +0 -155
- package/dist/package-loader/contract-package-loader.test.d.ts +0 -1
- package/dist/package-loader/contract-package-loader.test.js +0 -274
- package/dist/package-loader/host-authority-loading.test.d.ts +0 -1
- package/dist/package-loader/host-authority-loading.test.js +0 -104
- package/dist/package-loader/host-dispatch-policy.test.d.ts +0 -1
- package/dist/package-loader/host-dispatch-policy.test.js +0 -56
- package/dist/package-loader/isolated-artifact.test.d.ts +0 -1
- package/dist/package-loader/isolated-artifact.test.js +0 -688
- package/dist/package-loader/isolated-persistent-var-gateway.test.d.ts +0 -1
- package/dist/package-loader/isolated-persistent-var-gateway.test.js +0 -56
- package/dist/package-loader/isolated-table-gateway.test.d.ts +0 -1
- package/dist/package-loader/isolated-table-gateway.test.js +0 -633
- package/dist/package-loader/package-loader.test.d.ts +0 -1
- package/dist/package-loader/package-loader.test.js +0 -1764
- package/dist/package-loader/resolve-consumed-contracts.test.d.ts +0 -1
- package/dist/package-loader/resolve-consumed-contracts.test.js +0 -166
- package/dist/serial-json.compat.test.d.ts +0 -1
- package/dist/serial-json.compat.test.js +0 -369
- package/dist/serial-json.test.d.ts +0 -1
- package/dist/serial-json.test.js +0 -401
- package/dist/testing/mock-host-contract.test.d.ts +0 -1
- package/dist/testing/mock-host-contract.test.js +0 -782
- package/dist/utils.test.d.ts +0 -1
- package/dist/utils.test.js +0 -232
|
@@ -375,6 +375,13 @@ export interface IContractResolution {
|
|
|
375
375
|
version: number;
|
|
376
376
|
tables?: Record<string, Table<any>>;
|
|
377
377
|
tools?: Record<string, IContractToolImplementation>;
|
|
378
|
+
/**
|
|
379
|
+
* Trusted runtime invocation after access checks, with host context already appended.
|
|
380
|
+
* It validates the requested version's input and checks endpoint liveness immediately
|
|
381
|
+
* before running provider code. Without it, dispatch validates the system definition or
|
|
382
|
+
* the implementation's declared input fields and calls the tool function directly.
|
|
383
|
+
*/
|
|
384
|
+
invokeTool?: (name: string, args: any[]) => any;
|
|
378
385
|
/**
|
|
379
386
|
* Host-only capabilities appended as the final argument to provider tool functions.
|
|
380
387
|
* Omit this for remote or otherwise untrusted provider routes.
|
|
@@ -15,6 +15,8 @@ const observable_1 = require("../observable");
|
|
|
15
15
|
const utils_1 = require("../utils");
|
|
16
16
|
const action_dispatch_1 = require("./action-dispatch");
|
|
17
17
|
const contract_transport_1 = require("./contract-transport");
|
|
18
|
+
const system_contracts_1 = require("./system-contracts");
|
|
19
|
+
const tool_arguments_1 = require("./tool-arguments");
|
|
18
20
|
const STANDARD_REMOTE_TABLE_METHODS = new Set([
|
|
19
21
|
"get",
|
|
20
22
|
"list",
|
|
@@ -594,6 +596,21 @@ function createContractProvider(resolution, opts = {}) {
|
|
|
594
596
|
}
|
|
595
597
|
const { workflow, ...caller } = context;
|
|
596
598
|
const authority = await assertContractToolAccess(tool, call, caller);
|
|
599
|
+
const invoke = (...args) => {
|
|
600
|
+
if (resolution.invokeTool)
|
|
601
|
+
return resolution.invokeTool(call.name, args);
|
|
602
|
+
const definition = (0, system_contracts_1.listSystemContracts)()
|
|
603
|
+
.find((entry) => (entry.contractId ?? entry.getDefinition().contractId) === call.contractId &&
|
|
604
|
+
(entry.version ?? entry.getDefinition().version) === call.version)
|
|
605
|
+
?.getDefinition();
|
|
606
|
+
const member = definition?.tools.find((entry) => entry.name === call.name);
|
|
607
|
+
if (definition && !member)
|
|
608
|
+
throw new Error(`Contract ${call.contractId} does not declare tool '${call.name}'`);
|
|
609
|
+
const fields = member?.inputFields ?? tool.tool.inputSchema?.fields;
|
|
610
|
+
if (fields?.length)
|
|
611
|
+
(0, tool_arguments_1.checkToolArguments)(fields, call.args[0], call.name);
|
|
612
|
+
return tool.toolFn(...args);
|
|
613
|
+
};
|
|
597
614
|
if (resolution.toolContext ||
|
|
598
615
|
resolution.forwardCallContext ||
|
|
599
616
|
authority.strictActionScope) {
|
|
@@ -621,7 +638,7 @@ function createContractProvider(resolution, opts = {}) {
|
|
|
621
638
|
authority: (0, action_dispatch_1.narrowActionPrincipal)(frame, true),
|
|
622
639
|
});
|
|
623
640
|
};
|
|
624
|
-
return
|
|
641
|
+
return invoke(call.args[0], {
|
|
625
642
|
...base,
|
|
626
643
|
workflow: caller.callerDeviceId || caller.callerPackageId ? undefined : workflow,
|
|
627
644
|
callerPackageId: caller.callerPackageId,
|
|
@@ -632,7 +649,7 @@ function createContractProvider(resolution, opts = {}) {
|
|
|
632
649
|
authority,
|
|
633
650
|
});
|
|
634
651
|
}
|
|
635
|
-
return
|
|
652
|
+
return invoke(...call.args);
|
|
636
653
|
}
|
|
637
654
|
case "observable": {
|
|
638
655
|
const obs = resolution.observables?.[call.name];
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createLocalContractConsumer = createLocalContractConsumer;
|
|
4
4
|
const contract_proxy_1 = require("./contract-proxy");
|
|
5
5
|
const contract_transport_1 = require("./contract-transport");
|
|
6
|
+
const tool_arguments_1 = require("./tool-arguments");
|
|
6
7
|
/**
|
|
7
8
|
* Build a same-process contract consumer wired to a live provider resolution.
|
|
8
9
|
*
|
|
@@ -12,7 +13,21 @@ const contract_transport_1 = require("./contract-transport");
|
|
|
12
13
|
*/
|
|
13
14
|
function createLocalContractConsumer(definition, resolution, opts) {
|
|
14
15
|
const [consumerTransport, providerTransport] = (0, contract_transport_1.inProcessTransportPair)();
|
|
15
|
-
(0, contract_proxy_1.createContractProviderSession)(
|
|
16
|
+
(0, contract_proxy_1.createContractProviderSession)({
|
|
17
|
+
...resolution,
|
|
18
|
+
invokeTool: resolution.invokeTool ??
|
|
19
|
+
((name, args) => {
|
|
20
|
+
const tool = resolution.tools?.[name];
|
|
21
|
+
if (!tool)
|
|
22
|
+
throw new Error(`Contract ${definition.contractId} does not provide tool '${name}'`);
|
|
23
|
+
const member = definition.tools.find((tool) => tool.name === name);
|
|
24
|
+
if (!member)
|
|
25
|
+
throw new Error(`Contract ${definition.contractId} does not declare tool '${name}'`);
|
|
26
|
+
if (member.inputFields.length)
|
|
27
|
+
(0, tool_arguments_1.checkToolArguments)(member.inputFields, args[0], name);
|
|
28
|
+
return tool.toolFn(...args);
|
|
29
|
+
}),
|
|
30
|
+
}, providerTransport, { context: opts?.context });
|
|
16
31
|
return (0, contract_proxy_1.createContractConsumer)(definition, consumerTransport, {
|
|
17
32
|
dataContextId: opts?.dataContextId,
|
|
18
33
|
});
|
|
@@ -29,9 +29,11 @@ export { getLogsContractDefinition, type ILogsConsumer, LOGS_CONTRACT_VERSION, r
|
|
|
29
29
|
export * from "./system/network-contracts";
|
|
30
30
|
export * from "./system/packages-contract";
|
|
31
31
|
export { getSchedulerContractDefinition, type IScheduleInfo, type IScheduleInput, type ISchedulerConsumer, SCHEDULER_CONTRACT_VERSION, SCHEDULER_MAX_DELAY_MS, schedulerProviderPackageId, } from "./system/scheduler-contract";
|
|
32
|
+
export * from "./system/sync-check-contract";
|
|
32
33
|
export { getToolAccessControlContractDefinition, type IToolAccessControlConsumer, TOOL_ACCESS_CONTROL_CONTRACT_VERSION, } from "./system/tool-access-control-contract";
|
|
33
34
|
export * from "./system/tool-catalog-contract";
|
|
34
35
|
export { type ISystemContractRegistration, installSystemContracts, isSystemContractId, listSystemContracts, registerSystemContract, } from "./system-contracts";
|
|
36
|
+
export * from "./tool-arguments";
|
|
35
37
|
export * from "./tool-catalog";
|
|
36
38
|
export * from "./tool-catalog-identity";
|
|
37
39
|
export * from "./tool-catalog-migrations";
|
package/dist/contracts/index.js
CHANGED
|
@@ -143,6 +143,7 @@ Object.defineProperty(exports, "getSchedulerContractDefinition", { enumerable: t
|
|
|
143
143
|
Object.defineProperty(exports, "SCHEDULER_CONTRACT_VERSION", { enumerable: true, get: function () { return scheduler_contract_1.SCHEDULER_CONTRACT_VERSION; } });
|
|
144
144
|
Object.defineProperty(exports, "SCHEDULER_MAX_DELAY_MS", { enumerable: true, get: function () { return scheduler_contract_1.SCHEDULER_MAX_DELAY_MS; } });
|
|
145
145
|
Object.defineProperty(exports, "schedulerProviderPackageId", { enumerable: true, get: function () { return scheduler_contract_1.schedulerProviderPackageId; } });
|
|
146
|
+
__exportStar(require("./system/sync-check-contract"), exports);
|
|
146
147
|
var tool_access_control_contract_1 = require("./system/tool-access-control-contract");
|
|
147
148
|
Object.defineProperty(exports, "getToolAccessControlContractDefinition", { enumerable: true, get: function () { return tool_access_control_contract_1.getToolAccessControlContractDefinition; } });
|
|
148
149
|
Object.defineProperty(exports, "TOOL_ACCESS_CONTROL_CONTRACT_VERSION", { enumerable: true, get: function () { return tool_access_control_contract_1.TOOL_ACCESS_CONTROL_CONTRACT_VERSION; } });
|
|
@@ -152,6 +153,7 @@ Object.defineProperty(exports, "installSystemContracts", { enumerable: true, get
|
|
|
152
153
|
Object.defineProperty(exports, "isSystemContractId", { enumerable: true, get: function () { return system_contracts_1.isSystemContractId; } });
|
|
153
154
|
Object.defineProperty(exports, "listSystemContracts", { enumerable: true, get: function () { return system_contracts_1.listSystemContracts; } });
|
|
154
155
|
Object.defineProperty(exports, "registerSystemContract", { enumerable: true, get: function () { return system_contracts_1.registerSystemContract; } });
|
|
156
|
+
__exportStar(require("./tool-arguments"), exports);
|
|
155
157
|
__exportStar(require("./tool-catalog"), exports);
|
|
156
158
|
__exportStar(require("./tool-catalog-identity"), exports);
|
|
157
159
|
__exportStar(require("./tool-catalog-migrations"), exports);
|
|
@@ -13,6 +13,7 @@ import "./logs-contract";
|
|
|
13
13
|
import "./network-contracts";
|
|
14
14
|
import "./packages-contract";
|
|
15
15
|
import "./scheduler-contract";
|
|
16
|
+
import "./sync-check-contract";
|
|
16
17
|
import "./tool-access-control-contract";
|
|
17
18
|
export * from "./app-updates-contract";
|
|
18
19
|
export { DEVICE_OPERATIONS_CONTRACT_VERSION, DEVICE_OPERATIONS_MAX_QUERY_LENGTH, DEVICE_OPERATIONS_MAX_RESULT_BYTES, DEVICE_OPERATIONS_MAX_ROWS, DEVICE_OPERATIONS_MAX_TOOLS, type DeviceOperationCapability, deviceOperationsProviderPackageId, deviceOperationsToolIds, getDeviceOperationsContractDefinition, type IDeviceDatabaseQueryInput, type IDeviceDatabaseQueryResult, type IDeviceOperationStatus, type IDeviceToolListInput, type IDeviceToolLookupInput, type IDeviceToolLookupResult, type IDeviceToolRunInput, } from "./device-operations-contract";
|
|
@@ -22,6 +23,7 @@ export { getInvitesContractDefinition, type IAcceptInviteResult, type ICreatedIn
|
|
|
22
23
|
export { getLogsContractDefinition, type ILogsConsumer, LOGS_CONTRACT_VERSION, resolveLogsContract, } from "./logs-contract";
|
|
23
24
|
export * from "./network-contracts";
|
|
24
25
|
export * from "./packages-contract";
|
|
26
|
+
export * from "./sync-check-contract";
|
|
25
27
|
export { getToolAccessControlContractDefinition, type IToolAccessControlConsumer, TOOL_ACCESS_CONTROL_CONTRACT_VERSION, } from "./tool-access-control-contract";
|
|
26
28
|
import "./tool-catalog-contract";
|
|
27
29
|
export * from "./desktop-tools-contract";
|
|
@@ -30,6 +30,7 @@ require("./logs-contract");
|
|
|
30
30
|
require("./network-contracts");
|
|
31
31
|
require("./packages-contract");
|
|
32
32
|
require("./scheduler-contract");
|
|
33
|
+
require("./sync-check-contract");
|
|
33
34
|
require("./tool-access-control-contract");
|
|
34
35
|
__exportStar(require("./app-updates-contract"), exports);
|
|
35
36
|
var device_operations_contract_1 = require("./device-operations-contract");
|
|
@@ -54,6 +55,7 @@ Object.defineProperty(exports, "LOGS_CONTRACT_VERSION", { enumerable: true, get:
|
|
|
54
55
|
Object.defineProperty(exports, "resolveLogsContract", { enumerable: true, get: function () { return logs_contract_1.resolveLogsContract; } });
|
|
55
56
|
__exportStar(require("./network-contracts"), exports);
|
|
56
57
|
__exportStar(require("./packages-contract"), exports);
|
|
58
|
+
__exportStar(require("./sync-check-contract"), exports);
|
|
57
59
|
var tool_access_control_contract_1 = require("./tool-access-control-contract");
|
|
58
60
|
Object.defineProperty(exports, "getToolAccessControlContractDefinition", { enumerable: true, get: function () { return tool_access_control_contract_1.getToolAccessControlContractDefinition; } });
|
|
59
61
|
Object.defineProperty(exports, "TOOL_ACCESS_CONTROL_CONTRACT_VERSION", { enumerable: true, get: function () { return tool_access_control_contract_1.TOOL_ACCESS_CONTROL_CONTRACT_VERSION; } });
|
|
@@ -47,8 +47,9 @@ function getInvitesContractDefinition() {
|
|
|
47
47
|
field("expiresInMs", field_type_1.FieldType.number, "Lifetime override in milliseconds.", {
|
|
48
48
|
optional: true,
|
|
49
49
|
}),
|
|
50
|
-
field("uses", field_type_1.FieldType.
|
|
50
|
+
field("uses", field_type_1.FieldType.any, "1 or unlimited (default unlimited).", {
|
|
51
51
|
optional: true,
|
|
52
|
+
enumValues: [1, "unlimited"],
|
|
52
53
|
}),
|
|
53
54
|
],
|
|
54
55
|
outputFields: [field("invite", field_type_1.FieldType.object, "The issued invite and encodings.")],
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { IChangeCount, ICountChangesRequest } from "../../data/change-tracking";
|
|
2
|
+
import type { Observable } from "../../observable";
|
|
3
|
+
import type { IContractConsumerBase } from "../contract-proxy";
|
|
4
|
+
import type { IContractDefinition } from "../types";
|
|
5
|
+
/** Version of the built-in System Sync Check contract. */
|
|
6
|
+
export declare const SYNC_CHECK_CONTRACT_VERSION = 1;
|
|
7
|
+
/** A device's answer to `countChanges`. */
|
|
8
|
+
export interface ICountChangesResult {
|
|
9
|
+
/** Tables this device never syncs for the context; the asking device leaves them out too. */
|
|
10
|
+
excludedTableNames: string[];
|
|
11
|
+
counts: IChangeCount[];
|
|
12
|
+
}
|
|
13
|
+
/** One change another device has that this device is missing. */
|
|
14
|
+
export interface IMissingChange {
|
|
15
|
+
changeId: string;
|
|
16
|
+
tableName: string;
|
|
17
|
+
recordId: string;
|
|
18
|
+
op: string;
|
|
19
|
+
path: string;
|
|
20
|
+
/** Author time. Hybrid-logical-clock milliseconds. */
|
|
21
|
+
createdAt: number;
|
|
22
|
+
}
|
|
23
|
+
/** What the check found when it compared this device with one other device in one context. */
|
|
24
|
+
export interface ISyncGap {
|
|
25
|
+
dataContextId: string;
|
|
26
|
+
dataContextName: string;
|
|
27
|
+
/** The device that has the changes. */
|
|
28
|
+
deviceId: string;
|
|
29
|
+
deviceName?: string;
|
|
30
|
+
checkedAt: number;
|
|
31
|
+
/** Changes the other device has that this device is missing. */
|
|
32
|
+
missingCount: number;
|
|
33
|
+
/** Up to 100 of the missing changes, oldest first. */
|
|
34
|
+
missing: IMissingChange[];
|
|
35
|
+
/** True when the check stopped before comparing everything; there may be more. */
|
|
36
|
+
truncated: boolean;
|
|
37
|
+
}
|
|
38
|
+
/** Live summary of the latest checks on this device. */
|
|
39
|
+
export interface ISyncCheckStatus {
|
|
40
|
+
/** Missing changes found, each counted once across contexts and devices. */
|
|
41
|
+
missingChangeCount: number;
|
|
42
|
+
/** When the latest check finished. */
|
|
43
|
+
lastCheckedAt?: number;
|
|
44
|
+
}
|
|
45
|
+
/** Result of `checkSyncGaps`. */
|
|
46
|
+
export interface ISyncCheckResult {
|
|
47
|
+
/** Device comparisons that completed. Devices without the check are skipped. */
|
|
48
|
+
compared: number;
|
|
49
|
+
/** Missing changes found. */
|
|
50
|
+
missingCount: number;
|
|
51
|
+
/** At least one comparison stopped at its bound; another check continues it. */
|
|
52
|
+
truncated?: boolean;
|
|
53
|
+
message: string;
|
|
54
|
+
}
|
|
55
|
+
/** Result of `repairSyncGaps`. */
|
|
56
|
+
export interface ISyncRepairResult {
|
|
57
|
+
/** Missing changes this device now holds. */
|
|
58
|
+
repaired: number;
|
|
59
|
+
/** Missing changes still found after the repair. */
|
|
60
|
+
remaining: number;
|
|
61
|
+
message: string;
|
|
62
|
+
}
|
|
63
|
+
/** Typed consumer proxy for System Sync Check v1. */
|
|
64
|
+
export interface ISyncCheckConsumer extends IContractConsumerBase {
|
|
65
|
+
tools: {
|
|
66
|
+
/** Count this device's active changes in the call's context. Group Readers may call it. */
|
|
67
|
+
countChanges(input: ICountChangesRequest): Promise<ICountChangesResult>;
|
|
68
|
+
/** What the latest checks found, for one context or every context. Local callers only. */
|
|
69
|
+
getSyncGaps(input?: {
|
|
70
|
+
dataContextId?: string;
|
|
71
|
+
}): Promise<{
|
|
72
|
+
gaps: ISyncGap[];
|
|
73
|
+
}>;
|
|
74
|
+
/** Check now against each connected device. Local callers only. */
|
|
75
|
+
checkSyncGaps(input?: {
|
|
76
|
+
dataContextId?: string;
|
|
77
|
+
}): Promise<ISyncCheckResult>;
|
|
78
|
+
/** Fetch and apply the missing changes found in one context. Local callers only. */
|
|
79
|
+
repairSyncGaps(input: {
|
|
80
|
+
dataContextId: string;
|
|
81
|
+
deviceId?: string;
|
|
82
|
+
}): Promise<ISyncRepairResult>;
|
|
83
|
+
};
|
|
84
|
+
observables: {
|
|
85
|
+
/** Live summary; available over the local host transport only. */
|
|
86
|
+
status: Observable<ISyncCheckStatus>;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Return the System Sync Check contract shape.
|
|
91
|
+
*
|
|
92
|
+
* Once a day each device compares its change history for each personal and group context with
|
|
93
|
+
* each connected device's, and reports changes the other device has that this one is missing.
|
|
94
|
+
* `countChanges` is how devices compare: other devices in a group may call it with Reader
|
|
95
|
+
* access. The other tools serve this device's UI and CLI and refuse remote callers.
|
|
96
|
+
*/
|
|
97
|
+
export declare function getSyncCheckContractDefinition(): IContractDefinition;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SYNC_CHECK_CONTRACT_VERSION = void 0;
|
|
4
|
+
exports.getSyncCheckContractDefinition = getSyncCheckContractDefinition;
|
|
5
|
+
const access_level_1 = require("../../data/access-level");
|
|
6
|
+
const system_ids_1 = require("../../system-ids");
|
|
7
|
+
const field_type_1 = require("../../types/field-type");
|
|
8
|
+
const system_contracts_1 = require("../system-contracts");
|
|
9
|
+
/** Version of the built-in System Sync Check contract. */
|
|
10
|
+
exports.SYNC_CHECK_CONTRACT_VERSION = 1;
|
|
11
|
+
const field = (name, type, description, opts = {}) => ({ name, type, description, ...opts });
|
|
12
|
+
const contextInput = field("dataContextId", field_type_1.FieldType.id, "Personal or group context ID.", {
|
|
13
|
+
optional: true,
|
|
14
|
+
});
|
|
15
|
+
let definition;
|
|
16
|
+
/**
|
|
17
|
+
* Return the System Sync Check contract shape.
|
|
18
|
+
*
|
|
19
|
+
* Once a day each device compares its change history for each personal and group context with
|
|
20
|
+
* each connected device's, and reports changes the other device has that this one is missing.
|
|
21
|
+
* `countChanges` is how devices compare: other devices in a group may call it with Reader
|
|
22
|
+
* access. The other tools serve this device's UI and CLI and refuse remote callers.
|
|
23
|
+
*/
|
|
24
|
+
function getSyncCheckContractDefinition() {
|
|
25
|
+
definition ??= {
|
|
26
|
+
contractId: system_ids_1.syncCheckContractId,
|
|
27
|
+
version: exports.SYNC_CHECK_CONTRACT_VERSION,
|
|
28
|
+
devTag: "dev",
|
|
29
|
+
name: "System Sync Check",
|
|
30
|
+
description: "Find changes another device has that this device is missing, and repair them.",
|
|
31
|
+
tables: [],
|
|
32
|
+
tools: [
|
|
33
|
+
{
|
|
34
|
+
name: "countChanges",
|
|
35
|
+
usageDescription: "Count this device's active changes per table, or per table and change-id prefix, with a digest of their ids.",
|
|
36
|
+
inputFields: [
|
|
37
|
+
field("before", field_type_1.FieldType.string, "Count only change ids below this one."),
|
|
38
|
+
field("excludedTableNames", field_type_1.FieldType.string, "Tables to leave out.", {
|
|
39
|
+
optional: true,
|
|
40
|
+
isArray: true,
|
|
41
|
+
}),
|
|
42
|
+
field("tableName", field_type_1.FieldType.string, "Count only this table.", { optional: true }),
|
|
43
|
+
field("prefix", field_type_1.FieldType.string, "Count only ids that start with this.", {
|
|
44
|
+
optional: true,
|
|
45
|
+
}),
|
|
46
|
+
field("prefixLength", field_type_1.FieldType.number, "Also group by this many id characters.", {
|
|
47
|
+
optional: true,
|
|
48
|
+
}),
|
|
49
|
+
field("afterPrefix", field_type_1.FieldType.string, "Resume after this prefix; grouped pages contain at most 500 rows.", {
|
|
50
|
+
optional: true,
|
|
51
|
+
}),
|
|
52
|
+
],
|
|
53
|
+
outputFields: [
|
|
54
|
+
field("excludedTableNames", field_type_1.FieldType.string, "Tables this device never syncs.", {
|
|
55
|
+
isArray: true,
|
|
56
|
+
}),
|
|
57
|
+
field("counts", field_type_1.FieldType.object, "Counts and digests.", { isArray: true }),
|
|
58
|
+
],
|
|
59
|
+
remoteAccessLevel: access_level_1.AccessLevel.Reader,
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: "getSyncGaps",
|
|
63
|
+
usageDescription: "List changes the latest checks found on another device but not here.",
|
|
64
|
+
inputFields: [contextInput],
|
|
65
|
+
outputFields: [
|
|
66
|
+
field("gaps", field_type_1.FieldType.object, "Findings, one per context and device.", {
|
|
67
|
+
isArray: true,
|
|
68
|
+
}),
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: "checkSyncGaps",
|
|
73
|
+
usageDescription: "Compare one context, or every context, with each connected device now. Only reports.",
|
|
74
|
+
inputFields: [contextInput],
|
|
75
|
+
outputFields: [
|
|
76
|
+
field("compared", field_type_1.FieldType.number, "Device comparisons that completed."),
|
|
77
|
+
field("missingCount", field_type_1.FieldType.number, "Missing changes found."),
|
|
78
|
+
field("truncated", field_type_1.FieldType.boolean, "Another check is needed to finish a bounded comparison.", { optional: true }),
|
|
79
|
+
field("message", field_type_1.FieldType.string, "Human-readable result."),
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "repairSyncGaps",
|
|
84
|
+
usageDescription: "Fetch the missing changes found in one context from the devices that have them and apply them as sync would.",
|
|
85
|
+
inputFields: [
|
|
86
|
+
field("dataContextId", field_type_1.FieldType.id, "Personal or group context ID."),
|
|
87
|
+
field("deviceId", field_type_1.FieldType.id, "Repair only what this device has.", {
|
|
88
|
+
optional: true,
|
|
89
|
+
}),
|
|
90
|
+
],
|
|
91
|
+
outputFields: [
|
|
92
|
+
field("repaired", field_type_1.FieldType.number, "Missing changes this device now holds."),
|
|
93
|
+
field("remaining", field_type_1.FieldType.number, "Missing changes still found."),
|
|
94
|
+
field("message", field_type_1.FieldType.string, "Human-readable result."),
|
|
95
|
+
],
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
observables: [
|
|
99
|
+
{
|
|
100
|
+
name: "status",
|
|
101
|
+
description: "Live summary of the latest checks on this device.",
|
|
102
|
+
valueType: field_type_1.FieldType.object,
|
|
103
|
+
writable: false,
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
events: [],
|
|
107
|
+
};
|
|
108
|
+
return definition;
|
|
109
|
+
}
|
|
110
|
+
(0, system_contracts_1.registerSystemContract)({
|
|
111
|
+
providerPackageId: system_ids_1.peersSystemPackageId,
|
|
112
|
+
contractId: system_ids_1.syncCheckContractId,
|
|
113
|
+
version: exports.SYNC_CHECK_CONTRACT_VERSION,
|
|
114
|
+
getDefinition: getSyncCheckContractDefinition,
|
|
115
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type IField } from "../types/field-type";
|
|
2
|
+
/**
|
|
3
|
+
* Check a contract tool's arguments against its declared input fields. The Runtime does this
|
|
4
|
+
* before every tool run, whoever calls: the UI, the CLI, an assistant, a package, or another
|
|
5
|
+
* device. A missing or `null` input counts as `{}`. Optional fields that are `null` are left
|
|
6
|
+
* out first, and an ISO string in a `Date` field is read as a date.
|
|
7
|
+
*
|
|
8
|
+
* @param fields - The tool's input fields, from its contract definition.
|
|
9
|
+
* @param input - The tool's argument as the caller sent it.
|
|
10
|
+
* @param toolName - The tool's name, for the error message.
|
|
11
|
+
* @returns The arguments without empty optional fields and with `Date` fields as dates.
|
|
12
|
+
* @throws If the input isn't an object, or a field is missing, of the wrong type, or not one
|
|
13
|
+
* of its allowed values.
|
|
14
|
+
*/
|
|
15
|
+
export declare function checkToolArguments(fields: IField[], input: unknown, toolName: string): Record<string, unknown>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkToolArguments = checkToolArguments;
|
|
4
|
+
const types_1 = require("../data/orm/types");
|
|
5
|
+
const field_type_1 = require("../types/field-type");
|
|
6
|
+
/**
|
|
7
|
+
* Check a contract tool's arguments against its declared input fields. The Runtime does this
|
|
8
|
+
* before every tool run, whoever calls: the UI, the CLI, an assistant, a package, or another
|
|
9
|
+
* device. A missing or `null` input counts as `{}`. Optional fields that are `null` are left
|
|
10
|
+
* out first, and an ISO string in a `Date` field is read as a date.
|
|
11
|
+
*
|
|
12
|
+
* @param fields - The tool's input fields, from its contract definition.
|
|
13
|
+
* @param input - The tool's argument as the caller sent it.
|
|
14
|
+
* @param toolName - The tool's name, for the error message.
|
|
15
|
+
* @returns The arguments without empty optional fields and with `Date` fields as dates.
|
|
16
|
+
* @throws If the input isn't an object, or a field is missing, of the wrong type, or not one
|
|
17
|
+
* of its allowed values.
|
|
18
|
+
*/
|
|
19
|
+
function checkToolArguments(fields, input, toolName) {
|
|
20
|
+
const source = input ?? {};
|
|
21
|
+
if (typeof source !== "object" ||
|
|
22
|
+
Array.isArray(source) ||
|
|
23
|
+
(Object.getPrototypeOf(source) !== Object.prototype && Object.getPrototypeOf(source) !== null)) {
|
|
24
|
+
throw new Error(`Tool argument validation failed for ${toolName}: input must be an object`);
|
|
25
|
+
}
|
|
26
|
+
// An optional argument that is null (as models often send) or undefined is left out.
|
|
27
|
+
const args = (0, types_1.withoutEmptyFields)(fields, { ...source });
|
|
28
|
+
for (const field of fields) {
|
|
29
|
+
if (field.type === field_type_1.FieldType.Date && !field.isArray && typeof args[field.name] === "string") {
|
|
30
|
+
args[field.name] = new Date(args[field.name]);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// Zod reads named properties, including inherited ones. Object.prototype must not supply
|
|
34
|
+
// a missing argument such as `constructor`, or invalidate an omitted optional one.
|
|
35
|
+
const result = (0, types_1.fieldsToArgumentsSchema)(fields).safeParse(Object.assign(Object.create(null), args));
|
|
36
|
+
if (!result.success) {
|
|
37
|
+
const problems = result.error.issues.map((issue) => `${issue.path.join(".") || "input"}: ${issue.message}`);
|
|
38
|
+
throw new Error(`Tool argument validation failed for ${toolName}: ${problems.join("; ")}`);
|
|
39
|
+
}
|
|
40
|
+
return args;
|
|
41
|
+
}
|
|
@@ -8,15 +8,14 @@ exports.findToolCatalogEntry = findToolCatalogEntry;
|
|
|
8
8
|
exports.projectToolCatalogAccess = projectToolCatalogAccess;
|
|
9
9
|
exports.invokeToolCatalogTool = invokeToolCatalogTool;
|
|
10
10
|
const group_permissions_1 = require("../data/group-permissions");
|
|
11
|
-
const types_1 = require("../data/orm/types");
|
|
12
11
|
const tool_access_1 = require("../data/tool-access");
|
|
13
12
|
const tools_1 = require("../data/tools");
|
|
14
13
|
const system_ids_1 = require("../system-ids");
|
|
15
|
-
const field_type_1 = require("../types/field-type");
|
|
16
14
|
const utils_1 = require("../utils");
|
|
17
15
|
const contract_provider_router_1 = require("./contract-provider-router");
|
|
18
16
|
const contract_resolvers_1 = require("./contract-resolvers");
|
|
19
17
|
const system_contracts_1 = require("./system-contracts");
|
|
18
|
+
const tool_arguments_1 = require("./tool-arguments");
|
|
20
19
|
const tool_catalog_1 = require("./tool-catalog");
|
|
21
20
|
const tool_catalog_identity_1 = require("./tool-catalog-identity");
|
|
22
21
|
const tool_catalog_migrations_1 = require("./tool-catalog-migrations");
|
|
@@ -258,16 +257,7 @@ async function invokeToolCatalogTool(dataContext, input, context, opts = {}) {
|
|
|
258
257
|
if (liveLevel === undefined || liveLevel > opts.maxAccessLevel)
|
|
259
258
|
throw new Error("Tool provider access level exceeds the authorized workflow call");
|
|
260
259
|
}
|
|
261
|
-
const
|
|
262
|
-
requirePlainObject(source, "Tool args");
|
|
263
|
-
// An optional argument that is null (as models often send) or undefined is left out.
|
|
264
|
-
const args = (0, types_1.withoutEmptyFields)(tool.inputFields, { ...source });
|
|
265
|
-
for (const field of tool.inputFields)
|
|
266
|
-
if (field.type === field_type_1.FieldType.Date && !field.isArray && typeof args[field.name] === "string")
|
|
267
|
-
args[field.name] = new Date(args[field.name]);
|
|
268
|
-
const validated = (0, types_1.fieldsToSchema)(tool.inputFields).passthrough().safeParse(args);
|
|
269
|
-
if (!validated.success)
|
|
270
|
-
throw new Error(`Tool argument validation failed: ${validated.error.message}`);
|
|
260
|
+
const args = (0, tool_arguments_1.checkToolArguments)(tool.inputFields, input.args, target.toolName);
|
|
271
261
|
const dataContextId = dataContext.dataContextId;
|
|
272
262
|
const { workflow: _workflow, ...caller } = context;
|
|
273
263
|
const endpointContext = loader.isolatedRuntime?.isInstalled(providerPackageId)
|
|
@@ -51,6 +51,37 @@ export declare const changeRecordSchema: z.ZodObject<{
|
|
|
51
51
|
* One JSON-patch operation (or root snapshot / delete) stored for synchronization.
|
|
52
52
|
*/
|
|
53
53
|
export type IChangeRecord = z.infer<typeof changeRecordSchema>;
|
|
54
|
+
/** Which active changes {@link ChangeTrackingTable.countChanges} counts, and how it groups them. */
|
|
55
|
+
export interface ICountChangesRequest {
|
|
56
|
+
/**
|
|
57
|
+
* Count only change ids below this one. The first 10 characters of a change id are its author
|
|
58
|
+
* time in base36 milliseconds, so a 10-character prefix counts changes written before then.
|
|
59
|
+
*/
|
|
60
|
+
before: string;
|
|
61
|
+
/** Tables to leave out. */
|
|
62
|
+
excludedTableNames?: string[];
|
|
63
|
+
/** Count only this table. */
|
|
64
|
+
tableName?: string;
|
|
65
|
+
/** Count only change ids that start with this. */
|
|
66
|
+
prefix?: string;
|
|
67
|
+
/** Group by the first this-many characters of the change id as well as by table. */
|
|
68
|
+
prefixLength?: number;
|
|
69
|
+
/** Count ids after this entire prefix; also resumes grouped pages (at most 500 rows each). */
|
|
70
|
+
afterPrefix?: string;
|
|
71
|
+
}
|
|
72
|
+
/** Number of active changes in one table (and one id prefix), with a digest of their ids. */
|
|
73
|
+
export interface IChangeCount {
|
|
74
|
+
tableName: string;
|
|
75
|
+
/** The id prefix counted, when the request set `prefixLength`. */
|
|
76
|
+
prefix?: string;
|
|
77
|
+
count: number;
|
|
78
|
+
/**
|
|
79
|
+
* Two sums of numbers taken from the last 10 characters of each change id, as decimal text.
|
|
80
|
+
* Equal counts with different sums mean different changes, such as one device missing an edit
|
|
81
|
+
* that replaced an earlier change.
|
|
82
|
+
*/
|
|
83
|
+
sums: string;
|
|
84
|
+
}
|
|
54
85
|
/**
|
|
55
86
|
* Local-only change log used for peer sync.
|
|
56
87
|
*
|
|
@@ -134,6 +165,15 @@ export declare class ChangeTrackingTable extends SQLDataSource<IChangeRecord> {
|
|
|
134
165
|
* @returns Array of changeIds with no change records
|
|
135
166
|
*/
|
|
136
167
|
filterToMissingChangeIds(changeIds: string[]): Promise<string[]>;
|
|
168
|
+
/**
|
|
169
|
+
* Count active changes per table, or per table and change-id prefix, with a digest of their ids.
|
|
170
|
+
* Two devices holding the same active changes get the same results. One scan of the
|
|
171
|
+
* `(tableName, supersededAt)` index, which holds every change id.
|
|
172
|
+
*
|
|
173
|
+
* @param request - Which changes to count and how to group them
|
|
174
|
+
* @returns One row per table (and prefix) that has any active changes
|
|
175
|
+
*/
|
|
176
|
+
countChanges(request: ICountChangesRequest): Promise<IChangeCount[]>;
|
|
137
177
|
/**
|
|
138
178
|
* Mark every still-active change for `recordId` whose `createdAt` is older
|
|
139
179
|
* than `supersededAt`. Used after a root snapshot, delete, or restore.
|
|
@@ -37,6 +37,12 @@ exports.changeRecordSchema = zod_1.z.object({
|
|
|
37
37
|
.describe("Local apply / sync-visibility time; assigned at insert, incoming values replaced"),
|
|
38
38
|
supersededAt: zod_1.z.number().optional().describe("When this change was superseded; unset if active"),
|
|
39
39
|
});
|
|
40
|
+
/** Five id characters starting at `start`, read as one base-128 number. */
|
|
41
|
+
function idTailNumber(start) {
|
|
42
|
+
return [0, 1, 2, 3, 4]
|
|
43
|
+
.map((i) => `${128 ** (4 - i)} * unicode(substr(changeId, ${start + i}, 1))`)
|
|
44
|
+
.join(" + ");
|
|
45
|
+
}
|
|
40
46
|
const changeTrackingV2TableMetaData = {
|
|
41
47
|
name: "ChangeTrackingV2",
|
|
42
48
|
primaryKeyName: "changeId",
|
|
@@ -228,6 +234,89 @@ class ChangeTrackingTable extends orm_1.SQLDataSource {
|
|
|
228
234
|
`, changeIds);
|
|
229
235
|
return missingChangeIds.map((d) => d.changeId);
|
|
230
236
|
}
|
|
237
|
+
/**
|
|
238
|
+
* Count active changes per table, or per table and change-id prefix, with a digest of their ids.
|
|
239
|
+
* Two devices holding the same active changes get the same results. One scan of the
|
|
240
|
+
* `(tableName, supersededAt)` index, which holds every change id.
|
|
241
|
+
*
|
|
242
|
+
* @param request - Which changes to count and how to group them
|
|
243
|
+
* @returns One row per table (and prefix) that has any active changes
|
|
244
|
+
*/
|
|
245
|
+
async countChanges(request) {
|
|
246
|
+
if (!request ||
|
|
247
|
+
typeof request.before !== "string" ||
|
|
248
|
+
!/^[0-9a-z]{1,25}$/i.test(request.before) ||
|
|
249
|
+
(request.tableName !== undefined &&
|
|
250
|
+
(typeof request.tableName !== "string" ||
|
|
251
|
+
!request.tableName ||
|
|
252
|
+
request.tableName.length > 256)) ||
|
|
253
|
+
(request.prefix !== undefined &&
|
|
254
|
+
(typeof request.prefix !== "string" || !/^[0-9a-z]{0,25}$/i.test(request.prefix))) ||
|
|
255
|
+
(request.prefixLength !== undefined &&
|
|
256
|
+
(!Number.isInteger(request.prefixLength) ||
|
|
257
|
+
request.prefixLength < 1 ||
|
|
258
|
+
request.prefixLength > 25 ||
|
|
259
|
+
!request.tableName ||
|
|
260
|
+
request.prefixLength <= (request.prefix?.length ?? 0))) ||
|
|
261
|
+
(request.afterPrefix !== undefined &&
|
|
262
|
+
(typeof request.afterPrefix !== "string" ||
|
|
263
|
+
!request.tableName ||
|
|
264
|
+
!/^[0-9a-z]{1,25}$/i.test(request.afterPrefix))) ||
|
|
265
|
+
(request.excludedTableNames !== undefined &&
|
|
266
|
+
(!Array.isArray(request.excludedTableNames) ||
|
|
267
|
+
request.excludedTableNames.some((name) => typeof name !== "string" || name.length > 256)))) {
|
|
268
|
+
throw new Error("Invalid countChanges request");
|
|
269
|
+
}
|
|
270
|
+
await this.initTable();
|
|
271
|
+
const { before, excludedTableNames = [], tableName, prefix, prefixLength, afterPrefix, } = request;
|
|
272
|
+
const conditions = ["supersededAt IS NULL", "changeId < ?"];
|
|
273
|
+
const params = [before];
|
|
274
|
+
// Without one table, list the table names with a seek per name. Without index statistics,
|
|
275
|
+
// SQLite would otherwise read every row through the (supersededAt, ...) index, which lacks
|
|
276
|
+
// tableName, instead of scanning the covering one.
|
|
277
|
+
let tableNames = "";
|
|
278
|
+
if (tableName !== undefined) {
|
|
279
|
+
conditions.push("tableName = ?");
|
|
280
|
+
params.push(tableName);
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
tableNames = `WITH RECURSIVE names(name) AS (
|
|
284
|
+
SELECT MIN(tableName) FROM "${this.tableName}"
|
|
285
|
+
UNION ALL
|
|
286
|
+
SELECT (SELECT MIN(tableName) FROM "${this.tableName}" WHERE tableName > names.name)
|
|
287
|
+
FROM names WHERE names.name IS NOT NULL
|
|
288
|
+
)`;
|
|
289
|
+
conditions.push("tableName IN (SELECT name FROM names)");
|
|
290
|
+
}
|
|
291
|
+
if (excludedTableNames.length) {
|
|
292
|
+
conditions.push(`tableName NOT IN (${excludedTableNames.map(() => "?").join(", ")})`);
|
|
293
|
+
params.push(...excludedTableNames);
|
|
294
|
+
}
|
|
295
|
+
if (prefix) {
|
|
296
|
+
// Change ids are lowercase base36, so every id with this prefix sorts below `prefix~`.
|
|
297
|
+
conditions.push("changeId >= ?", "changeId < ?");
|
|
298
|
+
params.push(prefix, `${prefix}~`);
|
|
299
|
+
}
|
|
300
|
+
if (afterPrefix) {
|
|
301
|
+
conditions.push("changeId > ?");
|
|
302
|
+
params.push(`${afterPrefix}~`);
|
|
303
|
+
}
|
|
304
|
+
const length = prefixLength ?? 0;
|
|
305
|
+
const prefixColumn = length ? `, substr(changeId, 1, ${length}) AS prefix` : "";
|
|
306
|
+
const rows = await this.db.all(`${tableNames}
|
|
307
|
+
SELECT tableName${prefixColumn}, COUNT(*) AS count,
|
|
308
|
+
CAST(SUM(${idTailNumber(16)}) AS TEXT) || ':' || CAST(SUM(${idTailNumber(21)}) AS TEXT) AS sums
|
|
309
|
+
FROM "${this.tableName}"
|
|
310
|
+
WHERE ${conditions.join(" AND ")}
|
|
311
|
+
GROUP BY tableName${length ? ", prefix" : ""}
|
|
312
|
+
ORDER BY tableName${length ? ", prefix LIMIT 500" : ""}`, params);
|
|
313
|
+
return rows.map((row) => ({
|
|
314
|
+
tableName: row.tableName,
|
|
315
|
+
...(length ? { prefix: row.prefix } : {}),
|
|
316
|
+
count: Number(row.count),
|
|
317
|
+
sums: String(row.sums),
|
|
318
|
+
}));
|
|
319
|
+
}
|
|
231
320
|
/**
|
|
232
321
|
* Mark every still-active change for `recordId` whose `createdAt` is older
|
|
233
322
|
* than `supersededAt`. Used after a root snapshot, delete, or restore.
|