@engineeros/connector 0.8.6 → 0.8.8
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 +2 -1
- package/bin/engineeros-connector.mjs +23 -8
- package/package.json +1 -1
- package/src/config.mjs +30 -0
- package/src/runner.mjs +37 -16
package/README.md
CHANGED
|
@@ -40,10 +40,11 @@ An empty or document-only folder establishes a greenfield baseline. A code-beari
|
|
|
40
40
|
## Reconnect
|
|
41
41
|
|
|
42
42
|
```sh
|
|
43
|
-
npx @engineeros/connector start --workspace .
|
|
43
|
+
npx --yes @engineeros/connector@latest start --workspace .
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
Credentials are stored per workspace under `~/.engineeros/connectors` with owner-only permissions where supported.
|
|
47
|
+
If a new pairing command is accidentally run from the same folder against the same EngineerOS server, the connector reuses this saved identity instead of creating another baseline assessment.
|
|
47
48
|
|
|
48
49
|
## Run Goals
|
|
49
50
|
|
|
@@ -3,7 +3,9 @@ import os from "node:os";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import {
|
|
5
5
|
assessmentResultUrl,
|
|
6
|
+
connectorResumeCredentials,
|
|
6
7
|
loadConfig,
|
|
8
|
+
mergePairedConfig,
|
|
7
9
|
resultUrl,
|
|
8
10
|
saveConfig,
|
|
9
11
|
socketUrl,
|
|
@@ -59,6 +61,7 @@ if (command === "status") {
|
|
|
59
61
|
|
|
60
62
|
let config;
|
|
61
63
|
let firstMessage;
|
|
64
|
+
let existingConfig;
|
|
62
65
|
if (command === "pair") {
|
|
63
66
|
const pairingCode = positional[0];
|
|
64
67
|
if (!pairingCode)
|
|
@@ -81,11 +84,13 @@ if (command === "pair") {
|
|
|
81
84
|
flags.name ||
|
|
82
85
|
`${os.hostname()} - ${path.basename(path.resolve(flags.workspace || process.cwd()))}`,
|
|
83
86
|
};
|
|
87
|
+
existingConfig = await loadConfig(config.workspace);
|
|
84
88
|
firstMessage = {
|
|
85
89
|
type: "pair",
|
|
86
90
|
pairing_code: pairingCode,
|
|
87
91
|
name: config.name,
|
|
88
92
|
capabilities: {},
|
|
93
|
+
...connectorResumeCredentials(existingConfig, config.server_url),
|
|
89
94
|
};
|
|
90
95
|
} else if (command === "start") {
|
|
91
96
|
config = await loadConfig(flags.workspace || process.cwd());
|
|
@@ -157,11 +162,14 @@ async function connect() {
|
|
|
157
162
|
const message = JSON.parse(String(event.data));
|
|
158
163
|
if (message.type === "paired") {
|
|
159
164
|
clearConnectionWatchdog?.();
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
+
const reusedConnector =
|
|
166
|
+
existingConfig?.connector_id === message.connector.id;
|
|
167
|
+
config = mergePairedConfig(
|
|
168
|
+
config,
|
|
169
|
+
existingConfig,
|
|
170
|
+
message.connector.id,
|
|
171
|
+
message.token,
|
|
172
|
+
);
|
|
165
173
|
await saveConfig(config);
|
|
166
174
|
firstMessage = {
|
|
167
175
|
type: "authenticate",
|
|
@@ -169,7 +177,11 @@ async function connect() {
|
|
|
169
177
|
token: config.token,
|
|
170
178
|
capabilities,
|
|
171
179
|
};
|
|
172
|
-
console.log(
|
|
180
|
+
console.log(
|
|
181
|
+
reusedConnector
|
|
182
|
+
? `Reconnected existing workspace connector ${config.connector_id}; assessment history is preserved.`
|
|
183
|
+
: `Paired. Connector ${config.connector_id} is online.`,
|
|
184
|
+
);
|
|
173
185
|
reconnectDelay = 1_000;
|
|
174
186
|
startPings();
|
|
175
187
|
if (config.onboarding_pending) void submitWorkspaceSnapshot();
|
|
@@ -259,13 +271,16 @@ async function connect() {
|
|
|
259
271
|
console.error(`EngineerOS: ${message.message}`);
|
|
260
272
|
}
|
|
261
273
|
});
|
|
262
|
-
socket.addEventListener("close", () => {
|
|
274
|
+
socket.addEventListener("close", (event) => {
|
|
263
275
|
clearConnectionWatchdog?.();
|
|
264
276
|
clearInterval(pingTimer);
|
|
265
277
|
if (active?.kind === "prompt") {
|
|
266
278
|
active.cancelled = true;
|
|
267
279
|
void stopProcess(active.child);
|
|
268
280
|
}
|
|
281
|
+
if (event.code === 4001 && active?.kind === "assessment") {
|
|
282
|
+
void stopProcess(active.child);
|
|
283
|
+
}
|
|
269
284
|
if (connectionRejected) {
|
|
270
285
|
stopped = true;
|
|
271
286
|
console.error(
|
|
@@ -416,7 +431,7 @@ async function executePrompt(assignment) {
|
|
|
416
431
|
lastProgressMessage = message;
|
|
417
432
|
sendPromptProgress(promptId, message);
|
|
418
433
|
};
|
|
419
|
-
sendPromptProgress(promptId, "
|
|
434
|
+
sendPromptProgress(promptId, "Agent started this request");
|
|
420
435
|
console.log(
|
|
421
436
|
`Answering ${assignment.purpose || "project"} prompt with ${codingAgent.name}.`,
|
|
422
437
|
);
|
package/package.json
CHANGED
package/src/config.mjs
CHANGED
|
@@ -24,6 +24,36 @@ export function socketUrl(value) {
|
|
|
24
24
|
return url.toString();
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
export function connectorResumeCredentials(config, serverUrl) {
|
|
28
|
+
if (
|
|
29
|
+
!config?.connector_id ||
|
|
30
|
+
!config.token ||
|
|
31
|
+
config.server_url !== serverUrl
|
|
32
|
+
) {
|
|
33
|
+
return {};
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
existing_connector_id: config.connector_id,
|
|
37
|
+
existing_token: config.token,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function mergePairedConfig(
|
|
42
|
+
requestedConfig,
|
|
43
|
+
existingConfig,
|
|
44
|
+
connectorId,
|
|
45
|
+
token,
|
|
46
|
+
) {
|
|
47
|
+
const preserved =
|
|
48
|
+
existingConfig?.connector_id === connectorId ? existingConfig : {};
|
|
49
|
+
return {
|
|
50
|
+
...preserved,
|
|
51
|
+
...requestedConfig,
|
|
52
|
+
connector_id: connectorId,
|
|
53
|
+
token,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
27
57
|
export function resultUrl(websocketUrl, connectorId, runId) {
|
|
28
58
|
const url = new URL(websocketUrl);
|
|
29
59
|
url.protocol = url.protocol === "wss:" ? "https:" : "http:";
|
package/src/runner.mjs
CHANGED
|
@@ -587,9 +587,9 @@ export function promptProgressMessage(event) {
|
|
|
587
587
|
if (event.type === "item.completed" && event.item?.type === "agent_message") {
|
|
588
588
|
return "Preparing the response";
|
|
589
589
|
}
|
|
590
|
-
if (event.type === "agent.connected") return "
|
|
590
|
+
if (event.type === "agent.connected") return "Agent connected";
|
|
591
591
|
if (event.type === "acp.tool_call" || event.type === "acp.tool_call_update") {
|
|
592
|
-
return "
|
|
592
|
+
return "Agent is inspecting the workspace";
|
|
593
593
|
}
|
|
594
594
|
if (event.type === "acp.agent_message_chunk") return "Preparing the response";
|
|
595
595
|
return null;
|
|
@@ -597,15 +597,15 @@ export function promptProgressMessage(event) {
|
|
|
597
597
|
|
|
598
598
|
export function promptQueueMessage(activeKind) {
|
|
599
599
|
if (activeKind === "assessment") {
|
|
600
|
-
return "Queued:
|
|
600
|
+
return "Queued: agent is finishing the workspace assessment";
|
|
601
601
|
}
|
|
602
602
|
if (activeKind === "goal") {
|
|
603
|
-
return "Queued:
|
|
603
|
+
return "Queued: agent is finishing an active Goal";
|
|
604
604
|
}
|
|
605
605
|
if (activeKind === "prompt") {
|
|
606
|
-
return "Queued:
|
|
606
|
+
return "Queued: agent is finishing another request";
|
|
607
607
|
}
|
|
608
|
-
return "
|
|
608
|
+
return "Agent accepted the request";
|
|
609
609
|
}
|
|
610
610
|
|
|
611
611
|
function assessmentCommandMilestone(command) {
|
|
@@ -882,22 +882,29 @@ export function codexExecutionArgs({
|
|
|
882
882
|
if (profile.reasoning_effort) {
|
|
883
883
|
optionArgs.push(
|
|
884
884
|
"--config",
|
|
885
|
-
|
|
885
|
+
codexConfigArgument(
|
|
886
|
+
`model_reasoning_effort=${tomlLiteralString(profile.reasoning_effort)}`,
|
|
887
|
+
),
|
|
886
888
|
);
|
|
887
889
|
}
|
|
888
890
|
if (mcpServer) {
|
|
891
|
+
const mcpArgs = [
|
|
892
|
+
mcpServer.connectorBin,
|
|
893
|
+
"mcp",
|
|
894
|
+
"--workspace",
|
|
895
|
+
mcpServer.workspace,
|
|
896
|
+
"--run-id",
|
|
897
|
+
mcpServer.runId,
|
|
898
|
+
];
|
|
889
899
|
optionArgs.push(
|
|
890
900
|
"--config",
|
|
891
|
-
|
|
901
|
+
codexConfigArgument(
|
|
902
|
+
`mcp_servers.engineeros.command=${tomlLiteralString(process.execPath)}`,
|
|
903
|
+
),
|
|
892
904
|
"--config",
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
"--workspace",
|
|
897
|
-
mcpServer.workspace,
|
|
898
|
-
"--run-id",
|
|
899
|
-
mcpServer.runId,
|
|
900
|
-
])}`,
|
|
905
|
+
codexConfigArgument(
|
|
906
|
+
`mcp_servers.engineeros.args=[${mcpArgs.map(tomlLiteralString).join(",")}]`,
|
|
907
|
+
),
|
|
901
908
|
);
|
|
902
909
|
}
|
|
903
910
|
return previousSessionId
|
|
@@ -905,6 +912,20 @@ export function codexExecutionArgs({
|
|
|
905
912
|
: ["exec", ...optionArgs, "--sandbox", sandbox, "-C", workspace, "-"];
|
|
906
913
|
}
|
|
907
914
|
|
|
915
|
+
function tomlLiteralString(value) {
|
|
916
|
+
const text = String(value);
|
|
917
|
+
if (text.includes("'''")) {
|
|
918
|
+
throw new Error(
|
|
919
|
+
"Codex configuration values cannot contain three consecutive apostrophes.",
|
|
920
|
+
);
|
|
921
|
+
}
|
|
922
|
+
return `'''${text}'''`;
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
function codexConfigArgument(override) {
|
|
926
|
+
return process.platform === "win32" ? `"${override}"` : override;
|
|
927
|
+
}
|
|
928
|
+
|
|
908
929
|
function launchAgentProcess(
|
|
909
930
|
workspace,
|
|
910
931
|
prompt,
|