grix-connector 1.0.2

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 (211) hide show
  1. package/README.md +149 -0
  2. package/dist/adapter/acp/acp-adapter.js +13 -0
  3. package/dist/adapter/acp/index.js +1 -0
  4. package/dist/adapter/acp/usage-parser.js +1 -0
  5. package/dist/adapter/claude/activity-status-manager.js +1 -0
  6. package/dist/adapter/claude/channel-notification.js +1 -0
  7. package/dist/adapter/claude/claude-adapter.js +15 -0
  8. package/dist/adapter/claude/claude-bridge-server.js +1 -0
  9. package/dist/adapter/claude/claude-tools.js +1 -0
  10. package/dist/adapter/claude/claude-worker-client.js +1 -0
  11. package/dist/adapter/claude/index.js +1 -0
  12. package/dist/adapter/claude/interaction-protocol.js +1 -0
  13. package/dist/adapter/claude/mcp-http-launcher.js +2 -0
  14. package/dist/adapter/claude/model-list.js +1 -0
  15. package/dist/adapter/claude/protocol-contract.js +1 -0
  16. package/dist/adapter/claude/result-timeout.js +1 -0
  17. package/dist/adapter/claude/skill-scanner.js +2 -0
  18. package/dist/adapter/claude/usage-parser.js +3 -0
  19. package/dist/adapter/codewhale/codewhale-adapter.js +6 -0
  20. package/dist/adapter/codewhale/index.js +1 -0
  21. package/dist/adapter/codex/codex-bridge.js +10 -0
  22. package/dist/adapter/codex/codex-trust.js +8 -0
  23. package/dist/adapter/codex/index.js +1 -0
  24. package/dist/adapter/codex/usage-parser.js +1 -0
  25. package/dist/adapter/cursor/cursor-adapter.js +8 -0
  26. package/dist/adapter/cursor/index.js +1 -0
  27. package/dist/adapter/deepseek/deepseek-adapter.js +6 -0
  28. package/dist/adapter/deepseek/index.js +1 -0
  29. package/dist/adapter/index.js +1 -0
  30. package/dist/adapter/opencode/index.js +1 -0
  31. package/dist/adapter/opencode/opencode-adapter.js +8 -0
  32. package/dist/adapter/opencode/opencode-transport.js +5 -0
  33. package/dist/adapter/opencode/opencode-types.js +0 -0
  34. package/dist/adapter/openhuman/index.js +1 -0
  35. package/dist/adapter/openhuman/openhuman-adapter.js +7 -0
  36. package/dist/adapter/openhuman/openhuman-transport.js +1 -0
  37. package/dist/adapter/openhuman/openhuman-types.js +0 -0
  38. package/dist/adapter/pi/index.js +1 -0
  39. package/dist/adapter/pi/pi-adapter.js +10 -0
  40. package/dist/adapter/pi/pi-transport.js +4 -0
  41. package/dist/adapter/pi/pi-types.js +0 -0
  42. package/dist/adapter/pi/usage-parser.js +1 -0
  43. package/dist/adapter/qwen/index.js +1 -0
  44. package/dist/adapter/qwen/qwen-adapter.js +4 -0
  45. package/dist/adapter/types.js +1 -0
  46. package/dist/agent/index.js +1 -0
  47. package/dist/agent/process.js +2 -0
  48. package/dist/aibot/client.js +1 -0
  49. package/dist/aibot/index.js +1 -0
  50. package/dist/aibot/types.js +0 -0
  51. package/dist/bridge/adapter-pool.js +1 -0
  52. package/dist/bridge/bridge.js +10 -0
  53. package/dist/bridge/deferred-events.js +1 -0
  54. package/dist/bridge/event-queue.js +1 -0
  55. package/dist/bridge/index.js +1 -0
  56. package/dist/bridge/respawn-manager.js +1 -0
  57. package/dist/bridge/revoke-handler.js +1 -0
  58. package/dist/bridge/runtime-config.js +1 -0
  59. package/dist/bridge/send-controller.js +1 -0
  60. package/dist/bridge/session-controller.js +9 -0
  61. package/dist/bridge/tool-card-utils.js +1 -0
  62. package/dist/core/access/allowlist-gate.js +1 -0
  63. package/dist/core/access/allowlist-store.js +1 -0
  64. package/dist/core/access/index.js +1 -0
  65. package/dist/core/aibot/client.js +1 -0
  66. package/dist/core/aibot/connection-handle.js +1 -0
  67. package/dist/core/aibot/connection-manager.js +1 -0
  68. package/dist/core/aibot/event-lifecycle-types.js +0 -0
  69. package/dist/core/aibot/index.js +1 -0
  70. package/dist/core/aibot/types.js +0 -0
  71. package/dist/core/config/index.js +1 -0
  72. package/dist/core/config/paths.js +1 -0
  73. package/dist/core/context/channel-context-resolution.js +1 -0
  74. package/dist/core/context/channel-context-store.js +1 -0
  75. package/dist/core/context/index.js +1 -0
  76. package/dist/core/context/transcript-channel-context.js +1 -0
  77. package/dist/core/file-ops/handler.js +1 -0
  78. package/dist/core/file-ops/list-files.js +1 -0
  79. package/dist/core/file-ops/types.js +0 -0
  80. package/dist/core/files/create-folder.js +1 -0
  81. package/dist/core/files/index.js +1 -0
  82. package/dist/core/files/list-files.js +1 -0
  83. package/dist/core/files/list-handler.js +1 -0
  84. package/dist/core/files/types.js +0 -0
  85. package/dist/core/files/utils.js +1 -0
  86. package/dist/core/hooks/hook-signal-store.js +2 -0
  87. package/dist/core/hooks/index.js +1 -0
  88. package/dist/core/log/bridge-event-log.js +2 -0
  89. package/dist/core/log/conversation-log.js +3 -0
  90. package/dist/core/log/index.js +1 -0
  91. package/dist/core/log/logger.js +6 -0
  92. package/dist/core/log/packet-log.js +2 -0
  93. package/dist/core/log/rotation.js +2 -0
  94. package/dist/core/mcp/event-tool-executor.js +1 -0
  95. package/dist/core/mcp/index.js +1 -0
  96. package/dist/core/mcp/internal-api-server.js +1 -0
  97. package/dist/core/mcp/tool-schemas.js +1 -0
  98. package/dist/core/mcp/tools.js +1 -0
  99. package/dist/core/persistence/active-event-store.js +1 -0
  100. package/dist/core/persistence/agent-global-config-store.js +1 -0
  101. package/dist/core/persistence/elicitation-store.js +1 -0
  102. package/dist/core/persistence/event-results-store.js +1 -0
  103. package/dist/core/persistence/permission-store.js +1 -0
  104. package/dist/core/persistence/question-store.js +1 -0
  105. package/dist/core/persistence/session-binding-store.js +1 -0
  106. package/dist/core/protocol/agent-api-media.js +1 -0
  107. package/dist/core/protocol/attachment-file.js +1 -0
  108. package/dist/core/protocol/index.js +1 -0
  109. package/dist/core/protocol/interaction-parser.js +1 -0
  110. package/dist/core/protocol/message-metadata.js +2 -0
  111. package/dist/core/protocol/message-reference.js +2 -0
  112. package/dist/core/protocol/payload-parser.js +11 -0
  113. package/dist/core/protocol/protocol-descriptor.js +1 -0
  114. package/dist/core/protocol/protocol-text.js +1 -0
  115. package/dist/core/provider-quota/index.js +1 -0
  116. package/dist/core/provider-quota/kiro.js +1 -0
  117. package/dist/core/provider-quota/providers.js +1 -0
  118. package/dist/core/provider-quota/types.js +0 -0
  119. package/dist/core/runtime/health.js +1 -0
  120. package/dist/core/runtime/index.js +1 -0
  121. package/dist/core/runtime/pidfile.js +2 -0
  122. package/dist/core/runtime/spawn.js +1 -0
  123. package/dist/core/text-segmentation/index.js +1 -0
  124. package/dist/core/text-segmentation/safe-markdown-stream-segmenter.js +6 -0
  125. package/dist/core/transport/index.js +1 -0
  126. package/dist/core/transport/json-rpc.js +3 -0
  127. package/dist/core/upgrade/npm-upgrader.js +2 -0
  128. package/dist/core/upgrade/upgrade-checker.js +1 -0
  129. package/dist/core/util/client-version.js +1 -0
  130. package/dist/core/util/codex-output-policy.js +1 -0
  131. package/dist/core/util/event-buffer.js +1 -0
  132. package/dist/core/util/index.js +1 -0
  133. package/dist/core/util/json-file.js +2 -0
  134. package/dist/core/util/normalize-string.js +1 -0
  135. package/dist/core/util/quoted-message-stream.js +3 -0
  136. package/dist/grix.js +28 -0
  137. package/dist/index.js +1 -0
  138. package/dist/log.js +3 -0
  139. package/dist/main.js +31 -0
  140. package/dist/manager.js +1 -0
  141. package/dist/mcp/acp-mcp-server.js +5 -0
  142. package/dist/mcp/stdio/server.js +10 -0
  143. package/dist/mcp/stream-http/config.js +1 -0
  144. package/dist/mcp/stream-http/connection-binding.js +1 -0
  145. package/dist/mcp/stream-http/event-tool-executor.js +1 -0
  146. package/dist/mcp/stream-http/gateway.js +1 -0
  147. package/dist/mcp/stream-http/index.js +1 -0
  148. package/dist/mcp/stream-http/security.js +1 -0
  149. package/dist/mcp/stream-http/session-manager.js +1 -0
  150. package/dist/mcp/stream-http/tool-executor.js +1 -0
  151. package/dist/mcp/stream-http/tool-registry.js +1 -0
  152. package/dist/mcp/stream-http/tool-schemas.js +1 -0
  153. package/dist/protocol/acp-client.js +1 -0
  154. package/dist/protocol/event-mapper.js +5 -0
  155. package/dist/protocol/index.js +1 -0
  156. package/dist/runtime/daemon-lock.js +2 -0
  157. package/dist/runtime/service-state.js +2 -0
  158. package/dist/scripts/approve-plan-hook.js +2 -0
  159. package/dist/scripts/elicitation-hook.js +6 -0
  160. package/dist/scripts/lib/read-stdin.js +1 -0
  161. package/dist/scripts/lifecycle-hook.js +2 -0
  162. package/dist/scripts/notification-hook.js +4 -0
  163. package/dist/scripts/permission-hook.js +5 -0
  164. package/dist/scripts/status-line-forwarder.js +2 -0
  165. package/dist/scripts/user-prompt-submit-hook.js +2 -0
  166. package/dist/service/platform-adapter.js +45 -0
  167. package/dist/service/process-control.js +1 -0
  168. package/dist/service/service-install-store.js +1 -0
  169. package/dist/service/service-manager.js +1 -0
  170. package/dist/service/service-paths.js +1 -0
  171. package/dist/session/index.js +1 -0
  172. package/dist/session/manager.js +1 -0
  173. package/dist/transport/index.js +1 -0
  174. package/dist/transport/json-rpc.js +3 -0
  175. package/dist/types/events.js +1 -0
  176. package/dist/types/index.js +1 -0
  177. package/dist/types/protocol.js +0 -0
  178. package/dist/types/session-state.js +0 -0
  179. package/dist/types/usage.js +0 -0
  180. package/openclaw-plugin/index.js +11271 -0
  181. package/openclaw-plugin/skills/grix-admin/SKILL.md +202 -0
  182. package/openclaw-plugin/skills/grix-admin/references/api-contract.md +210 -0
  183. package/openclaw-plugin/skills/grix-egg/SKILL.md +81 -0
  184. package/openclaw-plugin/skills/grix-egg/references/api-contract.md +40 -0
  185. package/openclaw-plugin/skills/grix-group/SKILL.md +164 -0
  186. package/openclaw-plugin/skills/grix-group/references/api-contract.md +97 -0
  187. package/openclaw-plugin/skills/grix-query/SKILL.md +247 -0
  188. package/openclaw-plugin/skills/grix-register/SKILL.md +86 -0
  189. package/openclaw-plugin/skills/grix-register/references/api-contract.md +76 -0
  190. package/openclaw-plugin/skills/grix-register/references/grix-concepts.md +26 -0
  191. package/openclaw-plugin/skills/grix-register/references/handoff-contract.md +24 -0
  192. package/openclaw-plugin/skills/grix-register/references/openclaw-setup.md +6 -0
  193. package/openclaw-plugin/skills/grix-register/references/user-replies.md +25 -0
  194. package/openclaw-plugin/skills/grix-register/scripts/grix_auth.ts +599 -0
  195. package/openclaw-plugin/skills/grix-update/SKILL.md +310 -0
  196. package/openclaw-plugin/skills/grix-update/references/cron-setup.md +56 -0
  197. package/openclaw-plugin/skills/grix-update/references/update-contract.md +149 -0
  198. package/openclaw-plugin/skills/message-send/SKILL.md +197 -0
  199. package/openclaw-plugin/skills/message-unsend/SKILL.md +186 -0
  200. package/openclaw-plugin/skills/message-unsend/flowchart.mermaid +27 -0
  201. package/openclaw-plugin/skills/openclaw-memory-setup/SKILL.md +282 -0
  202. package/openclaw-plugin/skills/openclaw-memory-setup/references/case-study-macpro.md +52 -0
  203. package/openclaw-plugin/skills/openclaw-memory-setup/references/host-readiness.md +147 -0
  204. package/openclaw-plugin/skills/openclaw-memory-setup/scripts/bench_ollama_embeddings.ts +326 -0
  205. package/openclaw-plugin/skills/openclaw-memory-setup/scripts/set_openclaw_memory_model.ts +385 -0
  206. package/openclaw-plugin/skills/openclaw-memory-setup/scripts/survey_host_readiness.ts +294 -0
  207. package/openclaw.plugin.json +24 -0
  208. package/package.json +114 -0
  209. package/scripts/install-guardian.mjs +30 -0
  210. package/scripts/install-guardian.sh +30 -0
  211. package/scripts/upgrade-guardian.sh +98 -0
