@clawhive/openclaw-plugin 0.2.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 (80) hide show
  1. package/README.md +217 -0
  2. package/dist/api.d.ts +6 -0
  3. package/dist/api.js +6 -0
  4. package/dist/index.d.ts +4 -0
  5. package/dist/index.js +324 -0
  6. package/dist/runtime-api.d.ts +1 -0
  7. package/dist/runtime-api.js +1 -0
  8. package/dist/setup-entry.d.ts +4 -0
  9. package/dist/setup-entry.js +3 -0
  10. package/dist/src/agency-install/claimLoop.d.ts +41 -0
  11. package/dist/src/agency-install/claimLoop.js +188 -0
  12. package/dist/src/agent-panel/claimLoop.d.ts +32 -0
  13. package/dist/src/agent-panel/claimLoop.js +118 -0
  14. package/dist/src/agent-panel/executor.d.ts +8 -0
  15. package/dist/src/agent-panel/executor.js +368 -0
  16. package/dist/src/agent-panel/plan.d.ts +20 -0
  17. package/dist/src/agent-panel/plan.js +111 -0
  18. package/dist/src/agent-panel/prompts.d.ts +38 -0
  19. package/dist/src/agent-panel/prompts.js +87 -0
  20. package/dist/src/agent-panel/types.d.ts +45 -0
  21. package/dist/src/agent-panel/types.js +1 -0
  22. package/dist/src/agents.d.ts +44 -0
  23. package/dist/src/agents.js +195 -0
  24. package/dist/src/authorization.d.ts +34 -0
  25. package/dist/src/authorization.js +183 -0
  26. package/dist/src/channel.d.ts +5 -0
  27. package/dist/src/channel.js +93 -0
  28. package/dist/src/claimPolling.d.ts +9 -0
  29. package/dist/src/claimPolling.js +13 -0
  30. package/dist/src/client.d.ts +386 -0
  31. package/dist/src/client.js +595 -0
  32. package/dist/src/config.d.ts +28 -0
  33. package/dist/src/config.js +94 -0
  34. package/dist/src/defaults.d.ts +40 -0
  35. package/dist/src/defaults.js +52 -0
  36. package/dist/src/deviceCode.d.ts +16 -0
  37. package/dist/src/deviceCode.js +65 -0
  38. package/dist/src/heartbeat.d.ts +25 -0
  39. package/dist/src/heartbeat.js +65 -0
  40. package/dist/src/imageAttachments.d.ts +14 -0
  41. package/dist/src/imageAttachments.js +81 -0
  42. package/dist/src/inbound.d.ts +10 -0
  43. package/dist/src/inbound.js +140 -0
  44. package/dist/src/installMutex.d.ts +4 -0
  45. package/dist/src/installMutex.js +18 -0
  46. package/dist/src/market-install/claimLoop.d.ts +41 -0
  47. package/dist/src/market-install/claimLoop.js +183 -0
  48. package/dist/src/market-install/downloader.d.ts +36 -0
  49. package/dist/src/market-install/downloader.js +133 -0
  50. package/dist/src/market-install/executor.d.ts +28 -0
  51. package/dist/src/market-install/executor.js +352 -0
  52. package/dist/src/market-install/types.d.ts +62 -0
  53. package/dist/src/market-install/types.js +1 -0
  54. package/dist/src/market-install/verifier.d.ts +32 -0
  55. package/dist/src/market-install/verifier.js +60 -0
  56. package/dist/src/market-publish/packager.d.ts +34 -0
  57. package/dist/src/market-publish/packager.js +168 -0
  58. package/dist/src/market-publish/publishFlow.d.ts +70 -0
  59. package/dist/src/market-publish/publishFlow.js +107 -0
  60. package/dist/src/market-publish/uploader.d.ts +73 -0
  61. package/dist/src/market-publish/uploader.js +132 -0
  62. package/dist/src/openclawVersion.d.ts +4 -0
  63. package/dist/src/openclawVersion.js +13 -0
  64. package/dist/src/outbound.d.ts +13 -0
  65. package/dist/src/outbound.js +41 -0
  66. package/dist/src/pairing.d.ts +32 -0
  67. package/dist/src/pairing.js +64 -0
  68. package/dist/src/runtime.d.ts +52 -0
  69. package/dist/src/runtime.js +26 -0
  70. package/dist/src/telemetry.d.ts +34 -0
  71. package/dist/src/telemetry.js +89 -0
  72. package/dist/src/transport/realtime.d.ts +49 -0
  73. package/dist/src/transport/realtime.js +273 -0
  74. package/dist/src/transport.d.ts +38 -0
  75. package/dist/src/transport.js +15 -0
  76. package/dist/src/wake.d.ts +31 -0
  77. package/dist/src/wake.js +101 -0
  78. package/openclaw.config.example.yaml +10 -0
  79. package/openclaw.plugin.json +122 -0
  80. package/package.json +84 -0
