@simplr-ai/connect 0.7.2 → 0.7.4
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/dist/index.js +195 -69
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -122,7 +122,7 @@ var KanbanReconciliationError = class extends Error {
|
|
|
122
122
|
};
|
|
123
123
|
var DeferredUpdateError = class extends Error {
|
|
124
124
|
};
|
|
125
|
-
var APP_VERSION =
|
|
125
|
+
var APP_VERSION = "0.7.4";
|
|
126
126
|
var STANDALONE_EXECUTABLE = process.env.SIMPLR_CONNECT_STANDALONE === "true";
|
|
127
127
|
var MANIFEST_PUBLIC_KEY = process.env.SIMPLR_CONNECT_MANIFEST_PUBLIC_KEY || "";
|
|
128
128
|
var HERMES_INSTALL_COMMIT = "542e146b055f0d43767ac43cdb9e78054b240263";
|
|
@@ -130,9 +130,11 @@ var SIMPLR_MCP_VERSION = "2.3.0";
|
|
|
130
130
|
var SIMPLR_MCP_CONFIGURATION_VERSION = `operations@${SIMPLR_MCP_VERSION}`;
|
|
131
131
|
var managedProcesses = /* @__PURE__ */ new Map();
|
|
132
132
|
var hermesRuns = /* @__PURE__ */ new Map();
|
|
133
|
-
var
|
|
133
|
+
var hermesRunStreams = /* @__PURE__ */ new Map();
|
|
134
|
+
var hermesRunApprovals = /* @__PURE__ */ new Map();
|
|
134
135
|
var activeCommandIds = /* @__PURE__ */ new Set();
|
|
135
136
|
var commandJournalMutation = Promise.resolve();
|
|
137
|
+
var hermesTraceMutation = Promise.resolve();
|
|
136
138
|
var serviceExecutableSnapshot;
|
|
137
139
|
function stateDirectory() {
|
|
138
140
|
if (platform() === "darwin")
|
|
@@ -165,6 +167,9 @@ function encryptedHermesCredentialPath() {
|
|
|
165
167
|
function commandJournalPath() {
|
|
166
168
|
return join2(stateDirectory(), "commands.json");
|
|
167
169
|
}
|
|
170
|
+
function hermesTracePath() {
|
|
171
|
+
return join2(stateDirectory(), "hermes-traces.json");
|
|
172
|
+
}
|
|
168
173
|
function serviceLogPath() {
|
|
169
174
|
return join2(stateDirectory(), "connect.log");
|
|
170
175
|
}
|
|
@@ -818,6 +823,62 @@ async function removeCommandJournalEntry(commandId) {
|
|
|
818
823
|
commandJournalMutation = mutation.catch(() => void 0);
|
|
819
824
|
await mutation;
|
|
820
825
|
}
|
|
826
|
+
async function loadHermesTraces() {
|
|
827
|
+
try {
|
|
828
|
+
return JSON.parse(await readFile(hermesTracePath(), "utf8"));
|
|
829
|
+
} catch {
|
|
830
|
+
return {};
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
async function saveHermesTraces(traces) {
|
|
834
|
+
await mkdir(stateDirectory(), { recursive: true, mode: 448 });
|
|
835
|
+
const retained = Object.fromEntries(Object.entries(traces).sort(([, left], [, right]) => Date.parse(right.last_event_at) - Date.parse(left.last_event_at)).slice(0, 25));
|
|
836
|
+
const temporaryPath = `${hermesTracePath()}.${process.pid}.tmp`;
|
|
837
|
+
await writeFile(temporaryPath, `${JSON.stringify(retained, null, 2)}
|
|
838
|
+
`, { encoding: "utf8", mode: 384 });
|
|
839
|
+
if (platform() !== "win32") await chmod(temporaryPath, 384);
|
|
840
|
+
await rename(temporaryPath, hermesTracePath());
|
|
841
|
+
}
|
|
842
|
+
async function updateHermesTrace(command, state, runId, update, event) {
|
|
843
|
+
const mutation = hermesTraceMutation.then(async () => {
|
|
844
|
+
const traces = await loadHermesTraces();
|
|
845
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
846
|
+
const existing = traces[command.id];
|
|
847
|
+
const events = event ? [...existing?.events || [], event].slice(-40) : existing?.events || [];
|
|
848
|
+
traces[command.id] = {
|
|
849
|
+
...existing,
|
|
850
|
+
...update,
|
|
851
|
+
command_id: command.id,
|
|
852
|
+
organization_id: state.organization_id,
|
|
853
|
+
workstation_id: state.workstation_id,
|
|
854
|
+
run_id: runId,
|
|
855
|
+
status: update.status || existing?.status || "running",
|
|
856
|
+
current_action: update.current_action || existing?.current_action || "Starting Hermes",
|
|
857
|
+
next_step: update.next_step || existing?.next_step || "Waiting for the first local activity",
|
|
858
|
+
last_event_at: event?.created_at || update.last_event_at || existing?.last_event_at || now,
|
|
859
|
+
supported: update.supported ?? existing?.supported ?? true,
|
|
860
|
+
events
|
|
861
|
+
};
|
|
862
|
+
await saveHermesTraces(traces);
|
|
863
|
+
});
|
|
864
|
+
hermesTraceMutation = mutation.catch(() => void 0);
|
|
865
|
+
await mutation;
|
|
866
|
+
}
|
|
867
|
+
function localTraceText(value, maximumLength = 500) {
|
|
868
|
+
if (typeof value !== "string") return "";
|
|
869
|
+
return value.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, " ").replace(/\s+/g, " ").trim().slice(0, maximumLength);
|
|
870
|
+
}
|
|
871
|
+
function hermesTraceEvent(runId, sequence, type, title, detail, timestamp, durationMs) {
|
|
872
|
+
const seconds = typeof timestamp === "number" && Number.isFinite(timestamp) && timestamp > 0 && timestamp < 864e10 ? timestamp : Date.now() / 1e3;
|
|
873
|
+
return {
|
|
874
|
+
id: `${runId}:${sequence}`,
|
|
875
|
+
type,
|
|
876
|
+
title: localTraceText(title, 160),
|
|
877
|
+
...detail ? { detail: localTraceText(detail) } : {},
|
|
878
|
+
created_at: new Date(seconds * 1e3).toISOString(),
|
|
879
|
+
...durationMs === void 0 ? {} : { duration_ms: durationMs }
|
|
880
|
+
};
|
|
881
|
+
}
|
|
821
882
|
function credentialService(workstationId) {
|
|
822
883
|
return `simplr-connect:${workstationId}`;
|
|
823
884
|
}
|
|
@@ -1188,76 +1249,94 @@ async function hermesRequest(state, path, options = {}) {
|
|
|
1188
1249
|
throw new Error(`Hermes request failed (${response.status})`);
|
|
1189
1250
|
return await response.json();
|
|
1190
1251
|
}
|
|
1191
|
-
async function
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
Accept: "text/event-stream"
|
|
1203
|
-
},
|
|
1204
|
-
signal: controller.signal
|
|
1205
|
-
}
|
|
1206
|
-
);
|
|
1207
|
-
if (!response.ok || !response.body) {
|
|
1208
|
-
clearTimeout(startupTimeout);
|
|
1209
|
-
controller.abort();
|
|
1210
|
-
return {};
|
|
1211
|
-
}
|
|
1212
|
-
stream = {
|
|
1213
|
-
controller,
|
|
1214
|
-
reader: response.body.getReader(),
|
|
1215
|
-
decoder: new TextDecoder(),
|
|
1216
|
-
buffered: "",
|
|
1217
|
-
startup_timeout: startupTimeout
|
|
1218
|
-
};
|
|
1219
|
-
hermesApprovalStreams.set(runId, stream);
|
|
1252
|
+
async function streamHermesRunEvents(state, command, runId) {
|
|
1253
|
+
const controller = new AbortController();
|
|
1254
|
+
hermesRunStreams.set(runId, controller);
|
|
1255
|
+
const token = await loadHermesCredential(state);
|
|
1256
|
+
const response = await fetch(
|
|
1257
|
+
`http://127.0.0.1:8642/p/${hermesProfile(state.organization_id)}/v1/runs/${encodeURIComponent(runId)}/events`,
|
|
1258
|
+
{ headers: { Authorization: `Bearer ${token}`, Accept: "text/event-stream" }, signal: controller.signal }
|
|
1259
|
+
);
|
|
1260
|
+
if (!response.ok || !response.body) {
|
|
1261
|
+
await updateHermesTrace(command, state, runId, { supported: false, current_action: "Hermes is running", next_step: "Live detail is unavailable; local status polling remains active" });
|
|
1262
|
+
return;
|
|
1220
1263
|
}
|
|
1264
|
+
const reader = response.body.getReader();
|
|
1265
|
+
const decoder = new TextDecoder();
|
|
1266
|
+
let buffered = "";
|
|
1267
|
+
let sequence = 0;
|
|
1221
1268
|
try {
|
|
1222
1269
|
while (true) {
|
|
1223
|
-
const
|
|
1224
|
-
if (
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1270
|
+
const chunk = await reader.read();
|
|
1271
|
+
if (chunk.done) break;
|
|
1272
|
+
buffered += decoder.decode(chunk.value, { stream: true }).replace(/\r\n/g, "\n");
|
|
1273
|
+
let boundary = buffered.indexOf("\n\n");
|
|
1274
|
+
while (boundary >= 0) {
|
|
1275
|
+
const record = buffered.slice(0, boundary);
|
|
1276
|
+
buffered = buffered.slice(boundary + 2);
|
|
1277
|
+
boundary = buffered.indexOf("\n\n");
|
|
1278
|
+
const data = record.split("\n").filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trim()).join("\n");
|
|
1279
|
+
if (!data) continue;
|
|
1280
|
+
let raw;
|
|
1281
|
+
try {
|
|
1282
|
+
const parsed = JSON.parse(data);
|
|
1283
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) continue;
|
|
1284
|
+
raw = parsed;
|
|
1285
|
+
} catch {
|
|
1286
|
+
continue;
|
|
1287
|
+
}
|
|
1288
|
+
const eventType = localTraceText(raw.event, 80);
|
|
1289
|
+
const rawTool = localTraceText(raw.tool, 100);
|
|
1290
|
+
const tool = /^[a-zA-Z0-9_.:-]{1,100}$/.test(rawTool) ? rawTool : "Hermes tool";
|
|
1291
|
+
sequence += 1;
|
|
1292
|
+
if (eventType === "reasoning.available") {
|
|
1293
|
+
const detail = localTraceText(raw.text);
|
|
1294
|
+
if (!detail) continue;
|
|
1295
|
+
await updateHermesTrace(command, state, runId, { current_action: "Reviewing the plan", next_step: detail, blocker: void 0 }, hermesTraceEvent(runId, sequence, "reasoning", "Reasoning summary", detail, raw.timestamp));
|
|
1296
|
+
} else if (eventType === "tool.started") {
|
|
1297
|
+
const preview = localTraceText(raw.preview);
|
|
1298
|
+
await updateHermesTrace(command, state, runId, { current_action: `Running ${tool}`, next_step: `Waiting for ${tool} to finish`, blocker: void 0 }, hermesTraceEvent(runId, sequence, "tool", `Started ${tool}`, preview || void 0, raw.timestamp));
|
|
1299
|
+
} else if (eventType === "tool.completed") {
|
|
1300
|
+
const duration = typeof raw.duration === "number" && Number.isFinite(raw.duration) ? Math.max(0, Math.round(raw.duration * 1e3)) : void 0;
|
|
1301
|
+
const failed = raw.error === true;
|
|
1302
|
+
await updateHermesTrace(command, state, runId, { current_action: failed ? `${tool} reported an error` : `Finished ${tool}`, next_step: "Hermes is deciding the next action", ...failed ? { blocker: `${tool} reported an error` } : { blocker: void 0 } }, hermesTraceEvent(runId, sequence, failed ? "error" : "tool", failed ? `${tool} failed` : `Finished ${tool}`, void 0, raw.timestamp, duration));
|
|
1303
|
+
} else if (eventType === "approval.request") {
|
|
1304
|
+
const approvalCommand = localTraceText(raw.command, 1e3);
|
|
1305
|
+
if (approvalCommand) {
|
|
1306
|
+
hermesRunApprovals.set(runId, {
|
|
1307
|
+
approval_command: approvalCommand,
|
|
1308
|
+
approval_tool: tool,
|
|
1309
|
+
approval_fingerprint: createHash("sha256").update(JSON.stringify({ run_id: runId, tool, command: approvalCommand })).digest("hex"),
|
|
1310
|
+
approval_policy_decision: "approval_required"
|
|
1311
|
+
});
|
|
1312
|
+
}
|
|
1313
|
+
await updateHermesTrace(command, state, runId, { status: "waiting_approval", current_action: "Waiting for your approval", next_step: `Approve or reject ${tool}`, blocker: "Human approval is required" }, hermesTraceEvent(runId, sequence, "approval", "Approval required", approvalCommand || tool, raw.timestamp));
|
|
1314
|
+
} else if (["run.completed", "run.failed", "run.cancelled"].includes(eventType)) {
|
|
1315
|
+
const failed = eventType === "run.failed";
|
|
1316
|
+
const cancelled = eventType === "run.cancelled";
|
|
1317
|
+
const status = failed ? "failed" : cancelled ? "cancelled" : "completed";
|
|
1318
|
+
const title = failed ? "Hermes run failed" : cancelled ? "Hermes run stopped" : "Hermes run completed";
|
|
1319
|
+
await updateHermesTrace(command, state, runId, { status, current_action: title, next_step: failed ? "Review the failure and decide whether to retry" : cancelled ? "Continue in Chat or start a new run" : "Review the result and pull request", ...failed ? { blocker: localTraceText(raw.error, 300) || "Hermes reported a failure" } : { blocker: void 0 } }, hermesTraceEvent(runId, sequence, failed ? "error" : "success", title, failed ? localTraceText(raw.error, 300) : void 0, raw.timestamp));
|
|
1320
|
+
}
|
|
1229
1321
|
}
|
|
1230
|
-
const record = stream.buffered.slice(0, boundary);
|
|
1231
|
-
stream.buffered = stream.buffered.slice(boundary + 2);
|
|
1232
|
-
const data = record.split("\n").filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trim()).join("\n");
|
|
1233
|
-
if (!data) continue;
|
|
1234
|
-
const event = JSON.parse(data);
|
|
1235
|
-
if (event.event !== "approval.request") continue;
|
|
1236
|
-
clearTimeout(stream.startup_timeout);
|
|
1237
|
-
const tool = typeof event.tool === "string" && /^[a-zA-Z0-9_.:-]{1,100}$/.test(event.tool) ? event.tool : "protected tool";
|
|
1238
|
-
const command = typeof event.command === "string" ? event.command.trim().slice(0, 1e3) : "";
|
|
1239
|
-
if (!command) return {};
|
|
1240
|
-
const fingerprint = createHash("sha256").update(JSON.stringify({ run_id: runId, tool, command })).digest("hex");
|
|
1241
|
-
return {
|
|
1242
|
-
approval_command: command,
|
|
1243
|
-
approval_tool: tool,
|
|
1244
|
-
approval_fingerprint: fingerprint,
|
|
1245
|
-
approval_policy_decision: "approval_required"
|
|
1246
|
-
};
|
|
1247
1322
|
}
|
|
1248
|
-
}
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
return {};
|
|
1323
|
+
} finally {
|
|
1324
|
+
await reader.cancel().catch(() => void 0);
|
|
1325
|
+
if (hermesRunStreams.get(runId) === controller) hermesRunStreams.delete(runId);
|
|
1252
1326
|
}
|
|
1253
1327
|
}
|
|
1254
|
-
function
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1328
|
+
async function readHermesApproval(runId) {
|
|
1329
|
+
for (let attempt = 0; attempt < 20; attempt += 1) {
|
|
1330
|
+
const approval = hermesRunApprovals.get(runId);
|
|
1331
|
+
if (approval) return approval;
|
|
1332
|
+
await new Promise((resolve) => setTimeout(resolve, 250));
|
|
1333
|
+
}
|
|
1334
|
+
return {};
|
|
1335
|
+
}
|
|
1336
|
+
function closeHermesRunStream(runId) {
|
|
1337
|
+
hermesRunStreams.get(runId)?.abort();
|
|
1338
|
+
hermesRunStreams.delete(runId);
|
|
1339
|
+
hermesRunApprovals.delete(runId);
|
|
1261
1340
|
}
|
|
1262
1341
|
async function waitForProcess(child) {
|
|
1263
1342
|
return new Promise((resolve, reject) => {
|
|
@@ -2038,6 +2117,22 @@ async function monitorHermesRun(state, command, runId, startedAt) {
|
|
|
2038
2117
|
started_at: startedAt
|
|
2039
2118
|
};
|
|
2040
2119
|
hermesRuns.set(runId, run);
|
|
2120
|
+
await updateHermesTrace(command, state, runId, {
|
|
2121
|
+
status: "running",
|
|
2122
|
+
current_action: "Starting Hermes",
|
|
2123
|
+
next_step: "Waiting for the first local activity",
|
|
2124
|
+
blocker: void 0,
|
|
2125
|
+
supported: true
|
|
2126
|
+
}, hermesTraceEvent(runId, 0, "status", "Hermes run started", void 0, Date.now() / 1e3));
|
|
2127
|
+
const traceStream = streamHermesRunEvents(state, command, runId).catch(async () => {
|
|
2128
|
+
if (hermesRunStreams.has(runId)) {
|
|
2129
|
+
await updateHermesTrace(command, state, runId, {
|
|
2130
|
+
supported: false,
|
|
2131
|
+
current_action: "Hermes is running",
|
|
2132
|
+
next_step: "Live detail is unavailable; local status polling remains active"
|
|
2133
|
+
});
|
|
2134
|
+
}
|
|
2135
|
+
});
|
|
2041
2136
|
let lastReportedStatus;
|
|
2042
2137
|
let consecutivePollFailures = 0;
|
|
2043
2138
|
try {
|
|
@@ -2061,6 +2156,13 @@ async function monitorHermesRun(state, command, runId, startedAt) {
|
|
|
2061
2156
|
}
|
|
2062
2157
|
if (status.status === "completed") {
|
|
2063
2158
|
const output = status.output || "Hermes completed the task";
|
|
2159
|
+
await updateHermesTrace(command, state, runId, {
|
|
2160
|
+
status: "completed",
|
|
2161
|
+
current_action: "Hermes run completed",
|
|
2162
|
+
next_step: "Review the result and pull request",
|
|
2163
|
+
blocker: void 0,
|
|
2164
|
+
last_event_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
2165
|
+
});
|
|
2064
2166
|
await updateCommandJournal({
|
|
2065
2167
|
command_id: command.id,
|
|
2066
2168
|
type: command.type,
|
|
@@ -2089,7 +2191,7 @@ async function monitorHermesRun(state, command, runId, startedAt) {
|
|
|
2089
2191
|
started_at: startedAt,
|
|
2090
2192
|
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
2091
2193
|
});
|
|
2092
|
-
const approval = run.status === "waiting_approval" ? await readHermesApproval(
|
|
2194
|
+
const approval = run.status === "waiting_approval" ? await readHermesApproval(runId).catch(() => ({})) : {};
|
|
2093
2195
|
if (run.status === "waiting_approval" && approval.approval_fingerprint) {
|
|
2094
2196
|
await updateCommandJournal({
|
|
2095
2197
|
command_id: command.id,
|
|
@@ -2132,8 +2234,19 @@ async function monitorHermesRun(state, command, runId, startedAt) {
|
|
|
2132
2234
|
throw new Error(
|
|
2133
2235
|
"Hermes run exceeded the 30 minute monitoring window and was stopped"
|
|
2134
2236
|
);
|
|
2237
|
+
} catch (error) {
|
|
2238
|
+
const message = error instanceof Error ? error.message : "Hermes run failed";
|
|
2239
|
+
const cancelled = /cancelled|stopped/i.test(message);
|
|
2240
|
+
await updateHermesTrace(command, state, runId, {
|
|
2241
|
+
status: cancelled ? "cancelled" : "failed",
|
|
2242
|
+
current_action: cancelled ? "Hermes run stopped" : "Hermes run failed",
|
|
2243
|
+
next_step: cancelled ? "Continue in Chat or start a new run" : "Review the failure and decide whether to retry",
|
|
2244
|
+
...cancelled ? { blocker: void 0 } : { blocker: localTraceText(message, 300) }
|
|
2245
|
+
}, hermesTraceEvent(runId, Date.now(), cancelled ? "status" : "error", cancelled ? "Hermes run stopped" : "Hermes run failed", cancelled ? void 0 : message, Date.now() / 1e3));
|
|
2246
|
+
throw error;
|
|
2135
2247
|
} finally {
|
|
2136
|
-
|
|
2248
|
+
closeHermesRunStream(runId);
|
|
2249
|
+
await traceStream;
|
|
2137
2250
|
hermesRuns.delete(runId);
|
|
2138
2251
|
}
|
|
2139
2252
|
}
|
|
@@ -2517,7 +2630,7 @@ function dispatchCommand(state, command, inventoryAlreadySynced) {
|
|
|
2517
2630
|
);
|
|
2518
2631
|
if (run) {
|
|
2519
2632
|
void (async () => {
|
|
2520
|
-
const approval = run.status === "waiting_approval" ? await readHermesApproval(
|
|
2633
|
+
const approval = run.status === "waiting_approval" ? await readHermesApproval(run.id).catch(() => ({})) : {};
|
|
2521
2634
|
await reportCommandProgress(
|
|
2522
2635
|
state,
|
|
2523
2636
|
command.id,
|
|
@@ -3361,6 +3474,19 @@ async function main() {
|
|
|
3361
3474
|
token
|
|
3362
3475
|
);
|
|
3363
3476
|
process.stdout.write(`${JSON.stringify(overview)}
|
|
3477
|
+
`);
|
|
3478
|
+
return;
|
|
3479
|
+
}
|
|
3480
|
+
if (command === "work-order-traces") {
|
|
3481
|
+
const organizationId = argument("--organization-id");
|
|
3482
|
+
if (!isUuid(organizationId))
|
|
3483
|
+
throw new Error("Use: simplr-connect work-order-traces --organization-id <uuid>");
|
|
3484
|
+
const state = await loadState();
|
|
3485
|
+
const connection = state.connections.find((item) => item.organization_id === organizationId);
|
|
3486
|
+
if (!connection) throw new Error("Organization is not connected");
|
|
3487
|
+
await hermesTraceMutation;
|
|
3488
|
+
const traces = Object.values(await loadHermesTraces()).filter((trace) => trace.organization_id === connection.organization_id && trace.workstation_id === connection.workstation_id).sort((left, right) => Date.parse(right.last_event_at) - Date.parse(left.last_event_at));
|
|
3489
|
+
process.stdout.write(`${JSON.stringify({ traces, updated_at: (/* @__PURE__ */ new Date()).toISOString() })}
|
|
3364
3490
|
`);
|
|
3365
3491
|
return;
|
|
3366
3492
|
}
|
|
@@ -3466,7 +3592,7 @@ async function main() {
|
|
|
3466
3592
|
return;
|
|
3467
3593
|
}
|
|
3468
3594
|
process.stdout.write(
|
|
3469
|
-
"Simplr Connect\n\nCommands:\n wizard\n enroll --api-url <url> --code <code> [--setup-hermes] [--install-service]\n hermes-setup\n status\n service-install\n repair\n update-check\n update\n sync\n watch\n run -- <ai-command> [arguments]\n"
|
|
3595
|
+
"Simplr Connect\n\nCommands:\n wizard\n enroll --api-url <url> --code <code> [--setup-hermes] [--install-service]\n hermes-setup\n status\n overview --organization-id <uuid>\n work-order-traces --organization-id <uuid>\n service-install\n repair\n update-check\n update\n sync\n watch\n run -- <ai-command> [arguments]\n"
|
|
3470
3596
|
);
|
|
3471
3597
|
}
|
|
3472
3598
|
main().catch(async (error) => {
|