@@ -0,0 +1,294 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Survey host readiness for Ollama and OpenClaw memory setup.
4
+ *
5
+ * Emits a readable report by default, or JSON with --json.
6
+ */
7
+
8
+ import { accessSync, constants, readFileSync, statSync } from "node:fs";
9
+ import os from "node:os";
10
+ import { dirname, join } from "node:path";
11
+ import { parseArgs } from "node:util";
12
+
13
+ type Report = {
14
+ os: string;
15
+ release: string;
16
+ arch: string;
17
+ shell_context: string;
18
+ cpu_count: number;
19
+ memory_gib: number | null;
20
+ commands: Record<string, string | null>;
21
+ versions: Record<string, string | null>;
22
+ ollama_api: { reachable: boolean; models: string[] };
23
+ recommended_candidates: string[];
24
+ openclaw_install_note: string;
25
+ };
26
+
27
+ function usageText(): string {
28
+ return [
29
+ "Usage:",
30
+ " node scripts/survey_host_readiness.ts [--ollama-host <url>] [--json]",
31
+ "",
32
+ "Options:",
33
+ " --ollama-host <url> Ollama host to probe (default http://127.0.0.1:11434)",
34
+ " --json Emit JSON instead of a readable report",
35
+ ].join("\n");
36
+ }
37
+
38
+ function systemName(): string {
39
+ if (process.platform === "win32") return "Windows";
40
+ if (process.platform === "darwin") return "Darwin";
41
+ if (process.platform === "linux") return "Linux";
42
+ return process.platform;
43
+ }
44
+
45
+ function shellContext(): string {
46
+ if (process.platform === "win32") return "windows-native";
47
+ if (process.platform === "darwin") return "macos-native";
48
+ if (process.platform === "linux") {
49
+ const lowerRelease = os.release().toLowerCase();
50
+ if (lowerRelease.includes("microsoft") || lowerRelease.includes("wsl")) {
51
+ return "wsl";
52
+ }
53
+ try {
54
+ const version = readFileSync("/proc/version", "utf8").toLowerCase();
55
+ if (version.includes("microsoft")) {
56
+ return "wsl";
57
+ }
58
+ } catch {
59
+ // ignore
60
+ }
61
+ return "linux-native";
62
+ }
63
+ return "unknown";
64
+ }
65
+
66
+ function isExecutableFile(path: string): boolean {
67
+ try {
68
+ const stats = statSync(path);
69
+ if (!stats.isFile()) return false;
70
+ if (process.platform === "win32") return true;
71
+ accessSync(path, constants.X_OK);
72
+ return true;
73
+ } catch {
74
+ return false;
75
+ }
76
+ }
77
+
78
+ function commandCandidates(command: string): string[] {
79
+ const normalized = command.trim();
80
+ if (!normalized) return [];
81
+
82
+ const candidates: string[] = [];
83
+ const unixBins = ["/usr/local/bin", "/opt/homebrew/bin", "/usr/bin", "/bin"];
84
+
85
+ if (normalized === "node") {
86
+ candidates.push(process.execPath);
87
+ }
88
+
89
+ if (normalized === "npm") {
90
+ const base = dirname(process.execPath);
91
+ if (process.platform === "win32") {
92
+ candidates.push(join(base, "npm.cmd"), join(base, "npm.exe"));
93
+ } else {
94
+ candidates.push(join(base, "npm"));
95
+ }
96
+ }
97
+
98
+ if (process.platform === "win32") {
99
+ if (normalized === "ollama") {
100
+ candidates.push(
101
+ "C:\\\\Program Files\\\\Ollama\\\\ollama.exe",
102
+ "C:\\\\Program Files (x86)\\\\Ollama\\\\ollama.exe",
103
+ );
104
+ }
105
+ if (normalized === "node") {
106
+ candidates.push("C:\\\\Program Files\\\\nodejs\\\\node.exe", "C:\\\\Program Files (x86)\\\\nodejs\\\\node.exe");
107
+ }
108
+ if (normalized === "npm") {
109
+ candidates.push("C:\\\\Program Files\\\\nodejs\\\\npm.cmd", "C:\\\\Program Files (x86)\\\\nodejs\\\\npm.cmd");
110
+ }
111
+ if (normalized === "openclaw") {
112
+ candidates.push("C:\\\\Program Files\\\\OpenClaw\\\\openclaw.exe", "C:\\\\Program Files (x86)\\\\OpenClaw\\\\openclaw.exe");
113
+ }
114
+ return candidates;
115
+ }
116
+
117
+ for (const dir of unixBins) {
118
+ candidates.push(join(dir, normalized));
119
+ }
120
+ return candidates;
121
+ }
122
+
123
+ function resolveCommandPath(command: string): string | null {
124
+ for (const candidate of commandCandidates(command)) {
125
+ if (isExecutableFile(candidate)) {
126
+ return candidate;
127
+ }
128
+ }
129
+ return null;
130
+ }
131
+
132
+ function commandVersion(command: string, path: string | null): string | null {
133
+ if (!path) return null;
134
+ if (command === "node") {
135
+ return process.version;
136
+ }
137
+ return null;
138
+ }
139
+
140
+ function recommendCandidates(memoryGib: number | null): string[] {
141
+ if (memoryGib === null) {
142
+ return ["embeddinggemma:300m-qat-q8_0", "nomic-embed-text:latest", "qwen3-embedding:0.6b"];
143
+ }
144
+ if (memoryGib < 8) {
145
+ return ["nomic-embed-text:latest", "embeddinggemma:300m-qat-q8_0"];
146
+ }
147
+ if (memoryGib < 32) {
148
+ return ["embeddinggemma:300m-qat-q8_0", "nomic-embed-text:latest", "qwen3-embedding:0.6b"];
149
+ }
150
+ return [
151
+ "embeddinggemma:300m-qat-q8_0",
152
+ "nomic-embed-text:latest",
153
+ "qwen3-embedding:0.6b",
154
+ "qwen3-embedding:latest",
155
+ ];
156
+ }
157
+
158
+ async function fetchWithTimeout(url: string, timeoutMs: number): Promise<Response> {
159
+ const controller = new AbortController();
160
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
161
+ try {
162
+ return await fetch(url, { signal: controller.signal });
163
+ } finally {
164
+ clearTimeout(timer);
165
+ }
166
+ }
167
+
168
+ async function probeOllama(host: string): Promise<{ reachable: boolean; models: string[] }> {
169
+ const url = host.replace(/\/+$/, "") + "/api/tags";
170
+ try {
171
+ const response = await fetchWithTimeout(url, 5000);
172
+ if (!response.ok) {
173
+ return { reachable: false, models: [] };
174
+ }
175
+ const text = await response.text();
176
+ const payload = JSON.parse(text) as { models?: unknown };
177
+ const models = Array.isArray(payload.models) ? payload.models : [];
178
+ const names = models
179
+ .map((item) => (item && typeof item === "object" ? (item as Record<string, unknown>).name : undefined))
180
+ .filter((name): name is string => typeof name === "string");
181
+ return { reachable: true, models: names };
182
+ } catch {
183
+ return { reachable: false, models: [] };
184
+ }
185
+ }
186
+
187
+ async function buildReport(ollamaHost: string): Promise<Report> {
188
+ const memoryGib = os.totalmem() ? os.totalmem() / 1024 / 1024 / 1024 : null;
189
+ const commands: Record<string, string | null> = {};
190
+ const versions: Record<string, string | null> = {};
191
+
192
+ for (const command of ["ollama", "openclaw", "node", "npm"]) {
193
+ const path = resolveCommandPath(command);
194
+ commands[command] = path;
195
+ versions[command] = commandVersion(command, path);
196
+ }
197
+
198
+ commands.openclaw_management = commands.openclaw;
199
+ versions.openclaw_management = versions.openclaw;
200
+
201
+ const ollamaApi = await probeOllama(ollamaHost);
202
+ const osName = systemName();
203
+
204
+ return {
205
+ os: osName,
206
+ release: os.release(),
207
+ arch: os.arch(),
208
+ shell_context: shellContext(),
209
+ cpu_count: os.cpus().length,
210
+ memory_gib: memoryGib === null ? null : Math.round(memoryGib * 100) / 100,
211
+ commands,
212
+ versions,
213
+ ollama_api: ollamaApi,
214
+ recommended_candidates: recommendCandidates(memoryGib === null ? null : memoryGib),
215
+ openclaw_install_note:
216
+ osName === "Windows"
217
+ ? "Use Mac or Linux directly; use WSL on Windows for current official OpenClaw setup."
218
+ : "Use the official Ollama OpenClaw launch flow.",
219
+ };
220
+ }
221
+
222
+ function printText(report: Report, ollamaHost: string): void {
223
+ process.stdout.write("System\n");
224
+ process.stdout.write(` OS: ${report.os} ${report.release}\n`);
225
+ process.stdout.write(` Context: ${report.shell_context}\n`);
226
+ process.stdout.write(` Arch: ${report.arch}\n`);
227
+ process.stdout.write(` CPUs: ${report.cpu_count}\n`);
228
+ process.stdout.write(` RAM GiB: ${report.memory_gib ?? "unknown"}\n\n`);
229
+
230
+ process.stdout.write("Commands\n");
231
+ for (const [command, path] of Object.entries(report.commands)) {
232
+ const version = report.versions[command] ?? null;
233
+ const label = command === "openclaw_management" ? "openclaw management" : command;
234
+ if (path) {
235
+ const suffix = version ? ` (${version})` : "";
236
+ process.stdout.write(` ${label}: ${path}${suffix}\n`);
237
+ } else {
238
+ process.stdout.write(` ${label}: missing\n`);
239
+ }
240
+ }
241
+
242
+ process.stdout.write("\nOllama API\n");
243
+ if (report.ollama_api.reachable) {
244
+ process.stdout.write(` ${ollamaHost}: reachable\n`);
245
+ process.stdout.write(
246
+ ` Models: ${report.ollama_api.models.length ? report.ollama_api.models.join(", ") : "none pulled"}\n`,
247
+ );
248
+ } else {
249
+ process.stdout.write(` ${ollamaHost}: unreachable\n`);
250
+ }
251
+
252
+ process.stdout.write("\nRecommended candidates\n");
253
+ for (const model of report.recommended_candidates) {
254
+ process.stdout.write(` - ${model}\n`);
255
+ }
256
+ process.stdout.write(`\nOpenClaw install note\n ${report.openclaw_install_note}\n`);
257
+ }
258
+
259
+ async function main(): Promise<number> {
260
+ const parsed = parseArgs({
261
+ args: process.argv.slice(2),
262
+ options: {
263
+ "ollama-host": { type: "string", default: "http://127.0.0.1:11434" },
264
+ json: { type: "boolean", default: false },
265
+ help: { type: "boolean", default: false },
266
+ },
267
+ });
268
+
269
+ if (parsed.values.help) {
270
+ process.stdout.write(`${usageText()}\n`);
271
+ return 0;
272
+ }
273
+
274
+ const ollamaHost = String(parsed.values["ollama-host"] ?? "").trim() || "http://127.0.0.1:11434";
275
+ const report = await buildReport(ollamaHost);
276
+
277
+ if (parsed.values.json) {
278
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
279
+ } else {
280
+ printText(report, ollamaHost);
281
+ }
282
+
283
+ return 0;
284
+ }
285
+
286
+ void main()
287
+ .then((code) => {
288
+ process.exitCode = code;
289
+ })
290
+ .catch((err) => {
291
+ const message = err instanceof Error ? err.message : String(err);
292
+ process.stderr.write(`${message}\n`);
293
+ process.exitCode = 1;
294
+ });
@@ -0,0 +1,24 @@
1
+ {
2
+ "id": "grix",
3
+ "version": "0.5.2",
4
+ "skills": [
5
+ "./openclaw-plugin/skills"
6
+ ],
7
+ "channels": [
8
+ "grix"
9
+ ],
10
+ "channelConfigs": {
11
+ "grix": {
12
+ "schema": {
13
+ "type": "object",
14
+ "additionalProperties": true
15
+ },
16
+ "label": "Grix"
17
+ }
18
+ },
19
+ "configSchema": {
20
+ "type": "object",
21
+ "additionalProperties": false,
22
+ "properties": {}
23
+ }
24
+ }
package/package.json ADDED
@@ -0,0 +1,114 @@
1
+ {
2
+ "name": "grix-connector",
3
+ "version": "1.0.2",
4
+ "description": "Connect local AI coding agents (Claude, Codex, Gemini, Qwen, DeepSeek, Cursor, OpenCode, Pi, OpenHuman, Reasonix) to the Grix scheduling platform. Also serves as an OpenClaw plugin for Grix channel transport.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "grix-connector": "dist/grix.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "!dist/**/*.map",
13
+ "!dist/**/*.d.ts",
14
+ "openclaw-plugin",
15
+ "scripts/install-guardian.mjs",
16
+ "scripts/install-guardian.sh",
17
+ "scripts/upgrade-guardian.sh",
18
+ "openclaw.plugin.json"
19
+ ],
20
+ "scripts": {
21
+ "postinstall": "node scripts/install-guardian.mjs",
22
+ "prepublishOnly": "npm run build:all",
23
+ "build": "tsc",
24
+ "build:plugin": "node scripts/build-plugin.mjs",
25
+ "build:all": "npm run build && node scripts/minify-dist.mjs && npm run build:plugin",
26
+ "dev": "npm run build && node dist/grix.js",
27
+ "test": "node --experimental-vm-modules node_modules/vitest/vitest.mjs run",
28
+ "test:watch": "node --experimental-vm-modules node_modules/vitest/vitest.mjs",
29
+ "lint": "tsc --noEmit",
30
+ "start": "node dist/grix.js start",
31
+ "stop": "node dist/grix.js stop",
32
+ "restart": "node dist/grix.js restart",
33
+ "status": "node dist/grix.js status"
34
+ },
35
+ "keywords": [
36
+ "grix",
37
+ "aibot",
38
+ "agent-connector",
39
+ "claude",
40
+ "codex",
41
+ "gemini",
42
+ "qwen",
43
+ "deepseek",
44
+ "cursor",
45
+ "opencode",
46
+ "pi",
47
+ "openhuman",
48
+ "reasonix",
49
+ "acp",
50
+ "agent-client-protocol",
51
+ "mcp",
52
+ "openclaw",
53
+ "openclaw-plugin"
54
+ ],
55
+ "author": "askie",
56
+ "repository": {
57
+ "type": "git",
58
+ "url": "git+https://github.com/askie/grix-connector.git"
59
+ },
60
+ "homepage": "https://github.com/askie/grix-connector#readme",
61
+ "bugs": {
62
+ "url": "https://github.com/askie/grix-connector/issues"
63
+ },
64
+ "license": "MIT",
65
+ "devDependencies": {
66
+ "@types/node": "^25.6.0",
67
+ "@types/ws": "^8.18.1",
68
+ "esbuild": "^0.27.7",
69
+ "fast-check": "^4.8.0",
70
+ "typescript": "^5.7.0",
71
+ "vitest": "^3.0.0"
72
+ },
73
+ "peerDependencies": {
74
+ "openclaw": ">=2026.4.8"
75
+ },
76
+ "peerDependenciesMeta": {
77
+ "openclaw": {
78
+ "optional": true
79
+ }
80
+ },
81
+ "engines": {
82
+ "node": ">=18.0.0"
83
+ },
84
+ "dependencies": {
85
+ "@modelcontextprotocol/sdk": "^1.29.0",
86
+ "extract-zip": "^2.0.1",
87
+ "socket.io-client": "^4.8.3",
88
+ "ws": "^8.20.0"
89
+ },
90
+ "optionalDependencies": {
91
+ "node-pty": "^1.1.0"
92
+ },
93
+ "openclaw": {
94
+ "extensions": [
95
+ "./openclaw-plugin/index.js"
96
+ ],
97
+ "channel": {
98
+ "id": "grix",
99
+ "label": "Grix",
100
+ "selectionLabel": "Grix",
101
+ "docsPath": "/channels/grix",
102
+ "blurb": "Connect OpenClaw to a Grix deployment for website management with mobile PWA support.",
103
+ "aliases": [
104
+ "gr"
105
+ ],
106
+ "order": 90
107
+ },
108
+ "install": {
109
+ "npmSpec": "grix-connector",
110
+ "localPath": ".",
111
+ "defaultChoice": "npm"
112
+ }
113
+ }
114
+ }
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+ // install-guardian — cross-platform npm postinstall script
3
+ // Copies upgrade-guardian.sh to ~/.grix/bin/ (idempotent, won't overwrite existing)
4
+ // On Windows, skips since the guardian is a bash script.
5
+
6
+ import { existsSync, copyFileSync, mkdirSync } from 'node:fs';
7
+ import { join, resolve } from 'node:path';
8
+ import { homedir } from 'node:os';
9
+
10
+ // Guardian is a bash script — skip on Windows entirely
11
+ if (process.platform === 'win32') {
12
+ process.exit(0);
13
+ }
14
+
15
+ const GRIX_HOME = process.env.GRIX_CONNECTOR_HOME || join(homedir(), '.grix');
16
+ const GUARDIAN_DEST = join(GRIX_HOME, 'bin', 'upgrade-guardian.sh');
17
+
18
+ if (existsSync(GUARDIAN_DEST)) {
19
+ process.exit(0);
20
+ }
21
+
22
+ const INIT_CWD = process.env.INIT_CWD || resolve(import.meta.dirname);
23
+ const GUARDIAN_SRC = join(INIT_CWD, 'scripts', 'upgrade-guardian.sh');
24
+
25
+ if (!existsSync(GUARDIAN_SRC)) {
26
+ process.exit(0);
27
+ }
28
+
29
+ mkdirSync(join(GRIX_HOME, 'bin'), { recursive: true });
30
+ copyFileSync(GUARDIAN_SRC, GUARDIAN_DEST);
@@ -0,0 +1,30 @@
1
+ #!/bin/bash
2
+ # install-guardian.sh — npm postinstall script
3
+ # Copies upgrade-guardian.sh to ~/.grix/bin/ (idempotent, won't overwrite existing)
4
+ # This ensures the guardian script exists on first install and survives npm upgrades.
5
+
6
+ set -e
7
+
8
+ GRIX_HOME="${GRIX_CONNECTOR_HOME:-$HOME/.grix}"
9
+ GUARDIAN_DEST="$GRIX_HOME/bin/upgrade-guardian.sh"
10
+
11
+ # Don't overwrite — user may have custom modifications
12
+ if [ -f "$GUARDIAN_DEST" ]; then
13
+ exit 0
14
+ fi
15
+
16
+ # Locate source: INIT_CWD is set by npm to the package root during lifecycle scripts
17
+ GUARDIAN_SRC="${INIT_CWD:-$(dirname "$0")}/scripts/upgrade-guardian.sh"
18
+ if [ ! -f "$GUARDIAN_SRC" ]; then
19
+ # Fallback: try relative to this script
20
+ GUARDIAN_SRC="$(cd "$(dirname "$0")" && pwd)/upgrade-guardian.sh"
21
+ fi
22
+
23
+ if [ ! -f "$GUARDIAN_SRC" ]; then
24
+ echo "grix-connector postinstall: guardian source not found, skipping" >&2
25
+ exit 0
26
+ fi
27
+
28
+ mkdir -p "$GRIX_HOME/bin"
29
+ cp "$GUARDIAN_SRC" "$GUARDIAN_DEST"
30
+ chmod +x "$GUARDIAN_DEST"
@@ -0,0 +1,98 @@
1
+ #!/bin/bash
2
+ # upgrade-guardian.sh — post-upgrade health monitor
3
+ # Started by daemon after npm install, runs as detached background process.
4
+ # Monitors healthz for 90s, rolls back on crash_count >= 3.
5
+ # This file is NOT inside the npm package — installed once to ~/.grix/bin/.
6
+
7
+ GRIX_HOME="${GRIX_CONNECTOR_HOME:-$HOME/.grix}"
8
+ PENDING_FILE="$GRIX_HOME/data/upgrade-pending.json"
9
+ LOCK_FILE="$GRIX_HOME/upgrade-guardian.lock"
10
+ LOG_FILE="$GRIX_HOME/log/upgrade.log"
11
+ MAX_CRASHES=3
12
+ HEALTH_TIMEOUT=90
13
+ HEALTH_PORT_FILE="$GRIX_HOME/data/health-port"
14
+ HEALTH_PORT=$(cat "$HEALTH_PORT_FILE" 2>/dev/null || echo "19579")
15
+ HEALTH_URL="http://127.0.0.1:${HEALTH_PORT}/healthz"
16
+ NPM_PACKAGE="grix-connector"
17
+
18
+ # Ensure directories exist
19
+ mkdir -p "$GRIX_HOME/log" "$GRIX_HOME/data"
20
+
21
+ log() {
22
+ echo "[$(date '+%Y-%m-%dT%H:%M:%S%z')] guardian: $1" >> "$LOG_FILE"
23
+ }
24
+
25
+ # Prevent duplicate guardian instances
26
+ if [ -f "$LOCK_FILE" ]; then
27
+ LOCK_PID=$(cat "$LOCK_FILE" 2>/dev/null)
28
+ if [ -n "$LOCK_PID" ] && kill -0 "$LOCK_PID" 2>/dev/null; then
29
+ exit 0
30
+ fi
31
+ rm -f "$LOCK_FILE"
32
+ fi
33
+ echo $$ > "$LOCK_FILE"
34
+ trap 'rm -f "$LOCK_FILE"' EXIT
35
+
36
+ # Read pending marker
37
+ if [ ! -f "$PENDING_FILE" ]; then
38
+ exit 0
39
+ fi
40
+
41
+ # Extract fields from JSON (portable: no jq dependency)
42
+ FROM_VERSION=$(cat "$PENDING_FILE" | grep -o '"from_version":"[^"]*"' | cut -d'"' -f4)
43
+ TARGET_VERSION=$(cat "$PENDING_FILE" | grep -o '"target_version":"[^"]*"' | cut -d'"' -f4)
44
+ UPGRADED_AT=$(cat "$PENDING_FILE" | grep -o '"upgraded_at":"[^"]*"' | cut -d'"' -f4)
45
+ CRASH_COUNT=$(cat "$PENDING_FILE" | grep -o '"crash_count":[0-9]*' | cut -d: -f2)
46
+ CRASH_COUNT=${CRASH_COUNT:-0}
47
+
48
+ # Validate pending file
49
+ if [ -z "$FROM_VERSION" ]; then
50
+ log "pending file corrupt, missing from_version, removing"
51
+ rm -f "$PENDING_FILE"
52
+ exit 0
53
+ fi
54
+
55
+ log "started: from=$FROM_VERSION target=$TARGET_VERSION crash_count=$CRASH_COUNT"
56
+
57
+ # Wait for old daemon to exit (SIGTERM + shutdown + restart)
58
+ sleep 15
59
+
60
+ # Monitor loop: wait for healthz to return 200
61
+ ELAPSED=0
62
+ while [ $ELAPSED -lt $HEALTH_TIMEOUT ]; do
63
+ if curl -sf "$HEALTH_URL" > /dev/null 2>&1; then
64
+ log "healthz passed, upgrade successful"
65
+ rm -f "$PENDING_FILE"
66
+ exit 0
67
+ fi
68
+ sleep 3
69
+ ELAPSED=$((ELAPSED + 3))
70
+ done
71
+
72
+ # Extra grace period for slow systems
73
+ sleep 15
74
+ if curl -sf "$HEALTH_URL" > /dev/null 2>&1; then
75
+ log "healthz passed (delayed), upgrade successful"
76
+ rm -f "$PENDING_FILE"
77
+ exit 0
78
+ fi
79
+
80
+ # Health check failed
81
+ CRASH_COUNT=$((CRASH_COUNT + 1))
82
+ log "healthz timeout, crash_count=$CRASH_COUNT"
83
+
84
+ if [ $CRASH_COUNT -ge $MAX_CRASHES ]; then
85
+ log "rollback: installing ${NPM_PACKAGE}@${FROM_VERSION}"
86
+ if npm install -g "${NPM_PACKAGE}@${FROM_VERSION}" --prefer-online --no-audit --no-fund >> "$LOG_FILE" 2>&1; then
87
+ log "rollback succeeded"
88
+ rm -f "$PENDING_FILE"
89
+ else
90
+ log "ROLLBACK FAILED — manual intervention required"
91
+ fi
92
+ exit 0
93
+ fi
94
+
95
+ # Under threshold — update crash_count and exit, let process manager restart
96
+ echo "{\"from_version\":\"$FROM_VERSION\",\"target_version\":\"$TARGET_VERSION\",\"upgraded_at\":\"$UPGRADED_AT\",\"crash_count\":$CRASH_COUNT}" > "$PENDING_FILE.tmp"
97
+ mv "$PENDING_FILE.tmp" "$PENDING_FILE"
98
+ log "updated crash_count to $CRASH_COUNT, exiting"