@@ -0,0 +1,188 @@
1
+ import { DEFAULT_ACTIVE_POLL_MS, DEFAULT_IDLE_POLL_MS, DEFAULT_RETRY_POLL_MS, jitterPollDelay, } from "../claimPolling.js";
2
+ import { runExclusiveInstall } from "../installMutex.js";
3
+ import { addInstallBreadcrumb, captureInstallFailure } from "../telemetry.js";
4
+ import { executeInstallJob } from "../market-install/executor.js";
5
+ /**
6
+ * Poll Agency install jobs and reuse the existing manifest executor with Agency endpoints.
7
+ */
8
+ export class AgencyInstallClaimLoop {
9
+ options;
10
+ timer = null;
11
+ wakeTimer = null;
12
+ wakePending = false;
13
+ claiming = false;
14
+ running = false;
15
+ activeRun = null;
16
+ lastError = null;
17
+ constructor(options) {
18
+ this.options = options;
19
+ }
20
+ start() {
21
+ if (this.running) {
22
+ return;
23
+ }
24
+ this.running = true;
25
+ void this.tick(true);
26
+ }
27
+ async stop() {
28
+ this.running = false;
29
+ if (this.timer) {
30
+ clearTimeout(this.timer);
31
+ this.timer = null;
32
+ }
33
+ if (this.wakeTimer) {
34
+ clearTimeout(this.wakeTimer);
35
+ this.wakeTimer = null;
36
+ }
37
+ this.wakePending = false;
38
+ if (this.activeRun) {
39
+ await this.activeRun;
40
+ }
41
+ this.options.onActiveInstallChange?.(null);
42
+ }
43
+ getLastError() {
44
+ return this.lastError;
45
+ }
46
+ wake() {
47
+ if (!this.running) {
48
+ return;
49
+ }
50
+ this.wakePending = true;
51
+ if (this.timer) {
52
+ clearTimeout(this.timer);
53
+ this.timer = null;
54
+ }
55
+ if (this.wakeTimer) {
56
+ return;
57
+ }
58
+ this.wakeTimer = setTimeout(() => {
59
+ this.wakeTimer = null;
60
+ if (!this.running || !this.wakePending) {
61
+ return;
62
+ }
63
+ this.wakePending = false;
64
+ void this.tick(false);
65
+ }, 25);
66
+ }
67
+ schedule(delayMs) {
68
+ if (!this.running) {
69
+ return;
70
+ }
71
+ const nextDelayMs = jitterPollDelay(delayMs);
72
+ this.timer = setTimeout(() => {
73
+ this.timer = null;
74
+ void this.tick(false);
75
+ }, nextDelayMs);
76
+ }
77
+ async tick(initial) {
78
+ if (!this.running) {
79
+ return;
80
+ }
81
+ if (this.claiming) {
82
+ this.wakePending = true;
83
+ return;
84
+ }
85
+ if (this.activeRun) {
86
+ return;
87
+ }
88
+ this.claiming = true;
89
+ try {
90
+ const result = await this.options.api.claimAgencyInstallJob({
91
+ pluginNodeId: this.options.pluginNodeId,
92
+ userId: this.options.userId,
93
+ });
94
+ this.claiming = false;
95
+ if (!result.job) {
96
+ this.lastError = null;
97
+ this.schedule(this.options.idlePollMs ?? DEFAULT_IDLE_POLL_MS);
98
+ return;
99
+ }
100
+ this.activeRun = this.processJob(result.job).finally(() => {
101
+ this.activeRun = null;
102
+ this.options.onActiveInstallChange?.(null);
103
+ });
104
+ await this.activeRun;
105
+ this.lastError = null;
106
+ this.schedule(DEFAULT_ACTIVE_POLL_MS);
107
+ }
108
+ catch (error) {
109
+ this.lastError = error;
110
+ const reason = error instanceof Error ? error.message : String(error);
111
+ this.options.logger?.warn(`ClawHive Agency install claim loop failed initial=${initial}: ${reason}`);
112
+ this.schedule(this.options.retryPollMs ?? DEFAULT_RETRY_POLL_MS);
113
+ }
114
+ finally {
115
+ if (this.claiming) {
116
+ this.claiming = false;
117
+ }
118
+ if (this.running && this.wakePending && !this.activeRun) {
119
+ this.wake();
120
+ }
121
+ }
122
+ }
123
+ async processJob(job) {
124
+ const pushStage = (stage) => {
125
+ this.options.onActiveInstallChange?.({
126
+ jobId: job.jobId,
127
+ listingId: job.listingId,
128
+ listingName: job.listingName,
129
+ releaseId: job.releaseId,
130
+ version: job.version,
131
+ targetNodeId: job.targetNodeId,
132
+ targetNodeName: job.targetNodeName,
133
+ stage,
134
+ updatedAt: new Date().toISOString(),
135
+ });
136
+ };
137
+ pushStage("claimed");
138
+ const executorApi = Object.create(this.options.api);
139
+ executorApi.updateInstallJob = this.options.api.updateAgencyInstallJob.bind(this.options.api);
140
+ executorApi.fetchInstallManifest =
141
+ this.options.api.fetchAgencyInstallManifest.bind(this.options.api);
142
+ try {
143
+ await runExclusiveInstall(() => executeInstallJob(job, {
144
+ api: executorApi,
145
+ pluginApi: this.options.pluginApi,
146
+ pluginNodeId: this.options.pluginNodeId,
147
+ userId: this.options.userId,
148
+ pluginVersion: this.options.pluginVersion,
149
+ openClawVersion: this.options.openClawVersion,
150
+ logger: this.options.logger ?? console,
151
+ onStageChange: pushStage,
152
+ onAgentsSynced: this.options.onAgentsSynced,
153
+ requireClaimedArtifact: false,
154
+ }));
155
+ }
156
+ catch (error) {
157
+ const reason = error instanceof Error ? error.message : String(error);
158
+ this.options.logger?.warn(`ClawHive Agency install executor crashed for job ${job.jobId}: ${reason}`);
159
+ pushStage("failed");
160
+ addInstallBreadcrumb({
161
+ stage: "executor-crashed",
162
+ job,
163
+ reasonKind: "install_apply_failed",
164
+ data: { error: reason },
165
+ });
166
+ captureInstallFailure({
167
+ error,
168
+ reasonKind: "install_apply_failed",
169
+ job,
170
+ });
171
+ await this.options.api.updateAgencyInstallJob({
172
+ pluginNodeId: this.options.pluginNodeId,
173
+ jobId: job.jobId,
174
+ userId: this.options.userId,
175
+ status: "failed",
176
+ reasonKind: "install_apply_failed",
177
+ errorMessage: reason,
178
+ details: {
179
+ crashDuring: "agency-claim-loop",
180
+ listingId: job.listingId,
181
+ releaseId: job.releaseId,
182
+ targetNodeId: job.targetNodeId,
183
+ version: job.version,
184
+ },
185
+ });
186
+ }
187
+ }
188
+ }
@@ -0,0 +1,32 @@
1
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core";
2
+ import type { ClawHiveCloudApi } from "../client.js";
3
+ export type AgentPanelClaimLoopLogger = {
4
+ warn: (message: string) => void;
5
+ };
6
+ export type AgentPanelClaimLoopOptions = {
7
+ api: ClawHiveCloudApi;
8
+ pluginApi: OpenClawPluginApi;
9
+ pluginNodeId: string;
10
+ userId: string;
11
+ logger?: AgentPanelClaimLoopLogger;
12
+ idlePollMs?: number;
13
+ retryPollMs?: number;
14
+ };
15
+ export declare class AgentPanelClaimLoop {
16
+ private readonly options;
17
+ private timer;
18
+ private wakeTimer;
19
+ private wakePending;
20
+ private claiming;
21
+ private running;
22
+ private activeRun;
23
+ private lastError;
24
+ constructor(options: AgentPanelClaimLoopOptions);
25
+ start(): void;
26
+ stop(): Promise<void>;
27
+ getLastError(): unknown;
28
+ wake(): void;
29
+ private schedule;
30
+ private tick;
31
+ private processTurn;
32
+ }
@@ -0,0 +1,118 @@
1
+ import { DEFAULT_ACTIVE_POLL_MS, DEFAULT_IDLE_POLL_MS, DEFAULT_RETRY_POLL_MS, jitterPollDelay, } from "../claimPolling.js";
2
+ import { clawhiveRuntimeStore } from "../runtime.js";
3
+ import { executePanelTurn } from "./executor.js";
4
+ export class AgentPanelClaimLoop {
5
+ options;
6
+ timer = null;
7
+ wakeTimer = null;
8
+ wakePending = false;
9
+ claiming = false;
10
+ running = false;
11
+ activeRun = null;
12
+ lastError = null;
13
+ constructor(options) {
14
+ this.options = options;
15
+ }
16
+ start() {
17
+ if (this.running)
18
+ return;
19
+ this.running = true;
20
+ void this.tick(true);
21
+ }
22
+ async stop() {
23
+ this.running = false;
24
+ if (this.timer) {
25
+ clearTimeout(this.timer);
26
+ this.timer = null;
27
+ }
28
+ if (this.wakeTimer) {
29
+ clearTimeout(this.wakeTimer);
30
+ this.wakeTimer = null;
31
+ }
32
+ this.wakePending = false;
33
+ if (this.activeRun) {
34
+ await this.activeRun;
35
+ }
36
+ }
37
+ getLastError() {
38
+ return this.lastError;
39
+ }
40
+ wake() {
41
+ if (!this.running)
42
+ return;
43
+ this.wakePending = true;
44
+ if (this.timer) {
45
+ clearTimeout(this.timer);
46
+ this.timer = null;
47
+ }
48
+ if (this.wakeTimer)
49
+ return;
50
+ this.wakeTimer = setTimeout(() => {
51
+ this.wakeTimer = null;
52
+ if (!this.running || !this.wakePending) {
53
+ return;
54
+ }
55
+ this.wakePending = false;
56
+ void this.tick(false);
57
+ }, 25);
58
+ }
59
+ schedule(delayMs) {
60
+ if (!this.running)
61
+ return;
62
+ const nextDelayMs = jitterPollDelay(delayMs);
63
+ this.timer = setTimeout(() => {
64
+ this.timer = null;
65
+ void this.tick(false);
66
+ }, nextDelayMs);
67
+ }
68
+ async tick(initial) {
69
+ if (!this.running)
70
+ return;
71
+ if (this.claiming) {
72
+ this.wakePending = true;
73
+ return;
74
+ }
75
+ if (this.activeRun) {
76
+ return;
77
+ }
78
+ this.claiming = true;
79
+ try {
80
+ const result = await this.options.api.claimPanelTurn({
81
+ pluginNodeId: this.options.pluginNodeId,
82
+ userId: this.options.userId,
83
+ });
84
+ this.claiming = false;
85
+ if (!result.turn) {
86
+ this.lastError = null;
87
+ this.schedule(this.options.idlePollMs ?? DEFAULT_IDLE_POLL_MS);
88
+ return;
89
+ }
90
+ this.activeRun = this.processTurn(result.turn).finally(() => {
91
+ this.activeRun = null;
92
+ });
93
+ await this.activeRun;
94
+ this.lastError = null;
95
+ this.schedule(DEFAULT_ACTIVE_POLL_MS);
96
+ }
97
+ catch (error) {
98
+ this.lastError = error;
99
+ const reason = error instanceof Error ? error.message : String(error);
100
+ this.options.logger?.warn(`ClawHive panel claim loop failed initial=${initial}: ${reason}`);
101
+ this.schedule(this.options.retryPollMs ?? DEFAULT_RETRY_POLL_MS);
102
+ }
103
+ finally {
104
+ if (this.claiming) {
105
+ this.claiming = false;
106
+ }
107
+ if (this.running && this.wakePending && !this.activeRun) {
108
+ this.wake();
109
+ }
110
+ }
111
+ }
112
+ async processTurn(turn) {
113
+ await executePanelTurn({
114
+ runtime: clawhiveRuntimeStore.getRuntime(),
115
+ turn,
116
+ });
117
+ }
118
+ }
@@ -0,0 +1,8 @@
1
+ import { type ClawHiveRuntime } from "../runtime.js";
2
+ import type { ClaimedPanelTurn } from "./types.js";
3
+ export declare function executePanelTurn(options: {
4
+ runtime: ClawHiveRuntime;
5
+ turn: ClaimedPanelTurn;
6
+ panelistTimeoutMs?: number;
7
+ moderatorTimeoutMs?: number;
8
+ }): Promise<void>;