@openclaw/crabline 0.0.0

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.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +226 -0
  3. package/dist/src/bin/crabline.d.ts +2 -0
  4. package/dist/src/bin/crabline.js +7 -0
  5. package/dist/src/bin/crabline.js.map +1 -0
  6. package/dist/src/cli/program.d.ts +5 -0
  7. package/dist/src/cli/program.js +295 -0
  8. package/dist/src/cli/program.js.map +1 -0
  9. package/dist/src/config/load.d.ts +6 -0
  10. package/dist/src/config/load.js +41 -0
  11. package/dist/src/config/load.js.map +1 -0
  12. package/dist/src/config/schema.d.ts +1571 -0
  13. package/dist/src/config/schema.js +528 -0
  14. package/dist/src/config/schema.js.map +1 -0
  15. package/dist/src/core/errors.d.ts +12 -0
  16. package/dist/src/core/errors.js +28 -0
  17. package/dist/src/core/errors.js.map +1 -0
  18. package/dist/src/core/exit-codes.d.ts +13 -0
  19. package/dist/src/core/exit-codes.js +13 -0
  20. package/dist/src/core/exit-codes.js.map +1 -0
  21. package/dist/src/core/matcher.d.ts +2 -0
  22. package/dist/src/core/matcher.js +30 -0
  23. package/dist/src/core/matcher.js.map +1 -0
  24. package/dist/src/core/message-template.d.ts +2 -0
  25. package/dist/src/core/message-template.js +20 -0
  26. package/dist/src/core/message-template.js.map +1 -0
  27. package/dist/src/core/nonces.d.ts +2 -0
  28. package/dist/src/core/nonces.js +11 -0
  29. package/dist/src/core/nonces.js.map +1 -0
  30. package/dist/src/core/reporters.d.ts +3 -0
  31. package/dist/src/core/reporters.js +23 -0
  32. package/dist/src/core/reporters.js.map +1 -0
  33. package/dist/src/core/run.d.ts +30 -0
  34. package/dist/src/core/run.js +240 -0
  35. package/dist/src/core/run.js.map +1 -0
  36. package/dist/src/fake-servers/index.d.ts +10 -0
  37. package/dist/src/fake-servers/index.js +12 -0
  38. package/dist/src/fake-servers/index.js.map +1 -0
  39. package/dist/src/fake-servers/telegram.d.ts +29 -0
  40. package/dist/src/fake-servers/telegram.js +346 -0
  41. package/dist/src/fake-servers/telegram.js.map +1 -0
  42. package/dist/src/index.d.ts +15 -0
  43. package/dist/src/index.js +9 -0
  44. package/dist/src/index.js.map +1 -0
  45. package/dist/src/openclaw.d.ts +102 -0
  46. package/dist/src/openclaw.js +289 -0
  47. package/dist/src/openclaw.js.map +1 -0
  48. package/dist/src/providers/builtin/discord.d.ts +15 -0
  49. package/dist/src/providers/builtin/discord.js +92 -0
  50. package/dist/src/providers/builtin/discord.js.map +1 -0
  51. package/dist/src/providers/builtin/feishu.d.ts +10 -0
  52. package/dist/src/providers/builtin/feishu.js +95 -0
  53. package/dist/src/providers/builtin/feishu.js.map +1 -0
  54. package/dist/src/providers/builtin/googlechat.d.ts +11 -0
  55. package/dist/src/providers/builtin/googlechat.js +83 -0
  56. package/dist/src/providers/builtin/googlechat.js.map +1 -0
  57. package/dist/src/providers/builtin/imessage.d.ts +11 -0
  58. package/dist/src/providers/builtin/imessage.js +67 -0
  59. package/dist/src/providers/builtin/imessage.js.map +1 -0
  60. package/dist/src/providers/builtin/loopback.d.ts +63 -0
  61. package/dist/src/providers/builtin/loopback.js +174 -0
  62. package/dist/src/providers/builtin/loopback.js.map +1 -0
  63. package/dist/src/providers/builtin/matrix.d.ts +21 -0
  64. package/dist/src/providers/builtin/matrix.js +84 -0
  65. package/dist/src/providers/builtin/matrix.js.map +1 -0
  66. package/dist/src/providers/builtin/mattermost.d.ts +11 -0
  67. package/dist/src/providers/builtin/mattermost.js +67 -0
  68. package/dist/src/providers/builtin/mattermost.js.map +1 -0
  69. package/dist/src/providers/builtin/msteams.d.ts +13 -0
  70. package/dist/src/providers/builtin/msteams.js +72 -0
  71. package/dist/src/providers/builtin/msteams.js.map +1 -0
  72. package/dist/src/providers/builtin/native-local-mock.d.ts +48 -0
  73. package/dist/src/providers/builtin/native-local-mock.js +119 -0
  74. package/dist/src/providers/builtin/native-local-mock.js.map +1 -0
  75. package/dist/src/providers/builtin/script.d.ts +39 -0
  76. package/dist/src/providers/builtin/script.js +206 -0
  77. package/dist/src/providers/builtin/script.js.map +1 -0
  78. package/dist/src/providers/builtin/slack.d.ts +6 -0
  79. package/dist/src/providers/builtin/slack.js +106 -0
  80. package/dist/src/providers/builtin/slack.js.map +1 -0
  81. package/dist/src/providers/builtin/telegram.d.ts +21 -0
  82. package/dist/src/providers/builtin/telegram.js +123 -0
  83. package/dist/src/providers/builtin/telegram.js.map +1 -0
  84. package/dist/src/providers/builtin/whatsapp.d.ts +19 -0
  85. package/dist/src/providers/builtin/whatsapp.js +90 -0
  86. package/dist/src/providers/builtin/whatsapp.js.map +1 -0
  87. package/dist/src/providers/builtin/zalo.d.ts +17 -0
  88. package/dist/src/providers/builtin/zalo.js +70 -0
  89. package/dist/src/providers/builtin/zalo.js.map +1 -0
  90. package/dist/src/providers/catalog.d.ts +69 -0
  91. package/dist/src/providers/catalog.js +95 -0
  92. package/dist/src/providers/catalog.js.map +1 -0
  93. package/dist/src/providers/local-mock.d.ts +41 -0
  94. package/dist/src/providers/local-mock.js +243 -0
  95. package/dist/src/providers/local-mock.js.map +1 -0
  96. package/dist/src/providers/recorder.d.ts +19 -0
  97. package/dist/src/providers/recorder.js +160 -0
  98. package/dist/src/providers/recorder.js.map +1 -0
  99. package/dist/src/providers/registry.d.ts +8 -0
  100. package/dist/src/providers/registry.js +171 -0
  101. package/dist/src/providers/registry.js.map +1 -0
  102. package/dist/src/providers/types.d.ts +94 -0
  103. package/dist/src/providers/types.js +2 -0
  104. package/dist/src/providers/types.js.map +1 -0
  105. package/dist/src/providers/webhook-server.d.ts +12 -0
  106. package/dist/src/providers/webhook-server.js +118 -0
  107. package/dist/src/providers/webhook-server.js.map +1 -0
  108. package/docs/channel-setup.md +181 -0
  109. package/fixtures/examples/crabline.example.yaml +195 -0
  110. package/fixtures/examples/openclaw-bridge.yaml +125 -0
  111. package/package.json +64 -0
