@realtimex/sdk 2.0.30 → 2.0.32

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 CHANGED
@@ -19,5 +19,60 @@ const workspaces = await client.request("listWorkspaces");
19
19
  `REALTIMEX_BASE_URL`. Desktop and `dev:all` runtimes propagate the resolved
20
20
  dynamic `/cli` endpoint; the SDK does not guess a localhost port.
21
21
 
22
+ ## Webhook endpoint management
23
+
24
+ Webhook endpoints can be managed through the generated authenticated client.
25
+ These control-plane operations require an authenticated, user-bound session
26
+ credential.
27
+
28
+ ```js
29
+ const { createRealtimeXClient } = require("@realtimex/sdk");
30
+
31
+ const client = createRealtimeXClient({
32
+ baseUrl: process.env.REALTIMEX_BASE_URL,
33
+ token: process.env.REALTIMEX_AUTH_TOKEN,
34
+ });
35
+
36
+ const created = await client.createWebhookEndpoint({
37
+ name: "Build tasks",
38
+ workspaceId: 7,
39
+ secret: process.env.REALTIMEX_WEBHOOK_SECRET,
40
+ dispatchMode: "trigger_agent",
41
+ });
42
+
43
+ await client.listWebhookDeliveries({
44
+ endpointId: created.endpoint.id,
45
+ limit: 25,
46
+ });
47
+ ```
48
+
49
+ The `secret` field is write-only. Endpoint responses report
50
+ `secretConfigured`; they never contain the plaintext secret, ciphertext, or a
51
+ secret-storage reference. Deletion additionally requires
52
+ `{ confirmDestructive: true }`.
53
+
54
+ ## Public webhook task delivery
55
+
56
+ Use a separate webhook client to trigger an existing public webhook endpoint.
57
+
58
+ ```js
59
+ const { createRealtimeXWebhookClient } = require("@realtimex/sdk");
60
+
61
+ const webhook = createRealtimeXWebhookClient({
62
+ endpointUrl: process.env.REALTIMEX_WEBHOOK_URL,
63
+ secret: process.env.REALTIMEX_WEBHOOK_SECRET,
64
+ });
65
+
66
+ const receipt = await webhook.trigger(
67
+ { prompt: "Review this task", context: { sourceId: "task-123" } },
68
+ { deliveryId: "task-123" }
69
+ );
70
+ ```
71
+
72
+ The client signs the exact UTF-8 request bytes with HMAC-SHA256. Network and
73
+ server-error retries reuse the serialized body, timestamp, and delivery ID so
74
+ the receiving endpoint can deduplicate delivery safely. A successful receipt
75
+ confirms acceptance and routing, not agent-task completion.
76
+
22
77
  The package also publishes generated skill assets under
23
78
  `skills/realtimex-moderator-sdk`.
package/index.d.ts CHANGED
@@ -169,6 +169,41 @@ export interface CreateThreadOptions extends RealtimeXRequestOptions {
169
169
  body?: CreateThreadBody;
170
170
  }
171
171
 
172
+ export type CreateWebhookEndpointParams = Record<string, never>;
173
+ export type CreateWebhookEndpointQuery = Record<string, never>;
174
+ export type CreateWebhookEndpointHeaders = Record<string, never>;
175
+ export type CreateWebhookEndpointBody = {
176
+ name: string;
177
+ workspaceId: number;
178
+ preset?: string;
179
+ enabled?: boolean;
180
+ secret: string;
181
+ signatureHeader?: string;
182
+ signaturePrefix?: string;
183
+ timestampHeader?: string;
184
+ deliveryIdHeader?: string;
185
+ eventTypeHeader?: string;
186
+ sourceHeader?: string;
187
+ allowedSourcePaths?: Array<string>;
188
+ replayWindowSeconds?: number;
189
+ payloadSizeLimitBytes?: number;
190
+ dispatchMode?: "record_only" | "send_to_thread" | "trigger_agent" | "trigger_flow";
191
+ triggerFlowId?: string;
192
+ agentTask?: Record<string, unknown>;
193
+ persistPayloadMode?: "none" | "attachment";
194
+ payloadStorageWorkspaceId?: number;
195
+ payloadStorageSubpath?: string;
196
+ dispatchInstruction?: string;
197
+ includePayloadPreview?: boolean;
198
+ };
199
+ export type CreateWebhookEndpointResponse = Record<string, unknown>;
200
+ export interface CreateWebhookEndpointOptions extends RealtimeXRequestOptions {
201
+ params?: CreateWebhookEndpointParams;
202
+ query?: CreateWebhookEndpointQuery;
203
+ headers?: CreateWebhookEndpointHeaders & Record<string, string>;
204
+ body?: CreateWebhookEndpointBody;
205
+ }
206
+
172
207
  export type CreateWorkspaceParams = Record<string, never>;
173
208
  export type CreateWorkspaceQuery = Record<string, never>;
