@useorgx/openclaw-plugin 0.4.8 → 0.4.9

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 (125) hide show
  1. package/dashboard/dist/assets/B5NEElEI.css +1 -0
  2. package/dashboard/dist/assets/BhapSNAs.js +215 -0
  3. package/dashboard/dist/assets/{BNeJ0kpF.js → iFdvE7lx.js} +1 -1
  4. package/dashboard/dist/assets/{CUV9IHHi.js → jRJsmpYM.js} +1 -1
  5. package/dashboard/dist/index.html +2 -2
  6. package/dist/activity-store.js +4 -18
  7. package/dist/agent-context-store.js +5 -25
  8. package/dist/agent-run-store.js +5 -25
  9. package/dist/agent-suite.js +1 -8
  10. package/dist/auth/flows.d.ts +47 -0
  11. package/dist/auth/flows.js +169 -0
  12. package/dist/auth-store.js +6 -26
  13. package/dist/byok-store.js +5 -19
  14. package/dist/cli/orgx.d.ts +66 -0
  15. package/dist/cli/orgx.js +91 -0
  16. package/dist/config/refresh.d.ts +32 -0
  17. package/dist/config/refresh.js +55 -0
  18. package/dist/config/resolution.d.ts +37 -0
  19. package/dist/config/resolution.js +178 -0
  20. package/dist/contracts/shared-types.d.ts +147 -0
  21. package/dist/contracts/shared-types.js +3 -0
  22. package/dist/contracts/types.d.ts +1 -134
  23. package/dist/contracts/types.js +5 -0
  24. package/dist/entities/auto-assignment.d.ts +36 -0
  25. package/dist/entities/auto-assignment.js +115 -0
  26. package/dist/entity-comment-store.js +5 -25
  27. package/dist/hash-utils.d.ts +2 -0
  28. package/dist/hash-utils.js +12 -0
  29. package/dist/http/helpers/activity-headline.d.ts +10 -0
  30. package/dist/http/helpers/activity-headline.js +192 -0
  31. package/dist/http/helpers/artifact-fallback.d.ts +13 -0
  32. package/dist/http/helpers/artifact-fallback.js +148 -0
  33. package/dist/http/helpers/auto-continue-engine.d.ts +298 -0
  34. package/dist/http/helpers/auto-continue-engine.js +1218 -0
  35. package/dist/http/helpers/autopilot-operations.d.ts +157 -0
  36. package/dist/http/helpers/autopilot-operations.js +403 -0
  37. package/dist/http/helpers/autopilot-runtime.d.ts +42 -0
  38. package/dist/http/helpers/autopilot-runtime.js +319 -0
  39. package/dist/http/helpers/autopilot-slice-utils.d.ts +38 -0
  40. package/dist/http/helpers/autopilot-slice-utils.js +476 -0
  41. package/dist/http/helpers/decision-mapper.d.ts +12 -0
  42. package/dist/http/helpers/decision-mapper.js +44 -0
  43. package/dist/http/helpers/dispatch-lifecycle.d.ts +102 -0
  44. package/dist/http/helpers/dispatch-lifecycle.js +604 -0
  45. package/dist/http/helpers/hash-utils.d.ts +1 -0
  46. package/dist/http/helpers/hash-utils.js +1 -0
  47. package/dist/http/helpers/kickoff-context.d.ts +12 -0
  48. package/dist/http/helpers/kickoff-context.js +154 -0
  49. package/dist/http/helpers/mission-control.d.ts +94 -0
  50. package/dist/http/helpers/mission-control.js +894 -0
  51. package/dist/http/helpers/openclaw-cli.d.ts +37 -0
  52. package/dist/http/helpers/openclaw-cli.js +283 -0
  53. package/dist/http/helpers/runtime-sse.d.ts +20 -0
  54. package/dist/http/helpers/runtime-sse.js +110 -0
  55. package/dist/http/helpers/value-utils.d.ts +6 -0
  56. package/dist/http/helpers/value-utils.js +67 -0
  57. package/dist/http/index.d.ts +88 -0
  58. package/dist/http/index.js +2353 -0
  59. package/dist/http/router.d.ts +23 -0
  60. package/dist/http/router.js +23 -0
  61. package/dist/http/routes/agent-control.d.ts +79 -0
  62. package/dist/http/routes/agent-control.js +684 -0
  63. package/dist/http/routes/agent-suite.d.ts +29 -0
  64. package/dist/http/routes/agent-suite.js +198 -0
  65. package/dist/http/routes/agents-catalog.d.ts +40 -0
  66. package/dist/http/routes/agents-catalog.js +83 -0
  67. package/dist/http/routes/billing.d.ts +23 -0
  68. package/dist/http/routes/billing.js +55 -0
  69. package/dist/http/routes/debug.d.ts +14 -0
  70. package/dist/http/routes/debug.js +21 -0
  71. package/dist/http/routes/decision-actions.d.ts +13 -0
  72. package/dist/http/routes/decision-actions.js +66 -0
  73. package/dist/http/routes/delegation.d.ts +19 -0
  74. package/dist/http/routes/delegation.js +32 -0
  75. package/dist/http/routes/entities.d.ts +47 -0
  76. package/dist/http/routes/entities.js +152 -0
  77. package/dist/http/routes/entity-dynamic.d.ts +25 -0
  78. package/dist/http/routes/entity-dynamic.js +191 -0
  79. package/dist/http/routes/health.d.ts +22 -0
  80. package/dist/http/routes/health.js +49 -0
  81. package/dist/http/routes/live-legacy.d.ts +110 -0
  82. package/dist/http/routes/live-legacy.js +598 -0
  83. package/dist/http/routes/live-misc.d.ts +69 -0
  84. package/dist/http/routes/live-misc.js +206 -0
  85. package/dist/http/routes/live-snapshot.d.ts +90 -0
  86. package/dist/http/routes/live-snapshot.js +297 -0
  87. package/dist/http/routes/mission-control-actions.d.ts +83 -0
  88. package/dist/http/routes/mission-control-actions.js +541 -0
  89. package/dist/http/routes/mission-control-read.d.ts +28 -0
  90. package/dist/http/routes/mission-control-read.js +67 -0
  91. package/dist/http/routes/onboarding.d.ts +34 -0
  92. package/dist/http/routes/onboarding.js +101 -0
  93. package/dist/http/routes/run-control.d.ts +24 -0
  94. package/dist/http/routes/run-control.js +86 -0
  95. package/dist/http/routes/runtime-hooks.d.ts +69 -0
  96. package/dist/http/routes/runtime-hooks.js +437 -0
  97. package/dist/http/routes/settings-byok.d.ts +23 -0
  98. package/dist/http/routes/settings-byok.js +163 -0
  99. package/dist/http/routes/summary.d.ts +18 -0
  100. package/dist/http/routes/summary.js +42 -0
  101. package/dist/http/routes/work-artifacts.d.ts +9 -0
  102. package/dist/http/routes/work-artifacts.js +36 -0
  103. package/dist/http/shared-state.d.ts +16 -0
  104. package/dist/http/shared-state.js +1 -0
  105. package/dist/http-handler.d.ts +1 -88
  106. package/dist/http-handler.js +1 -10605
  107. package/dist/index.js +108 -2243
  108. package/dist/json-utils.d.ts +1 -0
  109. package/dist/json-utils.js +8 -0
  110. package/dist/next-up-queue-store.js +4 -18
  111. package/dist/runtime-instance-store.js +5 -31
  112. package/dist/services/background.d.ts +23 -0
  113. package/dist/services/background.js +23 -0
  114. package/dist/services/instrumentation.d.ts +29 -0
  115. package/dist/services/instrumentation.js +136 -0
  116. package/dist/snapshot-store.js +5 -25
  117. package/dist/stores/json-store.d.ts +11 -0
  118. package/dist/stores/json-store.js +42 -0
  119. package/dist/sync/outbox-replay.d.ts +55 -0
  120. package/dist/sync/outbox-replay.js +514 -0
  121. package/dist/tools/core-tools.d.ts +76 -0
  122. package/dist/tools/core-tools.js +1005 -0
  123. package/package.json +1 -1
  124. package/dashboard/dist/assets/BzkiMPmM.js +0 -215
  125. package/dashboard/dist/assets/Ie7d9Iq2.css +0 -1