@@ -0,0 +1,30 @@
1
+ import { extractNonce } from "./nonces.js";
2
+ export function matchesInbound(envelope, config, nonce) {
3
+ if (config.author !== "any" && envelope.author !== config.author) {
4
+ return false;
5
+ }
6
+ const text = envelope.text ?? "";
7
+ const extractedNonce = extractNonce(text);
8
+ if (config.nonce !== "ignore") {
9
+ if (!extractedNonce) {
10
+ return false;
11
+ }
12
+ if (config.nonce === "exact" && extractedNonce !== nonce) {
13
+ return false;
14
+ }
15
+ if (config.nonce === "contains" && !text.includes(nonce)) {
16
+ return false;
17
+ }
18
+ }
19
+ if (!config.pattern) {
20
+ return true;
21
+ }
22
+ if (config.strategy === "exact") {
23
+ return text === config.pattern;
24
+ }
25
+ if (config.strategy === "regex") {
26
+ return new RegExp(config.pattern, "u").test(text);
27
+ }
28
+ return text.includes(config.pattern);
29
+ }
30
+ //# sourceMappingURL=matcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matcher.js","sourceRoot":"","sources":["../../../src/core/matcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,UAAU,cAAc,CAC5B,QAAyB,EACzB,MAA0B,EAC1B,KAAa;IAEb,IAAI,MAAM,CAAC,MAAM,KAAK,KAAK,IAAI,QAAQ,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;QACjE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC;IACjC,MAAM,cAAc,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAE1C,IAAI,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,MAAM,CAAC,KAAK,KAAK,OAAO,IAAI,cAAc,KAAK,KAAK,EAAE,CAAC;YACzD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,MAAM,CAAC,KAAK,KAAK,UAAU,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACzD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAChC,OAAO,IAAI,KAAK,MAAM,CAAC,OAAO,CAAC;IACjC,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAChC,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC;IAED,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { FixtureDefinition } from "../config/schema.js";
2
+ export declare function createOutboundText(fixture: FixtureDefinition, nonce: string): string;
@@ -0,0 +1,20 @@
1
+ function modePrefix(mode) {
2
+ switch (mode) {
3
+ case "send":
4
+ return "send";
5
+ case "roundtrip":
6
+ return "roundtrip";
7
+ case "agent":
8
+ return "agent";
9
+ case "probe":
10
+ return "probe";
11
+ }
12
+ }
13
+ export function createOutboundText(fixture, nonce) {
14
+ const prefix = `crabline ${modePrefix(fixture.mode)} ${fixture.id}`;
15
+ if (fixture.mode === "agent") {
16
+ return `${prefix} nonce=${nonce}. Reply with ACK ${nonce}.`;
17
+ }
18
+ return `${prefix} nonce=${nonce}`;
19
+ }
20
+ //# sourceMappingURL=message-template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-template.js","sourceRoot":"","sources":["../../../src/core/message-template.ts"],"names":[],"mappings":"AAEA,SAAS,UAAU,CAAC,IAAiB;IACnC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,MAAM;YACT,OAAO,MAAM,CAAC;QAChB,KAAK,WAAW;YACd,OAAO,WAAW,CAAC;QACrB,KAAK,OAAO;YACV,OAAO,OAAO,CAAC;QACjB,KAAK,OAAO;YACV,OAAO,OAAO,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAA0B,EAAE,KAAa;IAC1E,MAAM,MAAM,GAAG,YAAY,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC;IACpE,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC7B,OAAO,GAAG,MAAM,UAAU,KAAK,oBAAoB,KAAK,GAAG,CAAC;IAC9D,CAAC;IAED,OAAO,GAAG,MAAM,UAAU,KAAK,EAAE,CAAC;AACpC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function createNonce(fixtureId: string): string;
2
+ export declare function extractNonce(text: string): string | null;
@@ -0,0 +1,11 @@
1
+ import { randomBytes } from "node:crypto";
2
+ export function createNonce(fixtureId) {
3
+ const timestamp = Date.now().toString(36);
4
+ const entropy = randomBytes(4).toString("hex");
5
+ return `mp-${fixtureId}-${timestamp}-${entropy}`;
6
+ }
7
+ export function extractNonce(text) {
8
+ const match = text.match(/\bmp-[a-z0-9-]+-[a-z0-9]+-[a-f0-9]{8}\b/i);
9
+ return match?.[0] ?? null;
10
+ }
11
+ //# sourceMappingURL=nonces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nonces.js","sourceRoot":"","sources":["../../../src/core/nonces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,UAAU,WAAW,CAAC,SAAiB;IAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC/C,OAAO,MAAM,SAAS,IAAI,SAAS,IAAI,OAAO,EAAE,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;IACrE,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { CommandRunResult, SuiteRunResult } from "./run.js";
2
+ export declare function formatRunResultText(result: CommandRunResult | SuiteRunResult): string;
3
+ export declare function formatJson(result: unknown): string;
@@ -0,0 +1,23 @@
1
+ import pc from "picocolors";
2
+ export function formatRunResultText(result) {
3
+ if ("results" in result) {
4
+ const lines = [
5
+ `${pc.bold("suite")} ${result.totalPassed}/${result.results.length} passed`,
6
+ ...result.results.map((entry) => formatCaseLine(entry)),
7
+ ];
8
+ return lines.join("\n");
9
+ }
10
+ return formatSingleResult(result);
11
+ }
12
+ export function formatJson(result) {
13
+ return JSON.stringify(result === undefined ? null : result, null, 2);
14
+ }
15
+ function formatSingleResult(result) {
16
+ const lines = [formatCaseLine(result), ...result.diagnostics.map((entry) => ` - ${entry}`)];
17
+ return lines.join("\n");
18
+ }
19
+ function formatCaseLine(result) {
20
+ const colorize = result.ok ? pc.green : result.failureKind === "timeout" ? pc.yellow : pc.red;
21
+ return `${colorize(result.ok ? "PASS" : "FAIL")} ${result.fixtureId} ${result.mode} ${result.providerId}`;
22
+ }
23
+ //# sourceMappingURL=reporters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporters.js","sourceRoot":"","sources":["../../../src/core/reporters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAG5B,MAAM,UAAU,mBAAmB,CAAC,MAAyC;IAC3E,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG;YACZ,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,SAAS;YAC3E,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;SACxD,CAAC;QACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAe;IACxC,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACvE,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAwB;IAClD,MAAM,KAAK,GAAG,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC;IAC7F,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,cAAc,CAAC,MAAwB;IAC9C,MAAM,QAAQ,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC;IAC9F,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;AAC5G,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { type FailureKind } from "./errors.js";
2
+ import type { ManifestDefinition } from "../config/schema.js";
3
+ import type { Registry } from "../providers/registry.js";
4
+ export type CommandRunResult = {
5
+ diagnostics: string[];
6
+ failureKind?: FailureKind | undefined;
7
+ fixtureId: string;
8
+ mode: string;
9
+ nonce?: string | undefined;
10
+ ok: boolean;
11
+ providerId: string;
12
+ };
13
+ export type SuiteRunResult = {
14
+ results: CommandRunResult[];
15
+ totalPassed: number;
16
+ };
17
+ export declare function runFixtureCommand(params: {
18
+ fixtureId: string;
19
+ manifest: ManifestDefinition;
20
+ manifestPath: string;
21
+ modeOverride?: "agent" | "probe" | "roundtrip" | "send";
22
+ registry: Registry;
23
+ }): Promise<CommandRunResult>;
24
+ export declare function runSuite(params: {
25
+ fixtureIds: string[];
26
+ manifest: ManifestDefinition;
27
+ manifestPath: string;
28
+ registry: Registry;
29
+ }): Promise<SuiteRunResult>;
30
+ export declare function computeExitCode(result: CommandRunResult | SuiteRunResult): number;
@@ -0,0 +1,240 @@
1
+ import { matchesInbound } from "./matcher.js";
2
+ import { createOutboundText } from "./message-template.js";
3
+ import { createNonce } from "./nonces.js";
4
+ import { CrablineError, ensureErrorMessage } from "./errors.js";
5
+ function sleep(ms) {
6
+ return new Promise((resolve) => setTimeout(resolve, ms));
7
+ }
8
+ export async function runFixtureCommand(params) {
9
+ const fixture = params.manifest.fixtures.find((entry) => entry.id === params.fixtureId);
10
+ if (!fixture) {
11
+ throw new CrablineError(`Unknown fixture: ${params.fixtureId}`, { kind: "config" });
12
+ }
13
+ const provider = params.registry.resolve(fixture.provider, fixture.id);
14
+ const mode = params.modeOverride ?? fixture.mode;
15
+ const diagnostics = [];
16
+ if (!provider.supports.includes(mode)) {
17
+ return {
18
+ diagnostics: [`provider ${fixture.provider} does not support mode ${mode}`],
19
+ failureKind: "config",
20
+ fixtureId: fixture.id,
21
+ mode,
22
+ ok: false,
23
+ providerId: fixture.provider,
24
+ };
25
+ }
26
+ for (const envName of [
27
+ ...fixture.env,
28
+ ...(params.manifest.providers[fixture.provider]?.env ?? []),
29
+ ]) {
30
+ if (!process.env[envName]) {
31
+ return {
32
+ diagnostics: [`missing env: ${envName}`],
33
+ failureKind: "config",
34
+ fixtureId: fixture.id,
35
+ mode,
36
+ ok: false,
37
+ providerId: fixture.provider,
38
+ };
39
+ }
40
+ }
41
+ const contextBase = {
42
+ config: params.manifest.providers[fixture.provider],
43
+ fixture,
44
+ manifestPath: params.manifestPath,
45
+ providerId: fixture.provider,
46
+ userName: params.manifest.userName,
47
+ };
48
+ let result;
49
+ try {
50
+ if (mode === "probe") {
51
+ try {
52
+ const probeResult = await provider.probe(contextBase);
53
+ return (result = {
54
+ diagnostics: probeResult.details,
55
+ failureKind: probeResult.healthy ? undefined : "connectivity",
56
+ fixtureId: fixture.id,
57
+ mode,
58
+ ok: probeResult.healthy,
59
+ providerId: fixture.provider,
60
+ });
61
+ }
62
+ catch (error) {
63
+ return (result = toFailure(fixture.id, fixture.provider, mode, error));
64
+ }
65
+ }
66
+ let attempts = 0;
67
+ const maxAttempts = fixture.retries + 1;
68
+ let lastFailure = null;
69
+ while (attempts < maxAttempts) {
70
+ attempts += 1;
71
+ const nonce = createNonce(fixture.id);
72
+ try {
73
+ const outboundText = createOutboundText({ ...fixture, mode }, nonce);
74
+ const since = new Date().toISOString();
75
+ const accepted = await provider.send({
76
+ ...contextBase,
77
+ mode,
78
+ nonce,
79
+ text: outboundText,
80
+ });
81
+ diagnostics.push(`accepted message ${accepted.messageId}`);
82
+ if (mode === "send") {
83
+ return (result = {
84
+ diagnostics,
85
+ fixtureId: fixture.id,
86
+ mode,
87
+ nonce,
88
+ ok: true,
89
+ providerId: fixture.provider,
90
+ });
91
+ }
92
+ const inbound = await provider.waitForInbound({
93
+ ...contextBase,
94
+ nonce,
95
+ since,
96
+ threadId: accepted.threadId,
97
+ timeoutMs: fixture.timeoutMs,
98
+ });
99
+ if (!inbound) {
100
+ lastFailure = {
101
+ diagnostics: [
102
+ ...diagnostics,
103
+ `timed out waiting for inbound after ${fixture.timeoutMs}ms`,
104
+ ],
105
+ failureKind: "timeout",
106
+ fixtureId: fixture.id,
107
+ mode,
108
+ nonce,
109
+ ok: false,
110
+ providerId: fixture.provider,
111
+ };
112
+ await sleep(50);
113
+ continue;
114
+ }
115
+ if (!matchesInbound(inbound, fixture.inboundMatch, nonce)) {
116
+ lastFailure = {
117
+ diagnostics: [...diagnostics, `received non-matching inbound message ${inbound.id}`],
118
+ failureKind: "assertion",
119
+ fixtureId: fixture.id,
120
+ mode,
121
+ nonce,
122
+ ok: false,
123
+ providerId: fixture.provider,
124
+ };
125
+ await sleep(50);
126
+ continue;
127
+ }
128
+ return (result = {
129
+ diagnostics: [...diagnostics, `matched inbound ${inbound.id}`],
130
+ fixtureId: fixture.id,
131
+ mode,
132
+ nonce,
133
+ ok: true,
134
+ providerId: fixture.provider,
135
+ });
136
+ }
137
+ catch (error) {
138
+ lastFailure = toFailure(fixture.id, fixture.provider, mode, error, nonce);
139
+ }
140
+ }
141
+ return (result = lastFailure ?? {
142
+ diagnostics: ["unknown failure"],
143
+ failureKind: "assertion",
144
+ fixtureId: fixture.id,
145
+ mode,
146
+ ok: false,
147
+ providerId: fixture.provider,
148
+ });
149
+ }
150
+ finally {
151
+ try {
152
+ await provider.cleanup?.();
153
+ }
154
+ catch (error) {
155
+ const diagnostic = `cleanup failed: ${ensureErrorMessage(error)}`;
156
+ if (result) {
157
+ result.diagnostics.push(diagnostic);
158
+ }
159
+ else {
160
+ result = {
161
+ diagnostics: [...diagnostics, diagnostic],
162
+ failureKind: "assertion",
163
+ fixtureId: fixture.id,
164
+ mode,
165
+ ok: false,
166
+ providerId: fixture.provider,
167
+ };
168
+ }
169
+ }
170
+ }
171
+ // The finally block can synthesize a result when provider cleanup fails.
172
+ // oxlint-disable-next-line no-unreachable
173
+ return result;
174
+ }
175
+ export async function runSuite(params) {
176
+ const results = [];
177
+ for (const fixtureId of params.fixtureIds) {
178
+ results.push(await runFixtureCommand({
179
+ fixtureId,
180
+ manifest: params.manifest,
181
+ manifestPath: params.manifestPath,
182
+ registry: params.registry,
183
+ }));
184
+ }
185
+ return {
186
+ results,
187
+ totalPassed: results.filter((entry) => entry.ok).length,
188
+ };
189
+ }
190
+ export function computeExitCode(result) {
191
+ if ("results" in result) {
192
+ const failure = result.results.find((entry) => !entry.ok);
193
+ return failure ? computeExitCode(failure) : 0;
194
+ }
195
+ if (result.ok) {
196
+ return 0;
197
+ }
198
+ switch (result.failureKind) {
199
+ case "auth":
200
+ return 11;
201
+ case "config":
202
+ return 10;
203
+ case "connectivity":
204
+ return 12;
205
+ case "outbound":
206
+ return 13;
207
+ case "inbound":
208
+ return 14;
209
+ case "timeout":
210
+ return 15;
211
+ case "assertion":
212
+ return 16;
213
+ default:
214
+ return 1;
215
+ }
216
+ }
217
+ function toFailure(fixtureId, providerId, mode, error, nonce) {
218
+ const diagnostics = [ensureErrorMessage(error)];
219
+ if (error instanceof CrablineError) {
220
+ return {
221
+ diagnostics,
222
+ failureKind: error.kind,
223
+ fixtureId,
224
+ mode,
225
+ nonce,
226
+ ok: false,
227
+ providerId,
228
+ };
229
+ }
230
+ return {
231
+ diagnostics,
232
+ failureKind: "assertion",
233
+ fixtureId,
234
+ mode,
235
+ nonce,
236
+ ok: false,
237
+ providerId,
238
+ };
239
+ }
240
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/core/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { type StartedTelegramFakeServer, type StartTelegramFakeServerParams, type TelegramFakeServerManifest } from "./telegram.js";
2
+ export declare const CRABLINE_FAKE_PROVIDER_CHANNELS: readonly ["telegram"];
3
+ export type CrablineFakeProviderChannel = (typeof CRABLINE_FAKE_PROVIDER_CHANNELS)[number];
4
+ export type CrablineFakeProviderManifest = TelegramFakeServerManifest;
5
+ export type StartedCrablineFakeProviderServer = StartedTelegramFakeServer;
6
+ export type StartCrablineFakeProviderServerParams = StartTelegramFakeServerParams & {
7
+ channel: CrablineFakeProviderChannel;
8
+ };
9
+ export declare function isCrablineFakeProviderChannel(value: string): value is CrablineFakeProviderChannel;
10
+ export declare function startCrablineFakeProviderServer(params: StartCrablineFakeProviderServerParams): Promise<StartedCrablineFakeProviderServer>;
@@ -0,0 +1,12 @@
1
+ import { startTelegramFakeServer, } from "./telegram.js";
2
+ export const CRABLINE_FAKE_PROVIDER_CHANNELS = Object.freeze(["telegram"]);
3
+ export function isCrablineFakeProviderChannel(value) {
4
+ return CRABLINE_FAKE_PROVIDER_CHANNELS.includes(value);
5
+ }
6
+ export async function startCrablineFakeProviderServer(params) {
7
+ switch (params.channel) {
8
+ case "telegram":
9
+ return await startTelegramFakeServer(params);
10
+ }
11
+ }
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/fake-servers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,GAIxB,MAAM,eAAe,CAAC;AAEvB,MAAM,CAAC,MAAM,+BAA+B,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,CAAU,CAAC,CAAC;AAYpF,MAAM,UAAU,6BAA6B,CAAC,KAAa;IACzD,OAAO,+BAA+B,CAAC,QAAQ,CAAC,KAAoC,CAAC,CAAC;AACxF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACnD,MAA6C;IAE7C,QAAQ,MAAM,CAAC,OAAO,EAAE,CAAC;QACvB,KAAK,UAAU;YACb,OAAO,MAAM,uBAAuB,CAAC,MAAM,CAAC,CAAC;IACjD,CAAC;AACH,CAAC"}
@@ -0,0 +1,29 @@
1
+ export type TelegramFakeServerManifest = {
2
+ adminToken: string;
3
+ baseUrl: string;
4
+ botToken: string;
5
+ endpoints: {
6
+ adminInboundUrl: string;
7
+ apiRoot: string;
8
+ };
9
+ env: {
10
+ TELEGRAM_BOT_TOKEN: string;
11
+ };
12
+ provider: "telegram";
13
+ recorderPath: string;
14
+ version: 1;
15
+ };
16
+ export type StartedTelegramFakeServer = {
17
+ close(): Promise<void>;
18
+ manifest: TelegramFakeServerManifest;
19
+ };
20
+ export type StartTelegramFakeServerParams = {
21
+ adminToken?: string | undefined;
22
+ botId?: number | undefined;
23
+ botToken?: string | undefined;
24
+ botUsername?: string | undefined;
25
+ host?: string | undefined;
26
+ port?: number | undefined;
27
+ recorderPath?: string | undefined;
28
+ };
29
+ export declare function startTelegramFakeServer(params?: StartTelegramFakeServerParams): Promise<StartedTelegramFakeServer>;