@engineeros/connector 0.12.4 → 0.12.5
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/bin/engineeros-connector.mjs +17 -14
- package/package.json +1 -1
- package/src/connection.mjs +48 -0
|
@@ -31,7 +31,9 @@ import {
|
|
|
31
31
|
registeredAgents,
|
|
32
32
|
} from "../src/agent-registry.mjs";
|
|
33
33
|
import {
|
|
34
|
+
describeRejectedResponse,
|
|
34
35
|
describeWebSocketError,
|
|
36
|
+
protocolFailureMessage,
|
|
35
37
|
startConnectionWatchdog,
|
|
36
38
|
} from "../src/connection.mjs";
|
|
37
39
|
import { advertisedCapabilities } from "../src/capabilities.mjs";
|
|
@@ -387,7 +389,7 @@ async function submitWorkspaceSnapshot() {
|
|
|
387
389
|
);
|
|
388
390
|
if (!response.ok) {
|
|
389
391
|
throw new Error(
|
|
390
|
-
|
|
392
|
+
await describeRejectedResponse(response, "the workspace"),
|
|
391
393
|
);
|
|
392
394
|
}
|
|
393
395
|
const result = await response.json();
|
|
@@ -422,7 +424,7 @@ async function submitWorkspaceSnapshot() {
|
|
|
422
424
|
} catch (error) {
|
|
423
425
|
snapshotInFlight = false;
|
|
424
426
|
console.error(
|
|
425
|
-
`Workspace assessment failed: ${
|
|
427
|
+
`Workspace assessment failed: ${protocolFailureMessage(error)}`,
|
|
426
428
|
);
|
|
427
429
|
}
|
|
428
430
|
}
|
|
@@ -545,17 +547,18 @@ async function executePrompt(assignment) {
|
|
|
545
547
|
}),
|
|
546
548
|
);
|
|
547
549
|
} catch (error) {
|
|
550
|
+
const message = protocolFailureMessage(error);
|
|
548
551
|
if (!promptState.cancelled && socket.readyState === WebSocket.OPEN) {
|
|
549
552
|
socket.send(
|
|
550
553
|
JSON.stringify({
|
|
551
554
|
type: "prompt.failed",
|
|
552
555
|
prompt_id: promptId,
|
|
553
|
-
message
|
|
556
|
+
message,
|
|
554
557
|
}),
|
|
555
558
|
);
|
|
556
559
|
}
|
|
557
560
|
if (!promptState.cancelled) {
|
|
558
|
-
console.error(
|
|
561
|
+
console.error(message);
|
|
559
562
|
}
|
|
560
563
|
} finally {
|
|
561
564
|
if (activePrompts.get(promptId) === promptState)
|
|
@@ -662,22 +665,23 @@ async function executeAssessment(assignment) {
|
|
|
662
665
|
);
|
|
663
666
|
if (!response.ok) {
|
|
664
667
|
throw new Error(
|
|
665
|
-
|
|
668
|
+
await describeRejectedResponse(response, "the assessment"),
|
|
666
669
|
);
|
|
667
670
|
}
|
|
668
671
|
console.log("Workspace assessment is current in EngineerOS.");
|
|
669
672
|
} catch (error) {
|
|
670
673
|
flushOutput();
|
|
674
|
+
const message = protocolFailureMessage(error);
|
|
671
675
|
if (socket.readyState === WebSocket.OPEN) {
|
|
672
676
|
socket.send(
|
|
673
677
|
JSON.stringify({
|
|
674
678
|
type: "workspace.assessment.failed",
|
|
675
679
|
assessment_id: assessmentId,
|
|
676
|
-
message
|
|
680
|
+
message,
|
|
677
681
|
}),
|
|
678
682
|
);
|
|
679
683
|
}
|
|
680
|
-
console.error(
|
|
684
|
+
console.error(message);
|
|
681
685
|
} finally {
|
|
682
686
|
if (outputTimer) clearTimeout(outputTimer);
|
|
683
687
|
clearInterval(heartbeat);
|
|
@@ -735,10 +739,9 @@ async function execute(assignment) {
|
|
|
735
739
|
body: JSON.stringify(result),
|
|
736
740
|
},
|
|
737
741
|
);
|
|
738
|
-
if (!response.ok)
|
|
739
|
-
throw new Error(
|
|
740
|
-
|
|
741
|
-
);
|
|
742
|
+
if (!response.ok) {
|
|
743
|
+
throw new Error(await describeRejectedResponse(response, "the result"));
|
|
744
|
+
}
|
|
742
745
|
const integration = await applyAcceptedChange(
|
|
743
746
|
config.workspace,
|
|
744
747
|
assignment.base_revision,
|
|
@@ -757,17 +760,17 @@ async function execute(assignment) {
|
|
|
757
760
|
);
|
|
758
761
|
}
|
|
759
762
|
} catch (error) {
|
|
763
|
+
const message = protocolFailureMessage(error);
|
|
760
764
|
if (!active?.cancelled && socket.readyState === WebSocket.OPEN) {
|
|
761
765
|
socket.send(
|
|
762
766
|
JSON.stringify({
|
|
763
767
|
type: "run.failed",
|
|
764
768
|
run_id: runId,
|
|
765
|
-
message
|
|
769
|
+
message,
|
|
766
770
|
}),
|
|
767
771
|
);
|
|
768
772
|
}
|
|
769
|
-
if (!active?.cancelled)
|
|
770
|
-
console.error(error instanceof Error ? error.message : String(error));
|
|
773
|
+
if (!active?.cancelled) console.error(message);
|
|
771
774
|
} finally {
|
|
772
775
|
clearInterval(heartbeat);
|
|
773
776
|
active = null;
|
package/package.json
CHANGED
package/src/connection.mjs
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
const PROTOCOL_FAILURE_MESSAGE_MAX_LENGTH = 2_000;
|
|
2
|
+
const TRUNCATED_FAILURE_SUFFIX = "\n… [truncated by EngineerOS connector]";
|
|
3
|
+
|
|
1
4
|
export function describeWebSocketError(event) {
|
|
2
5
|
return (
|
|
3
6
|
event?.error?.message ||
|
|
@@ -6,6 +9,26 @@ export function describeWebSocketError(event) {
|
|
|
6
9
|
);
|
|
7
10
|
}
|
|
8
11
|
|
|
12
|
+
export function protocolFailureMessage(error) {
|
|
13
|
+
const raw = error instanceof Error ? error.message : String(error ?? "");
|
|
14
|
+
const message =
|
|
15
|
+
raw.trim() || "The connector failed without providing an error detail.";
|
|
16
|
+
const characters = [...message];
|
|
17
|
+
if (characters.length <= PROTOCOL_FAILURE_MESSAGE_MAX_LENGTH) return message;
|
|
18
|
+
const suffix = [...TRUNCATED_FAILURE_SUFFIX];
|
|
19
|
+
return `${characters
|
|
20
|
+
.slice(0, PROTOCOL_FAILURE_MESSAGE_MAX_LENGTH - suffix.length)
|
|
21
|
+
.join("")}${TRUNCATED_FAILURE_SUFFIX}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function describeRejectedResponse(response, subject) {
|
|
25
|
+
const responseBody = await response.text();
|
|
26
|
+
const detail = responseDetail(responseBody);
|
|
27
|
+
return protocolFailureMessage(
|
|
28
|
+
`EngineerOS rejected ${subject} (${response.status})${detail ? `: ${detail}` : "."}`,
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
9
32
|
export function startConnectionWatchdog(
|
|
10
33
|
socket,
|
|
11
34
|
url,
|
|
@@ -24,3 +47,28 @@ export function startConnectionWatchdog(
|
|
|
24
47
|
|
|
25
48
|
return () => clearTimeout(timer);
|
|
26
49
|
}
|
|
50
|
+
|
|
51
|
+
function responseDetail(responseBody) {
|
|
52
|
+
const body = String(responseBody || "").trim();
|
|
53
|
+
if (!body) return "";
|
|
54
|
+
try {
|
|
55
|
+
const parsed = JSON.parse(body);
|
|
56
|
+
if (typeof parsed?.detail === "string") return parsed.detail;
|
|
57
|
+
if (Array.isArray(parsed?.detail)) {
|
|
58
|
+
return parsed.detail.map(validationIssue).filter(Boolean).join("; ");
|
|
59
|
+
}
|
|
60
|
+
} catch {
|
|
61
|
+
// Plain-text server errors are already useful to the operator.
|
|
62
|
+
}
|
|
63
|
+
return body;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function validationIssue(issue) {
|
|
67
|
+
if (typeof issue === "string") return issue;
|
|
68
|
+
if (!issue || typeof issue !== "object") return "";
|
|
69
|
+
const location = Array.isArray(issue.loc) ? issue.loc.join(".") : "";
|
|
70
|
+
const message = typeof issue.msg === "string" ? issue.msg : "";
|
|
71
|
+
const type = typeof issue.type === "string" ? ` (${issue.type})` : "";
|
|
72
|
+
if (!location && !message) return "";
|
|
73
|
+
return `${location ? `${location}: ` : ""}${message}${type}`;
|
|
74
|
+
}
|