@@ -0,0 +1 @@
1
+ export declare function parseJsonSafe<T>(value: string): T | null;
@@ -0,0 +1,8 @@
1
+ export function parseJsonSafe(value) {
2
+ try {
3
+ return JSON.parse(value);
4
+ }
5
+ catch {
6
+ return null;
7
+ }
8
+ }
@@ -1,6 +1,7 @@
1
- import { chmodSync, existsSync, mkdirSync, readFileSync, } from "node:fs";
1
+ import { existsSync, readFileSync, } from "node:fs";
2
2
  import { getOrgxPluginConfigDir, getOrgxPluginConfigPath } from "./paths.js";
3
3
  import { backupCorruptFileSync, writeJsonFileAtomicSync } from "./fs-utils.js";
4
+ import { ensureStoreDirSync, parseJsonSafe, } from "./stores/json-store.js";
4
5
  const MAX_PINS = 240;
5
6
  function storeDir() {
6
7
  return getOrgxPluginConfigDir();
@@ -9,22 +10,7 @@ function storeFile() {
9
10
  return getOrgxPluginConfigPath("next-up-queue.json");
10
11
  }
11
12
  function ensureStoreDir() {
12
- const dir = storeDir();
13
- mkdirSync(dir, { recursive: true, mode: 0o700 });
14
- try {
15
- chmodSync(dir, 0o700);
16
- }
17
- catch {
18
- // best effort
19
- }
20
- }
21
- function parseJson(value) {
22
- try {
23
- return JSON.parse(value);
24
- }
25
- catch {
26
- return null;
27
- }
13
+ ensureStoreDirSync(storeDir());
28
14
  }
29
15
  function normalizeNullableString(value) {
30
16
  if (typeof value !== "string")
@@ -49,7 +35,7 @@ export function readNextUpQueuePins() {
49
35
  return { version: 1, updatedAt: new Date().toISOString(), pins: [] };
50
36
  }
51
37
  const raw = readFileSync(file, "utf8");
52
- const parsed = parseJson(raw);
38
+ const parsed = parseJsonSafe(raw);
53
39
  if (!parsed || typeof parsed !== "object") {
54
40
  backupCorruptFileSync(file);
55
41
  return { version: 1, updatedAt: new Date().toISOString(), pins: [] };
@@ -1,7 +1,8 @@
1
- import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync, } from "node:fs";
1
+ import { existsSync, readFileSync, writeFileSync, } from "node:fs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { getOrgxPluginConfigDir, getOrgxPluginConfigPath } from "./paths.js";
4
4
  import { backupCorruptFileSync, writeJsonFileAtomicSync } from "./fs-utils.js";
5
+ import { clearStoreFileSync, ensureStoreDirSync, parseJsonSafe, } from "./stores/json-store.js";
5
6
  const MAX_INSTANCES = 600;
6
7
  export const DEFAULT_RUNTIME_HEARTBEAT_TIMEOUT_MS = 90_000;
7
8
  function runtimeDir() {
@@ -14,33 +15,12 @@ function hookTokenFile() {
14
15
  return getOrgxPluginConfigPath("runtime-hook-token.txt");
15
16
  }
16
17
  function ensureRuntimeDir() {
17
- const dir = runtimeDir();
18
- mkdirSync(dir, { recursive: true, mode: 0o700 });
19
- try {
20
- chmodSync(dir, 0o700);
21
- }
22
- catch {
23
- // best effort
24
- }
18
+ ensureStoreDirSync(runtimeDir());
25
19
  }
26
20
  function writeHookTokenFile(token) {
27
21
  ensureRuntimeDir();
28
22
  const file = hookTokenFile();
29
23
  writeFileSync(file, `${token}\n`, { encoding: "utf8", mode: 0o600 });
30
- try {
31
- chmodSync(file, 0o600);
32
- }
33
- catch {
34
- // best effort
35
- }
36
- }
37
- function parseJson(value) {
38
- try {
39
- return JSON.parse(value);
40
- }
41
- catch {
42
- return null;
43
- }
44
24
  }
45
25
  function normalizeNullableString(value) {
46
26
  if (typeof value !== "string")
@@ -201,7 +181,7 @@ export function readRuntimeInstances() {
201
181
  return { updatedAt: new Date().toISOString(), instances: {} };
202
182
  }
203
183
  const raw = readFileSync(file, "utf8");
204
- const parsed = parseJson(raw);
184
+ const parsed = parseJsonSafe(raw);
205
185
  if (!parsed || typeof parsed !== "object") {
206
186
  backupCorruptFileSync(file);
207
187
  return { updatedAt: new Date().toISOString(), instances: {} };
@@ -349,13 +329,7 @@ export function listRuntimeInstances(options) {
349
329
  .slice(0, limit);
350
330
  }
351
331
  export function clearRuntimeInstances() {
352
- const file = runtimeFile();
353
- try {
354
- rmSync(file, { force: true });
355
- }
356
- catch {
357
- // best effort
358
- }
332
+ clearStoreFileSync(runtimeFile());
359
333
  }
360
334
  export function resolveRuntimeHookToken() {
361
335
  const envToken = normalizeNullableString(process.env.ORGX_HOOK_TOKEN);
@@ -0,0 +1,23 @@
1
+ export interface RegisterServiceApi {
2
+ registerService: (service: {
3
+ id: string;
4
+ start: () => Promise<void>;
5
+ stop: () => Promise<void>;
6
+ }) => void;
7
+ log?: {
8
+ info?: (msg: string, meta?: Record<string, unknown>) => void;
9
+ };
10
+ }
11
+ export interface RegisterSyncServiceDeps {
12
+ api: RegisterServiceApi;
13
+ syncIntervalMs: number;
14
+ ensureGatewayWatchdog: (logger: Record<string, unknown>) => {
15
+ started: boolean;
16
+ pid?: number | null;
17
+ };
18
+ doSync: () => Promise<void>;
19
+ scheduleNextSync: () => void;
20
+ setSyncServiceRunning: (running: boolean) => void;
21
+ clearSyncTimer: () => void;
22
+ }
23
+ export declare function registerSyncService(deps: RegisterSyncServiceDeps): void;
@@ -0,0 +1,23 @@
1
+ export function registerSyncService(deps) {
2
+ deps.api.registerService({
3
+ id: "orgx-sync",
4
+ start: async () => {
5
+ deps.setSyncServiceRunning(true);
6
+ const watchdog = deps.ensureGatewayWatchdog((deps.api.log ?? {}));
7
+ if (watchdog.started) {
8
+ deps.api.log?.info?.("[orgx] Gateway watchdog started", {
9
+ pid: watchdog.pid,
10
+ });
11
+ }
12
+ deps.api.log?.info?.("[orgx] Starting sync service", {
13
+ interval: deps.syncIntervalMs,
14
+ });
15
+ await deps.doSync();
16
+ deps.scheduleNextSync();
17
+ },
18
+ stop: async () => {
19
+ deps.setSyncServiceRunning(false);
20
+ deps.clearSyncTimer();
21
+ },
22
+ });
23
+ }
@@ -0,0 +1,29 @@
1
+ type ToolLike = {
2
+ name: string;
3
+ description: string;
4
+ parameters: Record<string, unknown>;
5
+ execute: (callId: string, params?: unknown) => Promise<{
6
+ content: Array<{
7
+ type: "text";
8
+ text: string;
9
+ }>;
10
+ }>;
11
+ };
12
+ type ServiceLike = {
13
+ id: string;
14
+ start: () => Promise<void>;
15
+ stop: () => Promise<void>;
16
+ };
17
+ type ApiLike = {
18
+ registerTool: (tool: ToolLike, options?: {
19
+ optional?: boolean;
20
+ }) => void;
21
+ registerService: (service: ServiceLike) => void;
22
+ };
23
+ export declare function instrumentPluginApi(input: {
24
+ api: ApiLike;
25
+ installationId: string;
26
+ pluginVersion: string;
27
+ toErrorMessage: (err: unknown) => string;
28
+ }): void;
29
+ export {};
@@ -0,0 +1,136 @@
1
+ import { posthogCapture } from "../telemetry/posthog.js";
2
+ export function instrumentPluginApi(input) {
3
+ const registerTool = input.api.registerTool.bind(input.api);
4
+ input.api.registerTool = (tool, options) => {
5
+ const toolName = tool.name;
6
+ const optional = Boolean(options?.optional);
7
+ registerTool({
8
+ ...tool,
9
+ execute: async (callId, params) => {
10
+ const startedAt = Date.now();
11
+ void posthogCapture({
12
+ event: "openclaw_tool_called",
13
+ distinctId: input.installationId,
14
+ properties: {
15
+ tool_name: toolName,
16
+ tool_optional: optional,
17
+ call_id: callId,
18
+ plugin_version: input.pluginVersion,
19
+ },
20
+ }).catch(() => {
21
+ // best effort
22
+ });
23
+ try {
24
+ const result = await tool.execute(callId, params);
25
+ const durationMs = Date.now() - startedAt;
26
+ void posthogCapture({
27
+ event: "openclaw_tool_succeeded",
28
+ distinctId: input.installationId,
29
+ properties: {
30
+ tool_name: toolName,
31
+ tool_optional: optional,
32
+ call_id: callId,
33
+ duration_ms: durationMs,
34
+ plugin_version: input.pluginVersion,
35
+ },
36
+ }).catch(() => {
37
+ // best effort
38
+ });
39
+ return result;
40
+ }
41
+ catch (err) {
42
+ const durationMs = Date.now() - startedAt;
43
+ void posthogCapture({
44
+ event: "openclaw_tool_failed",
45
+ distinctId: input.installationId,
46
+ properties: {
47
+ tool_name: toolName,
48
+ tool_optional: optional,
49
+ call_id: callId,
50
+ duration_ms: durationMs,
51
+ plugin_version: input.pluginVersion,
52
+ error: input.toErrorMessage(err),
53
+ },
54
+ }).catch(() => {
55
+ // best effort
56
+ });
57
+ throw err;
58
+ }
59
+ },
60
+ }, options);
61
+ };
62
+ const registerService = input.api.registerService.bind(input.api);
63
+ input.api.registerService = (service) => {
64
+ registerService({
65
+ ...service,
66
+ start: async () => {
67
+ const startedAt = Date.now();
68
+ try {
69
+ await service.start();
70
+ const durationMs = Date.now() - startedAt;
71
+ void posthogCapture({
72
+ event: "openclaw_service_started",
73
+ distinctId: input.installationId,
74
+ properties: {
75
+ service_id: service.id,
76
+ duration_ms: durationMs,
77
+ plugin_version: input.pluginVersion,
78
+ },
79
+ }).catch(() => {
80
+ // best effort
81
+ });
82
+ }
83
+ catch (err) {
84
+ const durationMs = Date.now() - startedAt;
85
+ void posthogCapture({
86
+ event: "openclaw_service_start_failed",
87
+ distinctId: input.installationId,
88
+ properties: {
89
+ service_id: service.id,
90
+ duration_ms: durationMs,
91
+ plugin_version: input.pluginVersion,
92
+ error: input.toErrorMessage(err),
93
+ },
94
+ }).catch(() => {
95
+ // best effort
96
+ });
97
+ throw err;
98
+ }
99
+ },
100
+ stop: async () => {
101
+ const startedAt = Date.now();
102
+ try {
103
+ await service.stop();
104
+ const durationMs = Date.now() - startedAt;
105
+ void posthogCapture({
106
+ event: "openclaw_service_stopped",
107
+ distinctId: input.installationId,
108
+ properties: {
109
+ service_id: service.id,
110
+ duration_ms: durationMs,
111
+ plugin_version: input.pluginVersion,
112
+ },
113
+ }).catch(() => {
114
+ // best effort
115
+ });
116
+ }
117
+ catch (err) {
118
+ const durationMs = Date.now() - startedAt;
119
+ void posthogCapture({
120
+ event: "openclaw_service_stop_failed",
121
+ distinctId: input.installationId,
122
+ properties: {
123
+ service_id: service.id,
124
+ duration_ms: durationMs,
125
+ plugin_version: input.pluginVersion,
126
+ error: input.toErrorMessage(err),
127
+ },
128
+ }).catch(() => {
129
+ // best effort
130
+ });
131
+ throw err;
132
+ }
133
+ },
134
+ });
135
+ };
136
+ }
@@ -1,6 +1,7 @@
1
- import { mkdirSync, readFileSync, chmodSync, existsSync, rmSync } from 'node:fs';
1
+ import { existsSync, readFileSync } from "node:fs";
2
2
  import { getOrgxPluginConfigDir, getOrgxPluginConfigPath } from './paths.js';
3
3
  import { backupCorruptFileSync, writeJsonFileAtomicSync } from './fs-utils.js';
4
+ import { clearStoreFileSync, ensureStoreDirSync, parseJsonSafe, } from "./stores/json-store.js";
4
5
  function snapshotDir() {
5
6
  return getOrgxPluginConfigDir();
6
7
  }
@@ -8,22 +9,7 @@ function snapshotFile() {
8
9
  return getOrgxPluginConfigPath('snapshot.json');
9
10
  }
10
11
  function ensureSnapshotDir() {
11
- const dir = snapshotDir();
12
- mkdirSync(dir, { recursive: true, mode: 0o700 });
13
- try {
14
- chmodSync(dir, 0o700);
15
- }
16
- catch {
17
- // best effort
18
- }
19
- }
20
- function parseJson(value) {
21
- try {
22
- return JSON.parse(value);
23
- }
24
- catch {
25
- return null;
26
- }
12
+ ensureStoreDirSync(snapshotDir());
27
13
  }
28
14
  export function readPersistedSnapshot() {
29
15
  const file = snapshotFile();
@@ -31,7 +17,7 @@ export function readPersistedSnapshot() {
31
17
  if (!existsSync(file))
32
18
  return null;
33
19
  const raw = readFileSync(file, 'utf8');
34
- const parsed = parseJson(raw);
20
+ const parsed = parseJsonSafe(raw);
35
21
  if (!parsed) {
36
22
  backupCorruptFileSync(file);
37
23
  return null;
@@ -57,11 +43,5 @@ export function writePersistedSnapshot(snapshot) {
57
43
  return record;
58
44
  }
59
45
  export function clearPersistedSnapshot() {
60
- const file = snapshotFile();
61
- try {
62
- rmSync(file, { force: true });
63
- }
64
- catch {
65
- // best effort
66
- }
46
+ clearStoreFileSync(snapshotFile());
67
47
  }
@@ -0,0 +1,11 @@
1
+ import { parseJsonSafe } from "../json-utils.js";
2
+ export declare function ensureStoreDirSync(dir: string): void;
3
+ export { parseJsonSafe };
4
+ export declare function readJsonFileOrDefault<T>(input: {
5
+ file: string;
6
+ fallback: () => T;
7
+ isValid?: (value: unknown) => value is T;
8
+ backupOnInvalid?: boolean;
9
+ }): T;
10
+ export declare function writeJsonStoreFileSync(file: string, data: unknown, mode?: number): void;
11
+ export declare function clearStoreFileSync(file: string): void;
@@ -0,0 +1,42 @@
1
+ import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, } from "node:fs";
2
+ import { backupCorruptFileSync, writeJsonFileAtomicSync } from "../fs-utils.js";
3
+ import { parseJsonSafe } from "../json-utils.js";
4
+ export function ensureStoreDirSync(dir) {
5
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
6
+ try {
7
+ chmodSync(dir, 0o700);
8
+ }
9
+ catch {
10
+ // best effort
11
+ }
12
+ }
13
+ export { parseJsonSafe };
14
+ export function readJsonFileOrDefault(input) {
15
+ const { file, fallback, isValid, backupOnInvalid = true, } = input;
16
+ if (!existsSync(file))
17
+ return fallback();
18
+ try {
19
+ const raw = readFileSync(file, "utf8");
20
+ const parsed = parseJsonSafe(raw);
21
+ const valid = parsed !== null && (isValid ? isValid(parsed) : true);
22
+ if (valid)
23
+ return parsed;
24
+ if (backupOnInvalid)
25
+ backupCorruptFileSync(file);
26
+ return fallback();
27
+ }
28
+ catch {
29
+ return fallback();
30
+ }
31
+ }
32
+ export function writeJsonStoreFileSync(file, data, mode = 0o600) {
33
+ writeJsonFileAtomicSync(file, data, mode);
34
+ }
35
+ export function clearStoreFileSync(file) {
36
+ try {
37
+ rmSync(file, { force: true });
38
+ }
39
+ catch {
40
+ // best effort
41
+ }
42
+ }
@@ -0,0 +1,55 @@
1
+ import type { OrgXClient } from "../api.js";
2
+ import type { OutboxEvent } from "../outbox.js";
3
+ import type { ReportingPhase, ReportingSourceClient } from "../types.js";
4
+ export type ReplayStatus = "idle" | "running" | "success" | "error";
5
+ export type OutboxReplayState = {
6
+ status: ReplayStatus;
7
+ lastReplayAttemptAt: string | null;
8
+ lastReplaySuccessAt: string | null;
9
+ lastReplayFailureAt: string | null;
10
+ lastReplayError: string | null;
11
+ };
12
+ interface ReportingContextInput {
13
+ initiative_id?: unknown;
14
+ run_id?: unknown;
15
+ correlation_id?: unknown;
16
+ source_client?: unknown;
17
+ initiativeId?: unknown;
18
+ runId?: unknown;
19
+ correlationId?: unknown;
20
+ sourceClient?: unknown;
21
+ }
22
+ type ReplayContext = {
23
+ initiativeId: string;
24
+ runId?: string;
25
+ correlationId?: string;
26
+ sourceClient?: ReportingSourceClient;
27
+ };
28
+ export interface CreateOutboxReplayerDeps {
29
+ client: OrgXClient;
30
+ logger: {
31
+ info?: (msg: string, meta?: Record<string, unknown>) => void;
32
+ warn?: (msg: string, meta?: Record<string, unknown>) => void;
33
+ };
34
+ toErrorMessage: (err: unknown) => string;
35
+ stableHash: (value: string) => string;
36
+ resolveReportingContext: (input: ReportingContextInput) => {
37
+ ok: true;
38
+ value: ReplayContext;
39
+ } | {
40
+ ok: false;
41
+ error: string;
42
+ };
43
+ pickStringField: (input: Record<string, unknown>, ...keys: string[]) => string | null;
44
+ pickStringArrayField: (input: Record<string, unknown>, ...keys: string[]) => string[] | undefined;
45
+ toReportingPhase: (phase: string, progressPct?: number) => ReportingPhase;
46
+ parseRetroEntityType: (value: string | null) => "initiative" | "task" | "milestone" | "workstream" | null | undefined;
47
+ isUuid: (value: string | undefined) => value is string;
48
+ readOutboxReplayState: () => OutboxReplayState;
49
+ writeOutboxReplayState: (next: OutboxReplayState) => void;
50
+ }
51
+ export declare function createOutboxReplayer(deps: CreateOutboxReplayerDeps): {
52
+ replayOutboxEvent: (event: OutboxEvent) => Promise<void>;
53
+ flushOutboxQueues: () => Promise<void>;
54
+ };
55
+ export {};