174
209
  export type CreateWorkspaceHeaders = {
@@ -255,6 +290,22 @@ export interface DeleteThreadOptions extends RealtimeXRequestOptions {
255
290
  body?: DeleteThreadBody;
256
291
  }
257
292
 
293
+ export type DeleteWebhookEndpointParams = {
294
+ endpointId: string;
295
+ };
296
+ export type DeleteWebhookEndpointQuery = Record<string, never>;
297
+ export type DeleteWebhookEndpointHeaders = Record<string, never>;
298
+ export type DeleteWebhookEndpointBody = {
299
+ confirmDestructive: true;
300
+ };
301
+ export type DeleteWebhookEndpointResponse = Record<string, unknown>;
302
+ export interface DeleteWebhookEndpointOptions extends RealtimeXRequestOptions {
303
+ params?: DeleteWebhookEndpointParams;
304
+ query?: DeleteWebhookEndpointQuery;
305
+ headers?: DeleteWebhookEndpointHeaders & Record<string, string>;
306
+ body?: DeleteWebhookEndpointBody;
307
+ }
308
+
258
309
  export type DeleteWorkspaceParams = {
259
310
  workspaceSlug: string;
260
311
  };
@@ -407,6 +458,20 @@ export interface GetThreadOptions extends RealtimeXRequestOptions {
407
458
  body?: GetThreadBody;
408
459
  }
409
460
 
461
+ export type GetWebhookEndpointParams = {
462
+ endpointId: string;
463
+ };
464
+ export type GetWebhookEndpointQuery = Record<string, never>;
465
+ export type GetWebhookEndpointHeaders = Record<string, never>;
466
+ export type GetWebhookEndpointBody = unknown;
467
+ export type GetWebhookEndpointResponse = Record<string, unknown>;
468
+ export interface GetWebhookEndpointOptions extends RealtimeXRequestOptions {
469
+ params?: GetWebhookEndpointParams;
470
+ query?: GetWebhookEndpointQuery;
471
+ headers?: GetWebhookEndpointHeaders & Record<string, string>;
472
+ body?: GetWebhookEndpointBody;
473
+ }
474
+
410
475
  export type GetWorkspaceParams = {
411
476
  workspaceSlug: string;
412
477
  };
@@ -423,6 +488,25 @@ export interface GetWorkspaceOptions extends RealtimeXRequestOptions {
423
488
  body?: GetWorkspaceBody;
424
489
  }
425
490
 
491
+ export type GoalKickoffComposerParams = Record<string, never>;
492
+ export type GoalKickoffComposerQuery = Record<string, never>;
493
+ export type GoalKickoffComposerHeaders = Record<string, never>;
494
+ export type GoalKickoffComposerBody = {
495
+ cdpUrl?: string;
496
+ mainAppUrl?: string;
497
+ artifactPath?: string;
498
+ screenshotDir?: string;
499
+ timeoutMs?: number;
500
+ confirmDestructive?: boolean;
501
+ };
502
+ export type GoalKickoffComposerResponse = Record<string, unknown>;
503
+ export interface GoalKickoffComposerOptions extends RealtimeXRequestOptions {
504
+ params?: GoalKickoffComposerParams;
505
+ query?: GoalKickoffComposerQuery;
506
+ headers?: GoalKickoffComposerHeaders & Record<string, string>;
507
+ body?: GoalKickoffComposerBody;
508
+ }
509
+
426
510
  export type InstallPluginParams = Record<string, never>;
427
511
  export type InstallPluginQuery = Record<string, never>;
428
512
  export type InstallPluginHeaders = {
@@ -591,6 +675,34 @@ export interface ListThreadsOptions extends RealtimeXRequestOptions {
591
675
  body?: ListThreadsBody;
592
676
  }
593
677
 
678
+ export type ListWebhookDeliveriesParams = Record<string, never>;
679
+ export type ListWebhookDeliveriesQuery = {
680
+ endpointId?: string;
681
+ limit?: number;
682
+ offset?: number;
683
+ };
684
+ export type ListWebhookDeliveriesHeaders = Record<string, never>;
685
+ export type ListWebhookDeliveriesBody = unknown;
686
+ export type ListWebhookDeliveriesResponse = Record<string, unknown>;
687
+ export interface ListWebhookDeliveriesOptions extends RealtimeXRequestOptions {
688
+ params?: ListWebhookDeliveriesParams;
689
+ query?: ListWebhookDeliveriesQuery;
690
+ headers?: ListWebhookDeliveriesHeaders & Record<string, string>;
691
+ body?: ListWebhookDeliveriesBody;
692
+ }
693
+
694
+ export type ListWebhookEndpointsParams = Record<string, never>;
695
+ export type ListWebhookEndpointsQuery = Record<string, never>;
696
+ export type ListWebhookEndpointsHeaders = Record<string, never>;
697
+ export type ListWebhookEndpointsBody = unknown;
698
+ export type ListWebhookEndpointsResponse = Record<string, unknown>;
699
+ export interface ListWebhookEndpointsOptions extends RealtimeXRequestOptions {
700
+ params?: ListWebhookEndpointsParams;
701
+ query?: ListWebhookEndpointsQuery;
702
+ headers?: ListWebhookEndpointsHeaders & Record<string, string>;
703
+ body?: ListWebhookEndpointsBody;
704
+ }
705
+
594
706
  export type ListWorkspaceAgentSkillsParams = {
595
707
  workspaceSlug: string;
596
708
  };
@@ -826,7 +938,7 @@ export type RespondTerminalIdlePromptHeaders = {
826
938
  "x-app-id"?: string;
827
939
  };
828
940
  export type RespondTerminalIdlePromptBody = {
829
- responseAction: "confirm-selected-option" | "cancel-prompt";
941
+ responseAction: "confirm-selected-option" | "confirm-persistent-workspace-trust" | "cancel-prompt";
830
942
  expectedEventSeq: number;
831
943
  dispatchKey: string;
832
944
  };
@@ -1359,6 +1471,22 @@ export interface TerminateTerminalSessionOptions extends RealtimeXRequestOptions
1359
1471
  body?: TerminateTerminalSessionBody;
1360
1472
  }
1361
1473
 
1474
+ export type TestWebhookEndpointParams = {
1475
+ endpointId: string;
1476
+ };
1477
+ export type TestWebhookEndpointQuery = Record<string, never>;
1478
+ export type TestWebhookEndpointHeaders = Record<string, never>;
1479
+ export type TestWebhookEndpointBody = {
1480
+ payload?: Record<string, unknown>;
1481
+ };
1482
+ export type TestWebhookEndpointResponse = Record<string, unknown>;
1483
+ export interface TestWebhookEndpointOptions extends RealtimeXRequestOptions {
1484
+ params?: TestWebhookEndpointParams;
1485
+ query?: TestWebhookEndpointQuery;
1486
+ headers?: TestWebhookEndpointHeaders & Record<string, string>;
1487
+ body?: TestWebhookEndpointBody;
1488
+ }
1489
+
1362
1490
  export type TriggerWorkspaceHeartbeatParams = {
1363
1491
  workspaceSlug: string;
1364
1492
  };
@@ -1419,6 +1547,43 @@ export interface UpdateChannelOptions extends RealtimeXRequestOptions {
1419
1547
  body?: UpdateChannelBody;
1420
1548
  }
1421
1549
 
1550
+ export type UpdateWebhookEndpointParams = {
1551
+ endpointId: string;
1552
+ };
1553
+ export type UpdateWebhookEndpointQuery = Record<string, never>;
1554
+ export type UpdateWebhookEndpointHeaders = Record<string, never>;
1555
+ export type UpdateWebhookEndpointBody = {
1556
+ name?: string;
1557
+ workspaceId?: number;
1558
+ preset?: string;
1559
+ enabled?: boolean;
1560
+ secret?: string;
1561
+ signatureHeader?: string;
1562
+ signaturePrefix?: string;
1563
+ timestampHeader?: string;
1564
+ deliveryIdHeader?: string;
1565
+ eventTypeHeader?: string;
1566
+ sourceHeader?: string;
1567
+ allowedSourcePaths?: Array<string>;
1568
+ replayWindowSeconds?: number;
1569
+ payloadSizeLimitBytes?: number;
1570
+ dispatchMode?: "record_only" | "send_to_thread" | "trigger_agent" | "trigger_flow";
1571
+ triggerFlowId?: string;
1572
+ agentTask?: Record<string, unknown>;
1573
+ persistPayloadMode?: "none" | "attachment";
1574
+ payloadStorageWorkspaceId?: number;
1575
+ payloadStorageSubpath?: string;
1576
+ dispatchInstruction?: string;
1577
+ includePayloadPreview?: boolean;
1578
+ };
1579
+ export type UpdateWebhookEndpointResponse = Record<string, unknown>;
1580
+ export interface UpdateWebhookEndpointOptions extends RealtimeXRequestOptions {
1581
+ params?: UpdateWebhookEndpointParams;
1582
+ query?: UpdateWebhookEndpointQuery;
1583
+ headers?: UpdateWebhookEndpointHeaders & Record<string, string>;
1584
+ body?: UpdateWebhookEndpointBody;
1585
+ }
1586
+
1422
1587
  export type WorkspaceShellLayoutParams = Record<string, never>;
1423
1588
  export type WorkspaceShellLayoutQuery = Record<string, never>;
1424
1589
  export type WorkspaceShellLayoutHeaders = Record<string, never>;
@@ -1457,6 +1622,47 @@ export interface RealtimeXRequestOptions {
1457
1622
  signal?: AbortSignal;
1458
1623
  }
1459
1624
 
1625
+ export interface RealtimeXWebhookClientOptions {
1626
+ endpointUrl?: string;
1627
+ url?: string;
1628
+ secret?: string;
1629
+ signatureHeader?: string;
1630
+ signaturePrefix?: string;
1631
+ timestampHeader?: string;
1632
+ deliveryIdHeader?: string;
1633
+ eventTypeHeader?: string;
1634
+ sourceHeader?: string;
1635
+ eventType?: string;
1636
+ source?: string;
1637
+ headers?: Record<string, string>;
1638
+ maxRetries?: number;
1639
+ retryDelayMs?: number;
1640
+ timeoutMs?: number;
1641
+ fetch?: typeof fetch;
1642
+ }
1643
+
1644
+ export interface RealtimeXWebhookTriggerOptions {
1645
+ deliveryId?: string;
1646
+ timestamp?: string | number;
1647
+ eventType?: string;
1648
+ source?: string;
1649
+ headers?: Record<string, string>;
1650
+ maxRetries?: number;
1651
+ retryDelayMs?: number;
1652
+ timeoutMs?: number;
1653
+ signal?: AbortSignal;
1654
+ }
1655
+
1656
+ export interface RealtimeXWebhookReceipt {
1657
+ success: boolean;
1658
+ accepted: boolean;
1659
+ duplicate: boolean;
1660
+ deliveryId: string;
1661
+ threadId: string | number | null;
1662
+ taskId: string | number | null;
1663
+ [key: string]: unknown;
1664
+ }
1665
+
1460
1666
  export declare class RealtimeXApiError extends Error {
1461
1667
  status?: number;
1462
1668
  statusText?: string;
@@ -1464,6 +1670,21 @@ export declare class RealtimeXApiError extends Error {
1464
1670
  response: Response;
1465
1671
  }
1466
1672
 
1673
+ export declare class RealtimeXWebhookError extends Error {
1674
+ status?: number;
1675
+ statusText?: string;
1676
+ body: unknown;
1677
+ response: Response | null;
1678
+ }
1679
+
1680
+ export declare class RealtimeXWebhookClient {
1681
+ constructor(options?: RealtimeXWebhookClientOptions);
1682
+ trigger(
1683
+ payload: unknown,
1684
+ options?: RealtimeXWebhookTriggerOptions
1685
+ ): Promise<RealtimeXWebhookReceipt>;
1686
+ }
1687
+
1467
1688
  export declare class RealtimeXClient {
1468
1689
  constructor(options?: RealtimeXClientOptions);
1469
1690
  request(operationName: string, options?: RealtimeXRequestOptions): Promise<unknown>;
@@ -1488,6 +1709,9 @@ export declare class RealtimeXClient {
1488
1709
  /** Create a thread in one workspace. The name is optional but recommended. */
1489
1710
  createThread(options?: CreateThreadOptions): Promise<CreateThreadResponse>;
1490
1711
  createThread(workspaceSlug: string, body: CreateThreadBody, options?: Omit<CreateThreadOptions, 'params' | 'body'>): Promise<CreateThreadResponse>;
1712
+ /** Create a webhook endpoint in an accessible workspace. secret is a write-only input. */
1713
+ createWebhookEndpoint(options?: CreateWebhookEndpointOptions): Promise<CreateWebhookEndpointResponse>;
1714
+ createWebhookEndpoint(body: CreateWebhookEndpointBody, options?: Omit<CreateWebhookEndpointOptions, 'body'>): Promise<CreateWebhookEndpointResponse>;
1491
1715
  /** Create a workspace. Requires a human-readable workspace name. */
1492
1716
  createWorkspace(options?: CreateWorkspaceOptions): Promise<CreateWorkspaceResponse>;
1493
1717
  createWorkspace(body: CreateWorkspaceBody, options?: Omit<CreateWorkspaceOptions, 'body'>): Promise<CreateWorkspaceResponse>;
@@ -1503,6 +1727,9 @@ export declare class RealtimeXClient {
1503
1727
  /** Delete one thread by exact workspace slug and exact thread slug. */
1504
1728
  deleteThread(options?: DeleteThreadOptions): Promise<DeleteThreadResponse>;
1505
1729
  deleteThread(params: DeleteThreadParams, options?: Omit<DeleteThreadOptions, 'params'>): Promise<DeleteThreadResponse>;
1730
+ /** Permanently delete a visible webhook endpoint. confirmDestructive must be true. */
1731
+ deleteWebhookEndpoint(options?: DeleteWebhookEndpointOptions): Promise<DeleteWebhookEndpointResponse>;
1732
+ deleteWebhookEndpoint(endpointId: string, body: DeleteWebhookEndpointBody, options?: Omit<DeleteWebhookEndpointOptions, 'params' | 'body'>): Promise<DeleteWebhookEndpointResponse>;
1506
1733
  /** Delete one workspace by exact workspace slug. */
1507
1734
  deleteWorkspace(options?: DeleteWorkspaceOptions): Promise<DeleteWorkspaceResponse>;
1508
1735
  deleteWorkspace(workspaceSlug: string, options?: Omit<DeleteWorkspaceOptions, 'params'>): Promise<DeleteWorkspaceResponse>;
@@ -1530,9 +1757,15 @@ export declare class RealtimeXClient {
1530
1757
  /** Get one thread by exact workspace slug and exact thread slug. */
1531
1758
  getThread(options?: GetThreadOptions): Promise<GetThreadResponse>;
1532
1759
  getThread(params: GetThreadParams, options?: Omit<GetThreadOptions, 'params'>): Promise<GetThreadResponse>;
1760
+ /** Get one visible webhook endpoint by endpoint id. The response reports secretConfigured but never returns the secret. */
1761
+ getWebhookEndpoint(options?: GetWebhookEndpointOptions): Promise<GetWebhookEndpointResponse>;
1762
+ getWebhookEndpoint(endpointId: string, options?: Omit<GetWebhookEndpointOptions, 'params'>): Promise<GetWebhookEndpointResponse>;
1533
1763
  /** Get one workspace by exact workspace slug. */
1534
1764
  getWorkspace(options?: GetWorkspaceOptions): Promise<GetWorkspaceResponse>;
1535
1765
  getWorkspace(workspaceSlug: string, options?: Omit<GetWorkspaceOptions, 'params'>): Promise<GetWorkspaceResponse>;
1766
+ /** Verify the shared Project/global Goal kickoff composer, routing, attachment authorization, retry, preview, and responsive layouts. */
1767
+ goalKickoffComposer(options?: GoalKickoffComposerOptions): Promise<GoalKickoffComposerResponse>;
1768
+ goalKickoffComposer(body: GoalKickoffComposerBody, options?: Omit<GoalKickoffComposerOptions, 'body'>): Promise<GoalKickoffComposerResponse>;
1536
1769
  /** Install a plugin from a local source directory on the same machine as the server. Pass an absolute path containing realtimex.plugin.json. Pass force=true to replace an already-installed version; its saved configuration (including secrets) is preserved. */
1537
1770
  installPlugin(options?: InstallPluginOptions): Promise<InstallPluginResponse>;
1538
1771
  installPlugin(body: InstallPluginBody, options?: Omit<InstallPluginOptions, 'body'>): Promise<InstallPluginResponse>;
@@ -1560,6 +1793,11 @@ export declare class RealtimeXClient {
1560
1793
  /** List threads for one exact workspace slug. */
1561
1794
  listThreads(options?: ListThreadsOptions): Promise<ListThreadsResponse>;
1562
1795
  listThreads(workspaceSlug: string, options?: Omit<ListThreadsOptions, 'params'>): Promise<ListThreadsResponse>;
1796
+ /** List bounded delivery metadata for visible webhook endpoints. Raw headers, bodies, signatures, and payload fields are omitted. */
1797
+ listWebhookDeliveries(options?: ListWebhookDeliveriesOptions): Promise<ListWebhookDeliveriesResponse>;
1798
+ listWebhookDeliveries(query?: ListWebhookDeliveriesQuery, options?: Omit<ListWebhookDeliveriesOptions, 'query'>): Promise<ListWebhookDeliveriesResponse>;
1799
+ /** List webhook endpoints visible to the authenticated user. Secrets are never returned. */
1800
+ listWebhookEndpoints(options?: ListWebhookEndpointsOptions): Promise<ListWebhookEndpointsResponse>;
1563
1801
  /** List published agent skills with enabled/disabled state for one exact workspace slug. */
1564
1802
  listWorkspaceAgentSkills(options?: ListWorkspaceAgentSkillsOptions): Promise<ListWorkspaceAgentSkillsResponse>;
1565
1803
  listWorkspaceAgentSkills(workspaceSlug: string, options?: Omit<ListWorkspaceAgentSkillsOptions, 'params'>): Promise<ListWorkspaceAgentSkillsResponse>;
@@ -1672,6 +1910,9 @@ export declare class RealtimeXClient {
1672
1910
  /** Terminate a terminal runtime session by detaching any controller and closing the underlying PTY session. */
1673
1911
  terminateTerminalSession(options?: TerminateTerminalSessionOptions): Promise<TerminateTerminalSessionResponse>;
1674
1912
  terminateTerminalSession(sessionId: string, options?: Omit<TerminateTerminalSessionOptions, 'params'>): Promise<TerminateTerminalSessionResponse>;
1913
+ /** Submit an optional JSON payload as a signed test delivery through a visible webhook endpoint. */
1914
+ testWebhookEndpoint(options?: TestWebhookEndpointOptions): Promise<TestWebhookEndpointResponse>;
1915
+ testWebhookEndpoint(endpointId: string, body: TestWebhookEndpointBody, options?: Omit<TestWebhookEndpointOptions, 'params' | 'body'>): Promise<TestWebhookEndpointResponse>;
1675
1916
  /** Trigger the default HEARTBEAT.md task for a workspace immediately. Falls back to the legacy heartbeat executor when no tasks are defined. */
1676
1917
  triggerWorkspaceHeartbeat(options?: TriggerWorkspaceHeartbeatOptions): Promise<TriggerWorkspaceHeartbeatResponse>;
1677
1918
  triggerWorkspaceHeartbeat(workspaceSlug: string, body: TriggerWorkspaceHeartbeatBody, options?: Omit<TriggerWorkspaceHeartbeatOptions, 'params' | 'body'>): Promise<TriggerWorkspaceHeartbeatResponse>;
@@ -1681,6 +1922,9 @@ export declare class RealtimeXClient {
1681
1922
  /** Update one chat channel by exact channel id. Only channel writable fields are changed. */
1682
1923
  updateChannel(options?: UpdateChannelOptions): Promise<UpdateChannelResponse>;
1683
1924
  updateChannel(channelId: string, body: UpdateChannelBody, options?: Omit<UpdateChannelOptions, 'params' | 'body'>): Promise<UpdateChannelResponse>;
1925
+ /** Update a visible webhook endpoint. Passing secret rotates it; the value is never returned. */
1926
+ updateWebhookEndpoint(options?: UpdateWebhookEndpointOptions): Promise<UpdateWebhookEndpointResponse>;
1927
+ updateWebhookEndpoint(endpointId: string, body: UpdateWebhookEndpointBody, options?: Omit<UpdateWebhookEndpointOptions, 'params' | 'body'>): Promise<UpdateWebhookEndpointResponse>;
1684
1928
  /** Verify workspace navigation, title-bar containment, Files dock behavior, and action contrast at desktop and compact viewports. */
1685
1929
  workspaceShellLayout(options?: WorkspaceShellLayoutOptions): Promise<WorkspaceShellLayoutResponse>;
1686
1930
  workspaceShellLayout(body: WorkspaceShellLayoutBody, options?: Omit<WorkspaceShellLayoutOptions, 'body'>): Promise<WorkspaceShellLayoutResponse>;
@@ -1689,6 +1933,9 @@ export declare class RealtimeXClient {
1689
1933
  export declare function createRealtimeXClient(
1690
1934
  options?: RealtimeXClientOptions
1691
1935
  ): RealtimeXClient;
1936
+ export declare function createRealtimeXWebhookClient(
1937
+ options?: RealtimeXWebhookClientOptions
1938
+ ): RealtimeXWebhookClient;
1692
1939
  export declare const createClient: typeof createRealtimeXClient;
1693
1940
  export declare const operations: Record<
1694
1941
  string,
package/index.js CHANGED
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ const crypto = require('node:crypto');
4
+
3
5
  const operations = {
4
6
  "approveChannelPairingCode": {
5
7
  "method": "POST",
@@ -80,6 +82,14 @@ const operations = {
80
82
  ],
81
83
  "hasBody": true
82
84
  },
85
+ "createWebhookEndpoint": {
86
+ "method": "POST",
87
+ "path": "/create-webhook-endpoint",
88
+ "pathParams": [],
89
+ "queryParams": [],
90
+ "headerParams": [],
91
+ "hasBody": true
92
+ },
83
93
  "createWorkspace": {
84
94
  "method": "POST",
85
95
  "path": "/create-workspace",
@@ -140,6 +150,16 @@ const operations = {
140
150
  ],
141
151
  "hasBody": false
142
152
  },
153
+ "deleteWebhookEndpoint": {
154
+ "method": "DELETE",
155
+ "path": "/delete-webhook-endpoint/{endpointId}",
156
+ "pathParams": [
157
+ "endpointId"
158
+ ],
159
+ "queryParams": [],
160
+ "headerParams": [],
161
+ "hasBody": true
162
+ },
143
163
  "deleteWorkspace": {
144
164
  "method": "DELETE",
145
165
  "path": "/delete-workspace/{workspaceSlug}",
@@ -256,6 +276,16 @@ const operations = {
256
276
  ],
257
277
  "hasBody": false
258
278
  },
279
+ "getWebhookEndpoint": {
280
+ "method": "GET",
281
+ "path": "/get-webhook-endpoint/{endpointId}",
282
+ "pathParams": [
283
+ "endpointId"
284
+ ],
285
+ "queryParams": [],
286
+ "headerParams": [],
287
+ "hasBody": false
288
+ },
259
289
  "getWorkspace": {
260
290
  "method": "GET",
261
291
  "path": "/get-workspace/{workspaceSlug}",
@@ -268,6 +298,14 @@ const operations = {
268
298
  ],
269
299
  "hasBody": false
270
300
  },
301
+ "goalKickoffComposer": {
302
+ "method": "POST",
303
+ "path": "/goal-kickoff-composer",
304
+ "pathParams": [],
305
+ "queryParams": [],
306
+ "headerParams": [],
307
+ "hasBody": true
308
+ },
271
309
  "installPlugin": {
272
310
  "method": "POST",
273
311
  "path": "/install-plugin",
@@ -389,6 +427,26 @@ const operations = {
389
427
  ],
390
428
  "hasBody": false
391
429
  },
430
+ "listWebhookDeliveries": {
431
+ "method": "GET",
432
+ "path": "/list-webhook-deliveries",
433
+ "pathParams": [],
434
+ "queryParams": [
435
+ "endpointId",
436
+ "limit",
437
+ "offset"
438
+ ],
439
+ "headerParams": [],
440
+ "hasBody": false
441
+ },
442
+ "listWebhookEndpoints": {
443
+ "method": "GET",
444
+ "path": "/list-webhook-endpoints",
445
+ "pathParams": [],
446
+ "queryParams": [],
447
+ "headerParams": [],
448
+ "hasBody": false
449
+ },
392
450
  "listWorkspaceAgentSkills": {
393
451
  "method": "GET",
394
452
  "path": "/list-workspace-agent-skills/{workspaceSlug}",
@@ -819,6 +877,16 @@ const operations = {
819
877
  ],
820
878
  "hasBody": false
821
879
  },
880
+ "testWebhookEndpoint": {
881
+ "method": "POST",
882
+ "path": "/test-webhook-endpoint/{endpointId}",
883
+ "pathParams": [
884
+ "endpointId"
885
+ ],
886
+ "queryParams": [],
887
+ "headerParams": [],
888
+ "hasBody": true
889
+ },
822
890
  "triggerWorkspaceHeartbeat": {
823
891
  "method": "POST",
824
892
  "path": "/trigger-workspace-heartbeat/{workspaceSlug}",
@@ -855,6 +923,16 @@ const operations = {
855
923
  ],
856
924
  "hasBody": true
857
925
  },
926
+ "updateWebhookEndpoint": {
927
+ "method": "POST",
928
+ "path": "/update-webhook-endpoint/{endpointId}",
929
+ "pathParams": [
930
+ "endpointId"
931
+ ],
932
+ "queryParams": [],
933
+ "headerParams": [],
934
+ "hasBody": true
935
+ },
858
936
  "workspaceShellLayout": {
859
937
  "method": "POST",
860
938
  "path": "/workspace-shell-layout",
@@ -876,6 +954,17 @@ class RealtimeXApiError extends Error {
876
954
  }
877
955
  }
878
956
 
957
+ class RealtimeXWebhookError extends Error {
958
+ constructor(message, response = null, body = null, cause = null) {
959
+ super(message, cause ? { cause } : undefined);
960
+ this.name = 'RealtimeXWebhookError';
961
+ this.status = response && response.status;
962
+ this.statusText = response && response.statusText;
963
+ this.body = body;
964
+ this.response = response;
965
+ }
966
+ }
967
+
879
968
  function joinUrl(baseUrl, pathname) {
880
969
  const base = String(baseUrl || '').replace(/\/+$/g, '');
881
970
  const path = String(pathname || '').replace(/^\/+/, '');
@@ -929,6 +1018,220 @@ async function parseResponseBody(response) {
929
1018
  }
930
1019
  }
931
1020
 
1021
+ function normalizeWebhookEndpointUrl(value) {
1022
+ const normalized = String(value || '').trim();
1023
+ if (!normalized) {
1024
+ throw new Error(
1025
+ 'RealtimeX webhook URL is unavailable; pass { endpointUrl } or set REALTIMEX_WEBHOOK_URL.'
1026
+ );
1027
+ }
1028
+ const parsed = new URL(normalized);
1029
+ if (!['http:', 'https:'].includes(parsed.protocol)) {
1030
+ throw new Error('RealtimeX webhook URL must use http or https.');
1031
+ }
1032
+ if (parsed.username || parsed.password) {
1033
+ throw new Error('RealtimeX webhook URL must not contain embedded credentials.');
1034
+ }
1035
+ return parsed.toString();
1036
+ }
1037
+
1038
+ function normalizeRetryCount(value, fallback = 2) {
1039
+ const parsed = Number(value);
1040
+ if (!Number.isInteger(parsed) || parsed < 0 || parsed > 10) return fallback;
1041
+ return parsed;
1042
+ }
1043
+
1044
+ function normalizeTimeout(value, fallback = 15000) {
1045
+ const parsed = Number(value);
1046
+ if (!Number.isFinite(parsed) || parsed <= 0) return fallback;
1047
+ return Math.min(Math.floor(parsed), 120000);
1048
+ }
1049
+
1050
+ function waitForRetry(delayMs, signal) {
1051
+ const delay = Math.max(0, Number(delayMs) || 0);
1052
+ if (delay === 0) return Promise.resolve();
1053
+ return new Promise((resolve, reject) => {
1054
+ const finish = () => {
1055
+ if (signal) signal.removeEventListener('abort', abort);
1056
+ resolve();
1057
+ };
1058
+ const timeout = setTimeout(finish, delay);
1059
+ const abort = () => {
1060
+ clearTimeout(timeout);
1061
+ signal.removeEventListener('abort', abort);
1062
+ reject(signal.reason || new Error('Webhook request aborted.'));
1063
+ };
1064
+ if (signal) {
1065
+ if (signal.aborted) return abort();
1066
+ signal.addEventListener('abort', abort, { once: true });
1067
+ }
1068
+ });
1069
+ }
1070
+
1071
+ function createAttemptSignal(externalSignal, timeoutMs) {
1072
+ const controller = new AbortController();
1073
+ const abortFromExternal = () => {
1074
+ controller.abort(externalSignal.reason || new Error('Webhook request aborted.'));
1075
+ };
1076
+ if (externalSignal) {
1077
+ if (externalSignal.aborted) abortFromExternal();
1078
+ else externalSignal.addEventListener('abort', abortFromExternal, { once: true });
1079
+ }
1080
+ const timeout = setTimeout(
1081
+ () => controller.abort(new Error('Webhook request timed out.')),
1082
+ timeoutMs
1083
+ );
1084
+ return {
1085
+ signal: controller.signal,
1086
+ cleanup() {
1087
+ clearTimeout(timeout);
1088
+ if (externalSignal) {
1089
+ externalSignal.removeEventListener('abort', abortFromExternal);
1090
+ }
1091
+ },
1092
+ };
1093
+ }
1094
+
1095
+ class RealtimeXWebhookClient {
1096
+ constructor(options = {}) {
1097
+ const env = typeof process !== 'undefined' ? process.env || {} : {};
1098
+ this.endpointUrl = normalizeWebhookEndpointUrl(
1099
+ options.endpointUrl || options.url || env.REALTIMEX_WEBHOOK_URL
1100
+ );
1101
+ this.secret = String(options.secret || env.REALTIMEX_WEBHOOK_SECRET || '');
1102
+ if (!this.secret) {
1103
+ throw new Error(
1104
+ 'RealtimeX webhook secret is unavailable; pass { secret } or set REALTIMEX_WEBHOOK_SECRET.'
1105
+ );
1106
+ }
1107
+ this.fetch = options.fetch || globalThis.fetch;
1108
+ if (typeof this.fetch !== 'function') {
1109
+ throw new Error('A fetch implementation is required. Use Node 18+ or pass { fetch }.');
1110
+ }
1111
+ this.signatureHeader =
1112
+ options.signatureHeader ||
1113
+ env.REALTIMEX_WEBHOOK_SIGNATURE_HEADER ||
1114
+ 'X-Webhook-Signature-256';
1115
+ this.signaturePrefix =
1116
+ options.signaturePrefix ?? env.REALTIMEX_WEBHOOK_SIGNATURE_PREFIX ?? 'sha256=';
1117
+ this.timestampHeader =
1118
+ options.timestampHeader ||
1119
+ env.REALTIMEX_WEBHOOK_TIMESTAMP_HEADER ||
1120
+ 'X-Webhook-Timestamp';
1121
+ this.deliveryIdHeader =
1122
+ options.deliveryIdHeader ||
1123
+ env.REALTIMEX_WEBHOOK_DELIVERY_ID_HEADER ||
1124
+ 'X-Webhook-Id';
1125
+ this.eventTypeHeader =
1126
+ options.eventTypeHeader ||
1127
+ env.REALTIMEX_WEBHOOK_EVENT_TYPE_HEADER ||
1128
+ 'X-Webhook-Event';
1129
+ this.sourceHeader =
1130
+ options.sourceHeader ||
1131
+ env.REALTIMEX_WEBHOOK_SOURCE_HEADER ||
1132
+ 'X-Webhook-Source';
1133
+ this.defaultEventType =
1134
+ options.eventType || env.REALTIMEX_WEBHOOK_EVENT_TYPE || 'realtimex.task';
1135
+ this.defaultSource =
1136
+ options.source || env.REALTIMEX_WEBHOOK_SOURCE || 'local-app';
1137
+ this.defaultHeaders = { ...(options.headers || {}) };
1138
+ this.maxRetries = normalizeRetryCount(options.maxRetries, 2);
1139
+ const configuredRetryDelay = Number(options.retryDelayMs);
1140
+ this.retryDelayMs = Number.isFinite(configuredRetryDelay) && configuredRetryDelay >= 0
1141
+ ? configuredRetryDelay
1142
+ : 250;
1143
+ this.timeoutMs = normalizeTimeout(options.timeoutMs, 15000);
1144
+ }
1145
+
1146
+ async trigger(payload, options = {}) {
1147
+ if (payload === undefined) {
1148
+ throw new Error('RealtimeX webhook payload is required.');
1149
+ }
1150
+ const serialized = typeof payload === 'string' ? payload : JSON.stringify(payload);
1151
+ if (serialized === undefined) {
1152
+ throw new Error('RealtimeX webhook payload is not JSON serializable.');
1153
+ }
1154
+ const body = Buffer.from(serialized, 'utf8');
1155
+ const deliveryId = String(options.deliveryId || crypto.randomUUID());
1156
+ const timestamp = String(
1157
+ options.timestamp || Math.floor(Date.now() / 1000)
1158
+ );
1159
+ const signature = crypto
1160
+ .createHmac('sha256', this.secret)
1161
+ .update(body)
1162
+ .digest('hex');
1163
+ const headers = {
1164
+ ...this.defaultHeaders,
1165
+ ...(options.headers || {}),
1166
+ 'content-type': 'application/json',
1167
+ [this.signatureHeader]: String(this.signaturePrefix || '') + signature,
1168
+ [this.timestampHeader]: timestamp,
1169
+ [this.deliveryIdHeader]: deliveryId,
1170
+ [this.eventTypeHeader]: String(options.eventType || this.defaultEventType),
1171
+ [this.sourceHeader]: String(options.source || this.defaultSource),
1172
+ };
1173
+ const maxRetries = normalizeRetryCount(options.maxRetries, this.maxRetries);
1174
+ const retryDelayMs =
1175
+ options.retryDelayMs === undefined
1176
+ ? this.retryDelayMs
1177
+ : Math.max(0, Number(options.retryDelayMs) || 0);
1178
+ const timeoutMs = normalizeTimeout(options.timeoutMs, this.timeoutMs);
1179
+
1180
+ for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
1181
+ const attemptSignal = createAttemptSignal(options.signal, timeoutMs);
1182
+ try {
1183
+ const response = await this.fetch(this.endpointUrl, {
1184
+ method: 'POST',
1185
+ headers,
1186
+ body,
1187
+ signal: attemptSignal.signal,
1188
+ });
1189
+ const responseBody = await parseResponseBody(response);
1190
+ if (response.status >= 500 && attempt < maxRetries) {
1191
+ await waitForRetry(retryDelayMs * (attempt + 1), options.signal);
1192
+ continue;
1193
+ }
1194
+ if (!response.ok) {
1195
+ throw new RealtimeXWebhookError(
1196
+ 'RealtimeX webhook request failed: ' +
1197
+ response.status +
1198
+ ' ' +
1199
+ response.statusText,
1200
+ response,
1201
+ responseBody
1202
+ );
1203
+ }
1204
+ return responseBody;
1205
+ } catch (error) {
1206
+ if (error instanceof RealtimeXWebhookError) throw error;
1207
+ if (options.signal && options.signal.aborted) {
1208
+ throw new RealtimeXWebhookError(
1209
+ 'RealtimeX webhook request aborted.',
1210
+ null,
1211
+ null,
1212
+ error
1213
+ );
1214
+ }
1215
+ if (attempt >= maxRetries) {
1216
+ const timedOut = attemptSignal.signal.aborted;
1217
+ throw new RealtimeXWebhookError(
1218
+ timedOut
1219
+ ? 'RealtimeX webhook request timed out.'
1220
+ : 'RealtimeX webhook request failed: ' + (error.message || String(error)),
1221
+ null,
1222
+ null,
1223
+ error
1224
+ );
1225
+ }
1226
+ await waitForRetry(retryDelayMs * (attempt + 1), options.signal);
1227
+ } finally {
1228
+ attemptSignal.cleanup();
1229
+ }
1230
+ }
1231
+ throw new RealtimeXWebhookError('RealtimeX webhook request failed.');
1232
+ }
1233
+ }
1234
+
932
1235
  function isPlainObject(value) {
933
1236
  return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
934
1237
  }
@@ -1112,6 +1415,13 @@ class RealtimeXClient {
1112
1415
  );
1113
1416
  }
1114
1417
 
1418
+ createWebhookEndpoint(...args) {
1419
+ return this.request(
1420
+ "createWebhookEndpoint",
1421
+ normalizeOperationOptions(operations["createWebhookEndpoint"], args)
1422
+ );
1423
+ }
1424
+
1115
1425
  createWorkspace(...args) {
1116
1426
  return this.request(
1117
1427
  "createWorkspace",
@@ -1147,6 +1457,13 @@ class RealtimeXClient {
1147
1457
  );
1148
1458
  }
1149
1459
 
1460
+ deleteWebhookEndpoint(...args) {
1461
+ return this.request(
1462
+ "deleteWebhookEndpoint",
1463
+ normalizeOperationOptions(operations["deleteWebhookEndpoint"], args)
1464
+ );
1465
+ }
1466
+
1150
1467
  deleteWorkspace(...args) {
1151
1468
  return this.request(
1152
1469
  "deleteWorkspace",
@@ -1210,6 +1527,13 @@ class RealtimeXClient {
1210
1527
  );
1211
1528
  }
1212
1529
 
1530
+ getWebhookEndpoint(...args) {
1531
+ return this.request(
1532
+ "getWebhookEndpoint",
1533
+ normalizeOperationOptions(operations["getWebhookEndpoint"], args)
1534
+ );
1535
+ }
1536
+
1213
1537
  getWorkspace(...args) {
1214
1538
  return this.request(
1215
1539
  "getWorkspace",
@@ -1217,6 +1541,13 @@ class RealtimeXClient {
1217
1541
  );
1218
1542
  }
1219
1543
 
1544
+ goalKickoffComposer(...args) {
1545
+ return this.request(
1546
+ "goalKickoffComposer",
1547
+ normalizeOperationOptions(operations["goalKickoffComposer"], args)
1548
+ );
1549
+ }
1550
+
1220
1551
  installPlugin(...args) {
1221
1552
  return this.request(
1222
1553
  "installPlugin",
@@ -1294,6 +1625,20 @@ class RealtimeXClient {
1294
1625
  );
1295
1626
  }
1296
1627
 
1628
+ listWebhookDeliveries(...args) {
1629
+ return this.request(
1630
+ "listWebhookDeliveries",
1631
+ normalizeOperationOptions(operations["listWebhookDeliveries"], args)
1632
+ );
1633
+ }
1634
+
1635
+ listWebhookEndpoints(...args) {
1636
+ return this.request(
1637
+ "listWebhookEndpoints",
1638
+ normalizeOperationOptions(operations["listWebhookEndpoints"], args)
1639
+ );
1640
+ }
1641
+
1297
1642
  listWorkspaceAgentSkills(...args) {
1298
1643
  return this.request(
1299
1644
  "listWorkspaceAgentSkills",
@@ -1560,6 +1905,13 @@ class RealtimeXClient {
1560
1905
  );
1561
1906
  }
1562
1907
 
1908
+ testWebhookEndpoint(...args) {
1909
+ return this.request(
1910
+ "testWebhookEndpoint",
1911
+ normalizeOperationOptions(operations["testWebhookEndpoint"], args)
1912
+ );
1913
+ }
1914
+
1563
1915
  triggerWorkspaceHeartbeat(...args) {
1564
1916
  return this.request(
1565
1917
  "triggerWorkspaceHeartbeat",
@@ -1581,6 +1933,13 @@ class RealtimeXClient {
1581
1933
  );
1582
1934
  }
1583
1935
 
1936
+ updateWebhookEndpoint(...args) {
1937
+ return this.request(
1938
+ "updateWebhookEndpoint",
1939
+ normalizeOperationOptions(operations["updateWebhookEndpoint"], args)
1940
+ );
1941
+ }
1942
+
1584
1943
  workspaceShellLayout(...args) {
1585
1944
  return this.request(
1586
1945
  "workspaceShellLayout",
@@ -1593,11 +1952,18 @@ function createRealtimeXClient(options = {}) {
1593
1952
  return new RealtimeXClient(options);
1594
1953
  }
1595
1954
 
1955
+ function createRealtimeXWebhookClient(options = {}) {
1956
+ return new RealtimeXWebhookClient(options);
1957
+ }
1958
+
1596
1959
  module.exports = {
1597
1960
  RealtimeXApiError,
1598
1961
  RealtimeXClient,
1962
+ RealtimeXWebhookClient,
1963
+ RealtimeXWebhookError,
1599
1964
  createClient: createRealtimeXClient,
1600
1965
  createRealtimeXClient,
1966
+ createRealtimeXWebhookClient,
1601
1967
  operations,
1602
- version: "2.0.30",
1968
+ version: "2.0.32",
1603
1969
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@realtimex/sdk",
3
- "version": "2.0.30",
3
+ "version": "2.0.32",
4
4
  "description": "RealtimeX runtime SDK package and moderator agent skill assets.",
5
5
  "private": false,
6
6
  "main": "./index.js",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: realtimex-moderator-sdk
3
- description: "Use the RealTimeX API through the generated CLI for workspace, thread, terminal-agent sessions, channel (Telegram, Zalo, Discord), skills, plugins and send messages, setup personality, heartbeat tasks operations, publish and manage artifacts, run tour guide to setup working dir."
3
+ description: "Use the RealTimeX API through the generated CLI for workspace, thread, terminal-agent sessions, channel (Telegram, Zalo, Discord), skills, plugins, webhook endpoint management and delivery inspection, send messages, setup personality, heartbeat tasks operations, publish and manage artifacts, run tour guide to setup working dir."
4
4
  author: ""
5
5
  license: "Apache-2.0"
6
6
  argument-hint: "<command> [args] | install cli"
@@ -20,15 +20,15 @@ This skill drives the `realtimex-pp-cli` binary. Verify the CLI is installed and
20
20
 
21
21
  1. Install or reinstall the pinned version via npm:
22
22
  ```bash
23
- npm install -g @realtimex/pp-cli@2.0.30
23
+ npm install -g @realtimex/pp-cli@2.0.32
24
24
  ```
25
25
  2. Verify the exact version:
26
26
  ```bash
27
27
  realtimex-pp-cli --version
28
28
  ```
29
- The output must be `realtimex-pp-cli 2.0.30`.
29
+ The output must be `realtimex-pp-cli 2.0.32`.
30
30
 
31
- If `--version` reports "command not found" after install, the npm global bin directory is not on `$PATH`. If it reports any version other than `2.0.30`, reinstall with the pinned npm command above. Do not proceed with skill commands until exact-version verification succeeds.
31
+ If `--version` reports "command not found" after install, the npm global bin directory is not on `$PATH`. If it reports any version other than `2.0.32`, reinstall with the pinned npm command above. Do not proceed with skill commands until exact-version verification succeeds.
32
32
 
33
33
  * Always run first:
34
34
 
@@ -66,6 +66,10 @@ If `--version` reports "command not found" after install, the npm global bin dir
66
66
 
67
67
  - `realtimex-pp-cli create-thread <workspaceSlug>` — Create a thread in one workspace. The name is optional but recommended.
68
68
 
69
+ **create-webhook-endpoint** — Manage create webhook endpoint
70
+
71
+ - `realtimex-pp-cli create-webhook-endpoint` — Create a webhook endpoint in an accessible workspace. secret is a write-only input.
72
+
69
73
  **create-workspace** — Manage create workspace
70
74
 
71
75
  - `realtimex-pp-cli create-workspace` — Create a workspace. Requires a human-readable workspace name.
@@ -86,6 +90,10 @@ If `--version` reports "command not found" after install, the npm global bin dir
86
90
 
87
91
  - `realtimex-pp-cli delete-thread <workspaceSlug> <threadSlug>` — Delete one thread by exact workspace slug and exact thread slug.
88
92
 
93
+ **delete-webhook-endpoint** — Manage delete webhook endpoint
94
+
95
+ - `realtimex-pp-cli delete-webhook-endpoint <endpointId>` — Permanently delete a visible webhook endpoint. confirmDestructive must be true.
96
+
89
97
  **delete-workspace** — Manage delete workspace
90
98
 
91
99
  - `realtimex-pp-cli delete-workspace <workspaceSlug>` — Delete one workspace by exact workspace slug.
@@ -122,10 +130,18 @@ If `--version` reports "command not found" after install, the npm global bin dir
122
130
 
123
131
  - `realtimex-pp-cli get-thread <workspaceSlug> <threadSlug>` — Get one thread by exact workspace slug and exact thread slug.
124
132
 
133
+ **get-webhook-endpoint** — Manage get webhook endpoint
134
+
135
+ - `realtimex-pp-cli get-webhook-endpoint <endpointId>` — Get one visible webhook endpoint by endpoint id. The response reports secretConfigured but never returns the secret.
136
+
125
137
  **get-workspace** — Manage get workspace
126
138
 
127
139
  - `realtimex-pp-cli get-workspace <workspaceSlug>` — Get one workspace by exact workspace slug.
128
140
 
141
+ **goal-kickoff-composer** — Manage goal kickoff composer
142
+
143
+ - `realtimex-pp-cli goal-kickoff-composer` — Verify the shared Project/global Goal kickoff composer, routing, attachment authorization, retry, preview
144
+
129
145
  **install-plugin** — Manage install plugin
130
146
 
131
147
  - `realtimex-pp-cli install-plugin` — Install a plugin from a local source directory on the same machine as the server.
@@ -170,6 +186,14 @@ If `--version` reports "command not found" after install, the npm global bin dir
170
186
 
171
187
  - `realtimex-pp-cli list-threads <workspaceSlug>` — List threads for one exact workspace slug.
172
188
 
189
+ **list-webhook-deliveries** — Manage list webhook deliveries
190
+
191
+ - `realtimex-pp-cli list-webhook-deliveries` — List bounded delivery metadata for visible webhook endpoints.
192
+
193
+ **list-webhook-endpoints** — Manage list webhook endpoints
194
+
195
+ - `realtimex-pp-cli list-webhook-endpoints` — List webhook endpoints visible to the authenticated user. Secrets are never returned.
196
+
173
197
  **list-workspace-agent-skills** — Manage list workspace agent skills
174
198
 
175
199
  - `realtimex-pp-cli list-workspace-agent-skills <workspaceSlug>` — List published agent skills with enabled/disabled state for one exact workspace slug.
@@ -318,6 +342,10 @@ If `--version` reports "command not found" after install, the npm global bin dir
318
342
 
319
343
  - `realtimex-pp-cli terminate-terminal-session <sessionId>` — Terminate a terminal runtime session by detaching any controller and closing the underlying PTY session.
320
344
 
345
+ **test-webhook-endpoint** — Manage test webhook endpoint
346
+
347
+ - `realtimex-pp-cli test-webhook-endpoint <endpointId>` — Submit an optional JSON payload as a signed test delivery through a visible webhook endpoint.
348
+
321
349
  **trigger-workspace-heartbeat** — Manage trigger workspace heartbeat
322
350
 
323
351
  - `realtimex-pp-cli trigger-workspace-heartbeat <workspaceSlug>` — Trigger the default HEARTBEAT.md task for a workspace immediately.
@@ -330,6 +358,10 @@ If `--version` reports "command not found" after install, the npm global bin dir
330
358
 
331
359
  - `realtimex-pp-cli update-channel <channelId>` — Update one chat channel by exact channel id. Only channel writable fields are changed.
332
360
 
361
+ **update-webhook-endpoint** — Manage update webhook endpoint
362
+
363
+ - `realtimex-pp-cli update-webhook-endpoint <endpointId>` — Update a visible webhook endpoint. Passing secret rotates it; the value is never returned.
364
+
333
365
  **workspace-shell-layout** — Manage workspace shell layout
334
366
 
335
367
  - `realtimex-pp-cli workspace-shell-layout` — Verify workspace navigation, title-bar containment, Files dock behavior
@@ -460,9 +492,9 @@ Verify: `claude mcp list`
460
492
  ```bash
461
493
  realtimex-pp-cli --version
462
494
  ```
463
- If the command is missing or the output is not exactly `realtimex-pp-cli 2.0.30`, reinstall the pinned version:
495
+ If the command is missing or the output is not exactly `realtimex-pp-cli 2.0.32`, reinstall the pinned version:
464
496
  ```bash
465
- npm install -g @realtimex/pp-cli@2.0.30
497
+ npm install -g @realtimex/pp-cli@2.0.32
466
498
  ```
467
499
  Then run `realtimex-pp-cli --version` again and proceed only after exact-version verification succeeds.
468
500
  2. Match the user query to the best command from the Unique Capabilities and Command Reference above.
@@ -525,6 +557,13 @@ For `send-channel-file`:
525
557
  * In desktop/local runtime, the CLI should send the absolute local `filePath` to the server. The server validates the path against allowed storage/temp roots before sending through the channel. Base64 upload is fallback transport, not the preferred path.
526
558
  * The server validates the delivery context, active channel session, plugin state, runtime binding when supplied, and file size/type handling before delivery.
527
559
 
560
+ For webhook endpoint management:
561
+
562
+ * These operations require an authenticated, user-bound session credential.
563
+ * Treat `secret` as write-only input for creation or rotation. Never expect, request, print, or persist a plaintext secret from endpoint responses.
564
+ * Use `list-webhook-deliveries` for bounded metadata inspection. Raw request headers, signatures, bodies, and normalized payload fields are intentionally unavailable.
565
+ * Pass `confirmDestructive=true` only after the user has explicitly requested permanent endpoint deletion.
566
+
528
567
  For workspace default-agent setup:
529
568
 
530
569
  * Use `prepare.agents` only.