@zhin.js/testing 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -1
- package/lib/fake-clock.d.ts +7 -2
- package/lib/fake-clock.d.ts.map +1 -1
- package/lib/fake-clock.js +15 -4
- package/lib/fake-clock.js.map +1 -1
- package/lib/fake-hosts.d.ts +1 -1
- package/lib/fake-hosts.d.ts.map +1 -1
- package/lib/fake-plugin.d.ts +37 -4
- package/lib/fake-plugin.d.ts.map +1 -1
- package/lib/fake-plugin.js +57 -4
- package/lib/fake-plugin.js.map +1 -1
- package/lib/fake-runners.d.ts +56 -3
- package/lib/fake-runners.d.ts.map +1 -1
- package/lib/fake-runners.js +97 -2
- package/lib/fake-runners.js.map +1 -1
- package/lib/index.d.ts +16 -8
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +9 -5
- package/lib/index.js.map +1 -1
- package/lib/test-module-runtime.d.ts +1 -1
- package/lib/test-module-runtime.d.ts.map +1 -1
- package/lib/test-module-runtime.js +1 -1
- package/lib/test-module-runtime.js.map +1 -1
- package/package.json +14 -12
- package/src/fake-clock.ts +14 -4
- package/src/fake-hosts.ts +1 -1
- package/src/fake-plugin.ts +71 -5
- package/src/fake-runners.ts +153 -5
- package/src/index.ts +17 -8
- package/src/test-module-runtime.ts +2 -2
package/lib/fake-runners.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fake-runners.js","sourceRoot":"","sources":["../src/fake-runners.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fake-runners.js","sourceRoot":"","sources":["../src/fake-runners.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
import { type AdapterSegmentPolicy, type EndpointIncomingMessage } from '
|
|
2
|
-
import { ImRuntime, type ConversationAddress, type MessageDispatchResult, type SendContent } from '
|
|
3
|
-
import { type ConversationRef, type DeliveryReceipt } from '
|
|
4
|
-
import { type ConfigPatch, type PluginId, type RuntimeConfigDocument } from '
|
|
5
|
-
import { type ModuleRuntime, type RootResourceInstaller } from '@zhin.js/runtime';
|
|
1
|
+
import { type AdapterSegmentPolicy, type EndpointIncomingMessage } from 'zhin.js/adapter';
|
|
2
|
+
import { ImRuntime, type ConversationAddress, type MessageDispatchResult, type RuntimeMessageDiagnosticsReader, type SendContent } from 'zhin.js/core/runtime';
|
|
3
|
+
import { type ConversationRef, type DeliveryReceipt } from 'zhin.js';
|
|
4
|
+
import { type ConfigDocumentPort, type ConfigPatch, type PluginId, type RuntimeConfigDocument } from 'zhin.js/plugin-runtime';
|
|
5
|
+
import { RootRuntime, type ModuleRuntime, type RootResourceInstaller } from '@zhin.js/runtime';
|
|
6
6
|
export { FakeClock, FakeScheduleRootHost, parseCron, type FakeScheduledJob } from './fake-clock.js';
|
|
7
7
|
export { FakeDatabaseRootHost, FakeOutboundRootHost, type FakeOutboundCall } from './fake-hosts.js';
|
|
8
|
-
export { FakePlugin, createFakePlugin, runPluginSetup, fakeResource, type FakePluginOptions, type FakeResource, type FakeRegisteredFeature } from './fake-plugin.js';
|
|
8
|
+
export { FakePlugin, createFakePlugin, runPluginSetup, resolvePluginConfig, PluginConfigValidationError, fakeResource, type FakePluginOptions, type RunPluginSetupOptions, type FakeResource, type FakeRegisteredFeature } from './fake-plugin.js';
|
|
9
9
|
export { fakeOf } from './partial.js';
|
|
10
|
-
export { createFakeMessage, createCommandContext, runCommand, runMiddleware, runHandler, type FakeMessage, type FakeMessageInit, type RunCommandOptions, type RunMiddlewareResult } from './fake-runners.js';
|
|
10
|
+
export { createFakeMessage, createCommandContext, runCommand, runMiddleware, runHandler, createToolContext, runTool, toolOriginFromMessage, type FakeMessage, type RunToolOptions, type FakeMessageInit, type RunCommandOptions, type RunMiddlewareResult } from './fake-runners.js';
|
|
11
11
|
export interface PluginTestKitOptions {
|
|
12
12
|
/** A real, disposable test app with its own package.json, plugin entry, dependencies and mounts. */
|
|
13
13
|
readonly projectRoot: string;
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* A v2 document, or a file-backed document such as `createConfigDocument(path)` from
|
|
16
|
+
* `@zhin.js/config-file` when the test must share the same file authority as `zhin start`.
|
|
17
|
+
*/
|
|
18
|
+
readonly config?: RuntimeConfigDocument | ConfigDocumentPort;
|
|
15
19
|
/** Adapter names reserved for synthetic transports, default: ['test']. */
|
|
16
20
|
readonly endpoints?: readonly string[];
|
|
17
21
|
/** Default endpoint renders HTML and buttons as text; override to verify negotiated capabilities. */
|
|
@@ -54,6 +58,10 @@ export declare class PluginTestKit {
|
|
|
54
58
|
static create(options: PluginTestKitOptions): Promise<PluginTestKit>;
|
|
55
59
|
/** The same PermissionHost consumed by real command admission. */
|
|
56
60
|
get permissions(): ImRuntime['permissionHost'];
|
|
61
|
+
/** The same bounded, body-free reader the Console serves at `GET /api/messages/diagnostics`. */
|
|
62
|
+
get messageDiagnostics(): RuntimeMessageDiagnosticsReader;
|
|
63
|
+
/** The committed-snapshot authority Console routes read (tasks, permissions); read-only use in tests. */
|
|
64
|
+
get snapshots(): RootRuntime['snapshots'];
|
|
57
65
|
get generation(): number;
|
|
58
66
|
get deliveries(): readonly TestDelivery[];
|
|
59
67
|
clearDeliveries(): void;
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAyC,KAAK,oBAAoB,EACxB,KAAK,uBAAuB,EAA4B,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/lib/index.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { realpath } from 'node:fs/promises';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
|
-
import { defineAdapter } from '
|
|
4
|
-
import { ImRuntime } from '
|
|
5
|
-
import { rootPluginId } from '
|
|
3
|
+
import { defineAdapter } from 'zhin.js/adapter';
|
|
4
|
+
import { ImRuntime } from 'zhin.js/core/runtime';
|
|
5
|
+
import { rootPluginId } from 'zhin.js/plugin-runtime';
|
|
6
6
|
import { NativeDevelopmentModuleRuntime, NodePackageResolver, RootRuntime } from '@zhin.js/runtime';
|
|
7
7
|
import { captureDeliveryValue } from './delivery-capture.js';
|
|
8
8
|
import { withTestEndpoints } from './test-module-runtime.js';
|
|
9
9
|
export { FakeClock, FakeScheduleRootHost, parseCron } from './fake-clock.js';
|
|
10
10
|
export { FakeDatabaseRootHost, FakeOutboundRootHost } from './fake-hosts.js';
|
|
11
|
-
export { FakePlugin, createFakePlugin, runPluginSetup, fakeResource } from './fake-plugin.js';
|
|
11
|
+
export { FakePlugin, createFakePlugin, runPluginSetup, resolvePluginConfig, PluginConfigValidationError, fakeResource } from './fake-plugin.js';
|
|
12
12
|
export { fakeOf } from './partial.js';
|
|
13
|
-
export { createFakeMessage, createCommandContext, runCommand, runMiddleware, runHandler } from './fake-runners.js';
|
|
13
|
+
export { createFakeMessage, createCommandContext, runCommand, runMiddleware, runHandler, createToolContext, runTool, toolOriginFromMessage } from './fake-runners.js';
|
|
14
14
|
/**
|
|
15
15
|
* Owns a test IM host and synthetic transports. Every operation enters the real Root Runtime.
|
|
16
16
|
* It does not install dependencies or replace providers. Discovered plugins still execute normally;
|
|
@@ -88,6 +88,10 @@ export class PluginTestKit {
|
|
|
88
88
|
}
|
|
89
89
|
/** The same PermissionHost consumed by real command admission. */
|
|
90
90
|
get permissions() { return this.#im.permissionHost; }
|
|
91
|
+
/** The same bounded, body-free reader the Console serves at `GET /api/messages/diagnostics`. */
|
|
92
|
+
get messageDiagnostics() { return this.#im.messageDiagnostics; }
|
|
93
|
+
/** The committed-snapshot authority Console routes read (tasks, permissions); read-only use in tests. */
|
|
94
|
+
get snapshots() { return this.#root.snapshots; }
|
|
91
95
|
get generation() { return this.#root.snapshot.generation; }
|
|
92
96
|
get deliveries() { return Object.freeze(this.#attempts.map(item => captureDeliveryValue(item))); }
|
|
93
97
|
clearDeliveries() { this.#attempts.splice(0); }
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EACmF,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EACmF,MAAM,iBAAiB,CAAC;AACjI,OAAO,EAAE,SAAS,EACwC,MAAM,sBAAsB,CAAC;AAEvF,OAAO,EAAE,YAAY,EAAwF,MAAM,wBAAwB,CAAC;AAC5I,OAAO,EAAE,8BAA8B,EAAE,mBAAmB,EAAE,WAAW,EACvB,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,SAAS,EAAyB,MAAM,iBAAiB,CAAC;AACpG,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAyB,MAAM,iBAAiB,CAAC;AACpG,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,cAAc,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,YAAY,EAChB,MAAM,kBAAkB,CAAC;AAC9H,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EACrF,iBAAiB,EAAE,OAAO,EAAE,qBAAqB,EAC8D,MAAM,mBAAmB,CAAC;AAmC3I;;;;GAIG;AACH,MAAM,OAAO,aAAa;IACf,GAAG,CAAY;IACf,KAAK,CAAc;IACnB,MAAM,GAAG,IAAI,GAAG,EAA6B,CAAC;IAC9C,WAAW,GAAG,IAAI,GAAG,EAA4B,CAAC;IAC3D,aAAa,GAAG,CAAC,CAAC;IACT,SAAS,GAAmB,EAAE,CAAC;IAC/B,gBAAgB,CAAS;IACzB,IAAI,CAAkD;IAC/D,eAAe,CAAqB;IACpC,QAAQ,GAAG,KAAK,CAAC;IACjB,OAAO,GAAG,KAAK,CAAC;IAChB,YAAY,CAAmB;IAC/B,YAAY,CAAiB;IAE7B,YAAoB,OAA6B,EAAE,WAAmB,EAAE,SAAiB;QACvF,IAAI,CAAC,GAAG,GAAG,IAAI,SAAS,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;QACnE,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5C,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM;eACpD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YACzD,MAAM,IAAI,SAAS,CAAC,iDAAiD,CAAC,CAAC;QACzE,CAAC;QACD,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QAClC,MAAM,WAAW,GAAG,IAAI,GAAG,CAA4B,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,aAAa,CAAC;gBAC5F,YAAY,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC;gBACrC,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE;gBACrF,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;oBACb,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;oBAC1C,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE;wBAChC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;wBACrC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;wBAC9B,OAAO,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,MAAM,EAAE,CAAC;4BAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;4BAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;wBAAC,CAAC,CAAC,CAAC,CAAC;oBACtH,CAAC;oBACD,IAAI,EAAE,CAAC,OAA4B,EAAE,EAAE;wBACrC,MAAM,EAAE,GAAG,QAAQ,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;wBAC1C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;4BACpD,YAAY,EAAE,oBAAoB,CAAC,OAAO,CAAC,YAAY,CAAC;4BACxD,OAAO,EAAE,oBAAoB,CAAC,OAAO,CAAC,OAAO,CAAC;yBAC/C,CAAC,CAAC,CAAC;wBACJ,OAAO,EAAE,CAAC;oBACZ,CAAC;iBACF,CAAC;aACH,CAAC,CAAC,CAAC,CAAC,CAAC;QACN,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,IAAI,8BAA8B,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QACrG,IAAI,CAAC,KAAK,GAAG,IAAI,WAAW,CAAC,EAAE,WAAW;YACxC,OAAO,EAAE,iBAAiB,CAAC,OAAO,EAAE,SAAS,EAAE,WAAW,CAAC;YAC3D,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE;YAC7D,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE,aAAa,EAAE,CAAC,EAAE;YAC9C,gBAAgB,EAAE,KAAK,EAAC,OAAO,EAAC,EAAE;gBAChC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;gBACpC,MAAM,OAAO,CAAC,gBAAgB,EAAE,CAAC,OAAO,CAAC,CAAC;YAC5C,CAAC;SACF,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC;YAC1C,iBAAiB,EAAE,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;YACnE,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;SACzB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAA6B;QAC/C,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;QACjE,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAC/D,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC9C,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;YAC5F,MAAM,IAAI,SAAS,CAAC,gDAAgD,CAAC,CAAC;QACxE,CAAC;QACD,OAAO,IAAI,aAAa,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACpG,CAAC;IAED,kEAAkE;IAClE,IAAI,WAAW,KAAkC,OAAO,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;IAClF,gGAAgG;IAChG,IAAI,kBAAkB,KAAsC,OAAO,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACjG,yGAAyG;IACzG,IAAI,SAAS,KAA+B,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAC1E,IAAI,UAAU,KAAa,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;IACnE,IAAI,UAAU,KAA8B,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3H,eAAe,KAAW,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAErD,KAAK;QACH,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC,CAAC;QAChF,IAAI,IAAI,CAAC,YAAY;YAAE,OAAO,IAAI,CAAC,YAAY,CAAC;QAChD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;YACrD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;YACrB,OAAO,QAAQ,CAAC,UAAU,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAAuB;QACnC,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,EAAE,GAAG,KAAK,CAAC;QACvC,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,OAAO,CAAsC,CAAC;IAC1F,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAY,EAAE,OAAgB,EAAE,QAAiB;QAC1D,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KACkD;QAC3D,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,gBAAgB,CAAC;QACrD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC;QAC7C,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,YAAY,EAAE,EAAE,GAAG,KAAK,CAAC,YAAY,EAAE,QAAQ,EAAE;oBACtE,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO;iBACnD,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,YAAY,EAAE,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,4FAA4F;IAC5F,KAAK,CAAC,YAAY,CAAC,MAAc;QAC/B,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC;QACjC,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAChC,IAAI,IAAI,CAAC,eAAe;gBAAE,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,kBAAkB;oBACzE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC;YACpF,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;QACzH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAA+B;QAC/C,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;IAC5D,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,YAAY;YAAE,OAAO,IAAI,CAAC,YAAY,CAAC;QAChD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,YAAY,GAAG,CAAC,KAAK,IAAI,EAAE;YAC9B,IAAI,CAAC;gBAAC,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAAC,CAAC;oBACvB,CAAC;gBAAC,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YAAC,CAAC;QACtC,CAAC,CAAC,EAAE,CAAC;QACL,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,cAAc;QACZ,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACxF,CAAC;IACD,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,gBAAgB;QACpC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,EAAE,CAAC,CAAC;QACjE,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AdapterDefinition } from '
|
|
1
|
+
import type { AdapterDefinition } from 'zhin.js/adapter';
|
|
2
2
|
import type { ModuleRuntime } from '@zhin.js/runtime';
|
|
3
3
|
/** Only the test application's setup is decorated; discovery and module caching stay native. */
|
|
4
4
|
export declare function withTestEndpoints(delegate: ModuleRuntime, rootEntry: string, endpoints: ReadonlyMap<string, AdapterDefinition>): ModuleRuntime;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-module-runtime.d.ts","sourceRoot":"","sources":["../src/test-module-runtime.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"test-module-runtime.d.ts","sourceRoot":"","sources":["../src/test-module-runtime.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,gGAAgG;AAChG,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,aAAa,EACvB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAChD,aAAa,CA2Bf"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { resolve } from 'node:path';
|
|
2
|
-
import { definePlugin } from '
|
|
2
|
+
import { definePlugin } from 'zhin.js/plugin-runtime';
|
|
3
3
|
/** Only the test application's setup is decorated; discovery and module caching stay native. */
|
|
4
4
|
export function withTestEndpoints(delegate, rootEntry, endpoints) {
|
|
5
5
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-module-runtime.js","sourceRoot":"","sources":["../src/test-module-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAyB,MAAM,
|
|
1
|
+
{"version":3,"file":"test-module-runtime.js","sourceRoot":"","sources":["../src/test-module-runtime.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/testing",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "Real Plugin Runtime integration fixtures with synthetic IM endpoints",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -16,21 +16,23 @@
|
|
|
16
16
|
"src",
|
|
17
17
|
"README.md"
|
|
18
18
|
],
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"@zhin.js/
|
|
22
|
-
"@zhin.js/
|
|
23
|
-
"@zhin.js/feature-kit": "1.1.6",
|
|
24
|
-
"@zhin.js/handler": "1.1.6",
|
|
25
|
-
"@zhin.js/middleware": "1.1.7",
|
|
26
|
-
"@zhin.js/im-contract": "1.1.4",
|
|
27
|
-
"@zhin.js/plugin-runtime": "1.1.15",
|
|
28
|
-
"@zhin.js/runtime": "1.1.9"
|
|
19
|
+
"peerDependencies": {
|
|
20
|
+
"zhin.js": "^1.1.16",
|
|
21
|
+
"@zhin.js/runtime": "^1.1.14",
|
|
22
|
+
"@zhin.js/tool": "^1.1.10"
|
|
29
23
|
},
|
|
30
24
|
"devDependencies": {
|
|
31
25
|
"@types/node": "^26.1.2",
|
|
32
26
|
"typescript": "^6.0.3",
|
|
33
|
-
"vitest": "^4.1.10"
|
|
27
|
+
"vitest": "^4.1.10",
|
|
28
|
+
"@zhin.js/adapter": "1.1.23",
|
|
29
|
+
"@zhin.js/command": "1.1.11",
|
|
30
|
+
"@zhin.js/core": "1.1.51",
|
|
31
|
+
"@zhin.js/middleware": "1.1.10",
|
|
32
|
+
"@zhin.js/plugin-runtime": "1.1.17",
|
|
33
|
+
"@zhin.js/runtime": "1.1.14",
|
|
34
|
+
"@zhin.js/tool": "1.1.10",
|
|
35
|
+
"zhin.js": "1.1.16"
|
|
34
36
|
},
|
|
35
37
|
"engines": {
|
|
36
38
|
"node": ">=22.19.0"
|
package/src/fake-clock.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PluginId, ScheduleHost, ScheduleJobRegistration } from '
|
|
1
|
+
import type { PluginId, ScheduleHost, ScheduleJobRegistration } from 'zhin.js/plugin-runtime';
|
|
2
2
|
|
|
3
3
|
/** Controllable wall clock. It never touches the real `Date` or timers. */
|
|
4
4
|
export class FakeClock {
|
|
@@ -15,13 +15,21 @@ export class FakeClock {
|
|
|
15
15
|
/** Jump without firing anything (like setting the system time). */
|
|
16
16
|
set(time: number | Date): void { this.#now = typeof time === 'number' ? time : time.getTime(); }
|
|
17
17
|
|
|
18
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* Move forward and run every cron job that became due, in time order.
|
|
20
|
+
*
|
|
21
|
+
* The clock always ends at the target time, even when a job throws. After a failure the error
|
|
22
|
+
* is rethrown and the remaining jobs due inside the same window are NOT run (they are skipped, not deferred).
|
|
23
|
+
*/
|
|
19
24
|
async advance(ms: number): Promise<void> {
|
|
20
25
|
if (!(ms >= 0)) throw new RangeError('FakeClock.advance requires a non-negative duration');
|
|
21
26
|
const from = this.#now;
|
|
22
27
|
const to = from + ms;
|
|
23
|
-
|
|
24
|
-
|
|
28
|
+
try {
|
|
29
|
+
for (const listener of [...this.#listeners]) await listener(from, to);
|
|
30
|
+
} finally {
|
|
31
|
+
this.#now = to;
|
|
32
|
+
}
|
|
25
33
|
}
|
|
26
34
|
|
|
27
35
|
/** @internal */
|
|
@@ -89,6 +97,8 @@ export class FakeScheduleRootHost implements ScheduleHost {
|
|
|
89
97
|
clock.onAdvance(async (from, to) => {
|
|
90
98
|
for (let t = Math.floor(from / 1000) * 1000 + 1000; t <= to; t += 1000) {
|
|
91
99
|
const date = new Date(t);
|
|
100
|
+
// A job firing at `t` must observe `t` (e.g. to decide what is due), not the advance() start.
|
|
101
|
+
clock.set(t);
|
|
92
102
|
for (const job of [...this.#jobs]) {
|
|
93
103
|
if (this.#jobs.has(job) && job.isActive?.() !== false && job.matches(date)) await job.execute();
|
|
94
104
|
}
|
package/src/fake-hosts.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type {
|
|
|
3
3
|
DatabaseHost, DatabaseHostModel, DatabaseHostSelection, DeliveryTarget, JsonValue,
|
|
4
4
|
OutboundEditInput, OutboundReactionInput, OutboundRecallInput, OutboundRootHost, OutboundSendInput,
|
|
5
5
|
OutboundTypingInput, PersistentStatePort, PluginId, StateRecord, StateScope,
|
|
6
|
-
} from '
|
|
6
|
+
} from 'zhin.js/plugin-runtime';
|
|
7
7
|
|
|
8
8
|
type Row = Record<string, unknown>;
|
|
9
9
|
const matches = (row: Row, query: Row): boolean => Object.entries(query).every(([k, v]) => row[k] === v);
|
package/src/fake-plugin.ts
CHANGED
|
@@ -3,8 +3,9 @@ import {
|
|
|
3
3
|
Scope, databaseHostToken, outboundHostToken, qualifyPluginResourceName, rootPluginId, scheduleHostToken,
|
|
4
4
|
type Dispose, type FeatureId, type PluginDefinition, type PluginId, type PluginNodeSnapshot,
|
|
5
5
|
type PluginSetupContext, type Token,
|
|
6
|
-
} from '
|
|
7
|
-
import type { CapabilityContext } from '
|
|
6
|
+
} from 'zhin.js/plugin-runtime';
|
|
7
|
+
import type { CapabilityContext } from 'zhin.js';
|
|
8
|
+
import { parsePluginConfigSchema } from '@zhin.js/runtime';
|
|
8
9
|
import { FakeClock, FakeScheduleRootHost } from './fake-clock.js';
|
|
9
10
|
import { FakeDatabaseRootHost, FakeOutboundRootHost, type FakeOutboundCall } from './fake-hosts.js';
|
|
10
11
|
|
|
@@ -118,6 +119,7 @@ export class FakePlugin<TConfig = unknown> {
|
|
|
118
119
|
signal: this.signal, owner, generation: this.generation,
|
|
119
120
|
config: this.config as Readonly<TConfig>,
|
|
120
121
|
use: <T>(token: Token<T>): T => this.resources.use(token),
|
|
122
|
+
has: (token: Token<unknown>): boolean => this.resources.has(token),
|
|
121
123
|
project: <T>(feature: FeatureId): T => {
|
|
122
124
|
if (!this.projections.has(feature)) throw new Error(`Missing Feature projection ${feature}`);
|
|
123
125
|
return this.projections.get(feature) as T;
|
|
@@ -160,12 +162,76 @@ export function createFakePlugin<TConfig = unknown>(options?: FakePluginOptions<
|
|
|
160
162
|
return new FakePlugin(options);
|
|
161
163
|
}
|
|
162
164
|
|
|
163
|
-
|
|
165
|
+
export interface RunPluginSetupOptions<TConfig = unknown> extends Omit<FakePluginOptions<TConfig>, 'name' | 'config'> {
|
|
166
|
+
/**
|
|
167
|
+
* Raw plugin configuration, as a user would write it under the instance key in `zhin.config.yml`.
|
|
168
|
+
* When the definition declares `config`, it is validated and defaulted like the real Runtime does.
|
|
169
|
+
*/
|
|
170
|
+
readonly config?: Partial<TConfig>;
|
|
171
|
+
/**
|
|
172
|
+
* Validate `config` against `definition.config` and apply its defaults (default `true`).
|
|
173
|
+
* Set `false` to pass `config` to `setup()` verbatim, as earlier versions of `runPluginSetup` did.
|
|
174
|
+
*/
|
|
175
|
+
readonly validateConfig?: boolean;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** Thrown by {@link runPluginSetup} / {@link resolvePluginConfig} when config fails the plugin's schema. */
|
|
179
|
+
export class PluginConfigValidationError extends TypeError {
|
|
180
|
+
override readonly name = 'PluginConfigValidationError';
|
|
181
|
+
constructor(
|
|
182
|
+
readonly plugin: string,
|
|
183
|
+
/** Human-readable `instancePath message` lines, same wording as Runtime startup errors. */
|
|
184
|
+
readonly issues: readonly string[],
|
|
185
|
+
) {
|
|
186
|
+
super(`Invalid config for plugin ${plugin}:\n ${issues.join('\n ')}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Resolve the config view `setup()` would receive from the real Runtime: validate `input` against
|
|
192
|
+
* `definition.config`, fill schema defaults, and keep only the top-level fields the schema declares.
|
|
193
|
+
* Without a declared `config` schema the input is returned unchanged (`{}` when omitted).
|
|
194
|
+
*/
|
|
195
|
+
export function resolvePluginConfig<TConfig = unknown>(
|
|
196
|
+
definition: Pick<PluginDefinition<TConfig>, 'name' | 'config'>,
|
|
197
|
+
input?: unknown,
|
|
198
|
+
): TConfig {
|
|
199
|
+
if (!definition.config) return (input ?? {}) as TConfig;
|
|
200
|
+
const schema = definition.config.toJsonSchema();
|
|
201
|
+
const { value, errors } = parsePluginConfigSchema(schema, input);
|
|
202
|
+
if (errors.length) {
|
|
203
|
+
throw new PluginConfigValidationError(definition.name, errors.map((error) => {
|
|
204
|
+
const params = error.params as Record<string, unknown> | undefined;
|
|
205
|
+
const detail = typeof params?.additionalProperty === 'string'
|
|
206
|
+
? ` (additionalProperty: ${params.additionalProperty})`
|
|
207
|
+
: Array.isArray(params?.allowedValues) ? ` (allowedValues: ${JSON.stringify(params.allowedValues)})` : '';
|
|
208
|
+
const path = error.instancePath.replace(/^\/candidate/, '');
|
|
209
|
+
return `${path || '/'} ${error.message ?? error.keyword}${detail}`;
|
|
210
|
+
}));
|
|
211
|
+
}
|
|
212
|
+
// The Runtime re-picks a plugin's own top-level fields (see config-composer `pickOwnFields`).
|
|
213
|
+
const properties = schema.properties && typeof schema.properties === 'object' && !Array.isArray(schema.properties)
|
|
214
|
+
? Object.keys(schema.properties)
|
|
215
|
+
: [];
|
|
216
|
+
const record = value && typeof value === 'object' ? value as Record<string, unknown> : {};
|
|
217
|
+
const view: Record<string, unknown> = {};
|
|
218
|
+
for (const key of properties) if (Object.hasOwn(record, key)) view[key] = record[key];
|
|
219
|
+
return view as TConfig;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Create a fake and run `definition.setup()` in one step. Call `dispose()` when done.
|
|
224
|
+
*
|
|
225
|
+
* When the plugin declares a `config` schema, `options.config` is validated and defaulted first
|
|
226
|
+
* (throws {@link PluginConfigValidationError}); pass `validateConfig: false` to opt out.
|
|
227
|
+
*/
|
|
164
228
|
export async function runPluginSetup<TConfig = unknown>(
|
|
165
229
|
definition: PluginDefinition<TConfig>,
|
|
166
|
-
options
|
|
230
|
+
options: RunPluginSetupOptions<TConfig> = {},
|
|
167
231
|
): Promise<FakePlugin<TConfig>> {
|
|
168
|
-
const
|
|
232
|
+
const { validateConfig = true, config, ...rest } = options;
|
|
233
|
+
const resolved = validateConfig ? resolvePluginConfig(definition, config) : config as TConfig | undefined;
|
|
234
|
+
const fake = new FakePlugin<TConfig>({ ...rest, ...(resolved === undefined ? {} : { config: resolved }), name: definition.name });
|
|
169
235
|
await fake.setup(definition);
|
|
170
236
|
return fake;
|
|
171
237
|
}
|
package/src/fake-runners.ts
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
|
+
import { resolveLocale, type Locale } from 'zhin.js/i18n';
|
|
1
2
|
import type {
|
|
2
3
|
CommandContext, CommandDefinition, CommandMessage, CommandParameterValue,
|
|
3
|
-
} from '
|
|
4
|
-
import type { HandlerContext, HandlerDefinition } from '
|
|
4
|
+
} from 'zhin.js/command';
|
|
5
|
+
import type { HandlerContext, HandlerDefinition } from 'zhin.js/handler';
|
|
5
6
|
import type {
|
|
6
7
|
MiddlewareContext, MiddlewareDefinition, MiddlewareNext,
|
|
7
|
-
} from '
|
|
8
|
+
} from 'zhin.js/middleware';
|
|
9
|
+
import {
|
|
10
|
+
parseToolInputSchema,
|
|
11
|
+
type AgentToolDefinition, type ToolExecutionContext, type ToolInvocationOrigin,
|
|
12
|
+
type ToolInvocationPolicy, type ToolQuestionPort,
|
|
13
|
+
} from '@zhin.js/tool';
|
|
14
|
+
import type { OperationClientPort } from 'zhin.js';
|
|
8
15
|
import type { FakePlugin } from './fake-plugin.js';
|
|
16
|
+
import { fileURLToPath } from 'node:url';
|
|
9
17
|
|
|
10
18
|
/** Inbound message with recorded replies. */
|
|
11
19
|
export interface FakeMessage extends CommandMessage {
|
|
@@ -14,6 +22,7 @@ export interface FakeMessage extends CommandMessage {
|
|
|
14
22
|
}
|
|
15
23
|
|
|
16
24
|
export interface FakeMessageInit {
|
|
25
|
+
readonly locale?: Locale;
|
|
17
26
|
readonly content?: string;
|
|
18
27
|
readonly sender?: { readonly id: string; readonly name?: string; readonly roles?: readonly string[] };
|
|
19
28
|
readonly conversation?: Partial<CommandMessage['conversation']>;
|
|
@@ -28,7 +37,7 @@ export function createFakeMessage(init: FakeMessageInit = {}): FakeMessage {
|
|
|
28
37
|
endpoint: { id: 'test', adapter: 'test' }, kind: 'group', id: 'test-group', ...init.conversation,
|
|
29
38
|
};
|
|
30
39
|
return {
|
|
31
|
-
conversation, content: init.content ?? '',
|
|
40
|
+
conversation, content: init.content ?? '', locale: resolveLocale(init.locale),
|
|
32
41
|
sender: init.sender ?? { id: 'test-user', name: 'Tester', roles: [] },
|
|
33
42
|
...(init.id === undefined ? {} : { id: init.id }),
|
|
34
43
|
...(init.metadata === undefined ? {} : { metadata: init.metadata }),
|
|
@@ -39,12 +48,22 @@ export function createFakeMessage(init: FakeMessageInit = {}): FakeMessage {
|
|
|
39
48
|
}
|
|
40
49
|
|
|
41
50
|
export interface RunCommandOptions<TInput extends CommandMessage = FakeMessage> {
|
|
51
|
+
readonly locale?: Locale;
|
|
52
|
+
readonly formatCommand?: CommandContext['formatCommand'];
|
|
42
53
|
readonly input?: TInput;
|
|
43
54
|
readonly args?: readonly string[];
|
|
44
55
|
readonly params?: Readonly<Record<string, CommandParameterValue>>;
|
|
45
56
|
readonly options?: Readonly<Record<string, CommandParameterValue>>;
|
|
46
57
|
readonly segments?: CommandContext['segments'];
|
|
47
58
|
readonly interaction?: CommandContext['interaction'];
|
|
59
|
+
/**
|
|
60
|
+
* Where the command lives: its `commands/.../index.ts` file (or directory), as a path or a
|
|
61
|
+
* `file:` URL such as `new URL('../commands/echo/[text]/index.ts', import.meta.url)`. When set,
|
|
62
|
+
* the definition first goes through the Runtime's convention-path check (`bindCommandSource`
|
|
63
|
+
* from `zhin.js/command`): a layout the Runtime would reject, e.g. `commands/term/[word]/[...rest]`,
|
|
64
|
+
* throws here too, and the directory parameter is bound as in the Runtime.
|
|
65
|
+
*/
|
|
66
|
+
readonly source?: string | URL;
|
|
48
67
|
}
|
|
49
68
|
|
|
50
69
|
/** Build the context a command receives from the fake plugin; usable for direct `execute()` calls. */
|
|
@@ -57,6 +76,8 @@ export function createCommandContext<TConfig, TInput extends CommandMessage = Fa
|
|
|
57
76
|
const sender = input.sender;
|
|
58
77
|
return {
|
|
59
78
|
...fake.capabilityContext(),
|
|
79
|
+
locale: options.locale ?? resolveLocale(input.locale),
|
|
80
|
+
formatCommand: options.formatCommand ?? (() => undefined),
|
|
60
81
|
args: options.args ?? [],
|
|
61
82
|
params: options.params ?? {},
|
|
62
83
|
options: options.options ?? {},
|
|
@@ -74,13 +95,27 @@ export function createCommandContext<TConfig, TInput extends CommandMessage = Fa
|
|
|
74
95
|
/**
|
|
75
96
|
* Execute a command definition against the fake. This calls `execute()` directly: it does NOT run
|
|
76
97
|
* route matching, parameter parsing, `permit`, or admission. Use `PluginTestKit` for those.
|
|
98
|
+
* Pass `source` to apply the Runtime's convention-path check first.
|
|
77
99
|
*/
|
|
78
100
|
export async function runCommand<TConfig, TResult, TInput extends CommandMessage = FakeMessage>(
|
|
79
101
|
fake: FakePlugin<TConfig>,
|
|
80
102
|
definition: CommandDefinition<TConfig, TResult, TInput, string | undefined>,
|
|
81
103
|
options?: RunCommandOptions<TInput>,
|
|
82
104
|
): Promise<TResult> {
|
|
83
|
-
|
|
105
|
+
const command = options?.source === undefined ? definition : await bindSource(definition, options.source);
|
|
106
|
+
return command.execute(createCommandContext(fake, options));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function bindSource<T extends CommandDefinition<never, unknown, never, string | undefined>>(
|
|
110
|
+
definition: T, source: string | URL,
|
|
111
|
+
): Promise<T> {
|
|
112
|
+
const path = source instanceof URL || source.startsWith('file:') ? fileURLToPath(source) : source;
|
|
113
|
+
// Loaded on demand, so an older zhin.js (unmet peer) only fails here, with an actionable message.
|
|
114
|
+
const command: Partial<typeof import('zhin.js/command')> = await import('zhin.js/command');
|
|
115
|
+
if (typeof command.bindCommandSource !== 'function') {
|
|
116
|
+
throw new Error('runCommand({ source }) needs a newer zhin.js whose zhin.js/command exports bindCommandSource; upgrade zhin.js');
|
|
117
|
+
}
|
|
118
|
+
return command.bindCommandSource(definition as never, path).definition as unknown as T;
|
|
84
119
|
}
|
|
85
120
|
|
|
86
121
|
export interface RunMiddlewareResult {
|
|
@@ -115,3 +150,116 @@ export async function runHandler<TConfig>(
|
|
|
115
150
|
const context: HandlerContext<TConfig> = fake.capabilityContext();
|
|
116
151
|
await definition.handle.call(context as HandlerContext, ...args);
|
|
117
152
|
}
|
|
153
|
+
|
|
154
|
+
export interface RunToolOptions {
|
|
155
|
+
readonly locale?: Locale;
|
|
156
|
+
/**
|
|
157
|
+
* Derive `origin` (`kind: 'im'`) and `principal` from an inbound message, so a tool sees the same
|
|
158
|
+
* conversation the command tests use. Explicit `origin` / `principal` win.
|
|
159
|
+
*/
|
|
160
|
+
readonly message?: CommandMessage;
|
|
161
|
+
/** Default: `{ kind: 'im', platform: 'test', endpoint: 'test', scope: 'group', sceneId: 'test-group' }`. */
|
|
162
|
+
readonly origin?: ToolInvocationOrigin;
|
|
163
|
+
readonly principal?: ToolExecutionContext['principal'];
|
|
164
|
+
/** Default: no permissions, attended, network disabled. */
|
|
165
|
+
readonly policy?: Partial<ToolInvocationPolicy>;
|
|
166
|
+
readonly question?: ToolQuestionPort;
|
|
167
|
+
/** Native client port; required when the tool declares `adapter`. */
|
|
168
|
+
readonly client?: OperationClientPort;
|
|
169
|
+
readonly traceId?: string;
|
|
170
|
+
readonly turnId?: string;
|
|
171
|
+
readonly sessionKey?: string;
|
|
172
|
+
readonly signal?: AbortSignal;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Map an inbound message to the Agent tool origin shape (`platform` / `endpoint` / `scope` / `sceneId`),
|
|
177
|
+
* with the same rules as the Agent's IM turn context (`clientAdapter` wins over the endpoint adapter).
|
|
178
|
+
*/
|
|
179
|
+
export function toolOriginFromMessage(message: CommandMessage): ToolInvocationOrigin {
|
|
180
|
+
const { conversation } = message;
|
|
181
|
+
return Object.freeze({
|
|
182
|
+
kind: 'im' as const,
|
|
183
|
+
platform: message.clientAdapter ?? conversation.endpoint.adapter,
|
|
184
|
+
endpoint: conversation.endpoint.id,
|
|
185
|
+
scope: conversation.kind,
|
|
186
|
+
sceneId: conversation.id,
|
|
187
|
+
...(message.id === undefined ? {} : { messageId: message.id }),
|
|
188
|
+
...(conversation.threadId === undefined ? {} : { threadId: conversation.threadId }),
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** Build the context an Agent tool's `execute()` receives, shaped like the real ToolIndex builds it. */
|
|
193
|
+
export function createToolContext<TConfig, TAdapter extends string | undefined = undefined>(
|
|
194
|
+
fake: FakePlugin<TConfig>,
|
|
195
|
+
options: RunToolOptions = {},
|
|
196
|
+
): ToolExecutionContext<TConfig, TAdapter> {
|
|
197
|
+
const message = options.message;
|
|
198
|
+
const sender = message?.sender;
|
|
199
|
+
const policy = options.policy ?? {};
|
|
200
|
+
const context = {
|
|
201
|
+
...fake.capabilityContext(),
|
|
202
|
+
locale: options.locale ?? resolveLocale(message?.locale),
|
|
203
|
+
signal: options.signal ?? fake.signal,
|
|
204
|
+
traceId: options.traceId ?? 'test-trace',
|
|
205
|
+
turnId: options.turnId ?? 'test-turn',
|
|
206
|
+
sessionKey: options.sessionKey ?? (message
|
|
207
|
+
? `${message.conversation.endpoint.adapter}:${message.conversation.endpoint.id}:${message.conversation.kind}:${message.conversation.id}`
|
|
208
|
+
: 'test-session'),
|
|
209
|
+
origin: Object.freeze({ ...(options.origin ?? (message ? toolOriginFromMessage(message) : {
|
|
210
|
+
kind: 'im', platform: 'test', endpoint: 'test', scope: 'group', sceneId: 'test-group',
|
|
211
|
+
})) }) as ToolInvocationOrigin,
|
|
212
|
+
principal: Object.freeze({ ...(options.principal ?? {
|
|
213
|
+
subjectId: sender?.id ?? 'test-user',
|
|
214
|
+
...(sender?.name === undefined ? {} : { displayName: sender.name }),
|
|
215
|
+
roles: sender?.roles ?? [],
|
|
216
|
+
}) }),
|
|
217
|
+
policy: Object.freeze({
|
|
218
|
+
permissions: Object.freeze([...(policy.permissions ?? [])]),
|
|
219
|
+
unattended: policy.unattended ?? false,
|
|
220
|
+
network: Object.freeze({ enabled: false, ...policy.network }),
|
|
221
|
+
...(policy.shell ? { shell: Object.freeze({ ...policy.shell }) } : {}),
|
|
222
|
+
...(policy.filesystem ? { filesystem: Object.freeze({ ...policy.filesystem }) } : {}),
|
|
223
|
+
}),
|
|
224
|
+
...(options.question ? { question: options.question } : {}),
|
|
225
|
+
} as ToolExecutionContext<TConfig, TAdapter>;
|
|
226
|
+
Object.defineProperty(context, '$client', { enumerable: true, get: () => options.client?.get() });
|
|
227
|
+
return Object.freeze(context);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Execute an Agent tool against the fake, the way the Runtime's tool index does: the input is parsed
|
|
232
|
+
* by an executable `inputSchema` (e.g. Zod; JSON Schema inputs pass through unchanged, as in the
|
|
233
|
+
* Runtime), an `adapter`-bound tool requires a matching `client`, then `execute()` runs.
|
|
234
|
+
* It does NOT run model discovery, approval, permission or policy enforcement; use an Agent
|
|
235
|
+
* integration test for those.
|
|
236
|
+
*
|
|
237
|
+
* `tool` is a definition (e.g. the default export of `tools/<name>/index.ts`) or the local name of a
|
|
238
|
+
* tool registered through `addTool()` during `runPluginSetup`.
|
|
239
|
+
*/
|
|
240
|
+
export async function runTool<TResult = unknown, TConfig = unknown, TInput = unknown>(
|
|
241
|
+
fake: FakePlugin<TConfig>,
|
|
242
|
+
tool: AgentToolDefinition<TInput, TResult, TConfig, string | undefined> | string,
|
|
243
|
+
input?: unknown,
|
|
244
|
+
options: RunToolOptions = {},
|
|
245
|
+
): Promise<TResult> {
|
|
246
|
+
const definition = typeof tool === 'string' ? registeredTool<TInput, TResult, TConfig>(fake, tool) : tool;
|
|
247
|
+
const name = typeof tool === 'string' ? tool : 'tool';
|
|
248
|
+
const parsed = parseToolInputSchema(definition.inputSchema, input ?? {});
|
|
249
|
+
if (!parsed.ok) throw new TypeError(`Invalid Agent Tool input for ${name}: ${parsed.error}`);
|
|
250
|
+
if (definition.adapter && options.client?.adapter !== definition.adapter) {
|
|
251
|
+
throw new Error(`Agent Tool ${name} requires adapter ${definition.adapter}`);
|
|
252
|
+
}
|
|
253
|
+
return await definition.execute(parsed.data, createToolContext<TConfig, string | undefined>(fake, options));
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function registeredTool<TInput, TResult, TConfig>(
|
|
257
|
+
fake: FakePlugin<TConfig>, localName: string,
|
|
258
|
+
): AgentToolDefinition<TInput, TResult, TConfig, string | undefined> {
|
|
259
|
+
const found = fake.features.find(feature => feature.kind === 'tool' && feature.localName === localName);
|
|
260
|
+
if (!found) {
|
|
261
|
+
const known = fake.features.filter(feature => feature.kind === 'tool').map(feature => feature.localName);
|
|
262
|
+
throw new Error(`No tool "${localName}" was registered through addTool()${known.length ? `; registered: ${known.join(', ')}` : ''}`);
|
|
263
|
+
}
|
|
264
|
+
return found.definition as AgentToolDefinition<TInput, TResult, TConfig, string | undefined>;
|
|
265
|
+
}
|