@engineeros/connector 0.8.8 → 0.9.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.
package/src/runner.mjs CHANGED
@@ -12,6 +12,7 @@ import path from "node:path";
12
12
  import { promisify } from "node:util";
13
13
  import { deflateRaw } from "node:zlib";
14
14
  import { launchAcpAgent } from "./acp-client.mjs";
15
+ import { buildAgentHarnessPrompt } from "./agent-harness.mjs";
15
16
 
16
17
  const deflate = promisify(deflateRaw);
17
18
  const MAX_ARCHIVE_BYTES = 25 * 1024 * 1024;
@@ -117,7 +118,15 @@ export async function executeAssignment(assignment, config, callbacks) {
117
118
  );
118
119
  const verifier = launchAgentProcess(
119
120
  runWorkspace,
120
- verificationPrompt(assignment, committed.revision, committed.changedFiles),
121
+ buildAgentHarnessPrompt({
122
+ agentRole: "verification",
123
+ prompt: verificationPrompt(
124
+ assignment,
125
+ committed.revision,
126
+ committed.changedFiles,
127
+ ),
128
+ sandboxMode: "read-only",
129
+ }),
121
130
  "read-only",
122
131
  config,
123
132
  callbacks,
@@ -485,7 +494,12 @@ export async function executeConnectedPrompt(assignment, config, callbacks) {
485
494
  callbacks,
486
495
  execution.profile,
487
496
  previousSessionId,
497
+ {
498
+ persistentAcp: true,
499
+ sessionKey: execution.sessionKey,
500
+ },
488
501
  );
502
+ callbacks.onController?.(controller);
489
503
  callbacks.onProcess?.(controller.child);
490
504
  const completed = await controller.completed;
491
505
  const content = completed.finalMessage.trim();
@@ -510,7 +524,7 @@ export async function inspectCodingAgent(config, workspace = process.cwd()) {
510
524
  return {
511
525
  protocol: "acp",
512
526
  name: config.agent_name || path.basename(config.agent_command),
513
- version: "ACP v1",
527
+ version: config.agent_version || "ACP v1",
514
528
  };
515
529
  }
516
530
  const codex = await inspectCodexCli(workspace);
@@ -595,17 +609,35 @@ export function promptProgressMessage(event) {
595
609
  return null;
596
610
  }
597
611
 
598
- export function promptQueueMessage(activeKind) {
599
- if (activeKind === "assessment") {
600
- return "Queued: agent is finishing the workspace assessment";
612
+ export function promptStreamEvent(event) {
613
+ if (!event || typeof event !== "object") return null;
614
+ if (
615
+ event.type === "acp.agent_message_chunk" &&
616
+ event.update?.content?.type === "text"
617
+ ) {
618
+ return { kind: "message", delta: event.update.content.text };
619
+ }
620
+ if (event.type === "acp.agent_thought_chunk") {
621
+ return {
622
+ kind: "thought",
623
+ message: "Agent is reasoning through the request",
624
+ };
601
625
  }
602
- if (activeKind === "goal") {
603
- return "Queued: agent is finishing an active Goal";
626
+ if (event.type === "acp.plan") {
627
+ return { kind: "plan", message: "Agent updated the working plan" };
604
628
  }
605
- if (activeKind === "prompt") {
606
- return "Queued: agent is finishing another request";
629
+ if (event.type === "acp.tool_call" || event.type === "acp.tool_call_update") {
630
+ return {
631
+ kind: "tool",
632
+ message: event.update?.title || "Agent is inspecting the workspace",
633
+ status: event.update?.status,
634
+ };
607
635
  }
608
- return "Agent accepted the request";
636
+ if (event.type === "item.completed" && event.item?.type === "agent_message") {
637
+ return { kind: "message", delta: event.item.text };
638
+ }
639
+ const message = promptProgressMessage(event);
640
+ return message ? { kind: "status", message } : null;
609
641
  }
610
642
 
611
643
  function assessmentCommandMilestone(command) {
@@ -633,8 +665,8 @@ function assessmentCommandMilestone(command) {
633
665
  }
634
666
 
635
667
  export function connectorExecution(assignment) {
636
- const prompt = assignment?.prompt_markdown;
637
- if (typeof prompt !== "string" || !prompt.trim()) {
668
+ const rawPrompt = assignment?.prompt_markdown;
669
+ if (typeof rawPrompt !== "string" || !rawPrompt.trim()) {
638
670
  throw new Error("EngineerOS assignment is missing prompt_markdown.");
639
671
  }
640
672
  const sandboxMode = assignment?.sandbox_mode;
@@ -653,13 +685,26 @@ export function connectorExecution(assignment) {
653
685
  "EngineerOS assignment has an unsupported reasoning effort.",
654
686
  );
655
687
  }
688
+ const agentRole = assignment?.agent_role;
689
+ const prompt = buildAgentHarnessPrompt({
690
+ agentRole,
691
+ prompt: rawPrompt,
692
+ sandboxMode,
693
+ });
656
694
  return {
657
695
  prompt,
696
+ agentRole,
658
697
  sandboxMode,
659
698
  sessionKey:
660
- typeof assignment.session_key === "string" && assignment.session_key.trim()
699
+ typeof assignment.session_key === "string" &&
700
+ assignment.session_key.trim()
661
701
  ? assignment.session_key.trim()
662
- : `project-${String(assignment.purpose || "general").toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 80)}`,
702
+ : `project-${String(agentRole)}-${String(
703
+ assignment.purpose || "general",
704
+ )
705
+ .toLowerCase()
706
+ .replace(/[^a-z0-9]+/g, "-")
707
+ .slice(0, 80)}`,
663
708
  profile: {
664
709
  ...(model ? { model } : {}),
665
710
  ...(reasoningEffort ? { reasoning_effort: reasoningEffort } : {}),
@@ -830,7 +875,10 @@ function launchCodexProcess(
830
875
  if (!line.trim()) continue;
831
876
  try {
832
877
  const event = JSON.parse(line);
833
- if (event.type === "thread.started" && typeof event.thread_id === "string") {
878
+ if (
879
+ event.type === "thread.started" &&
880
+ typeof event.thread_id === "string"
881
+ ) {
834
882
  sessionId = event.thread_id;
835
883
  }
836
884
  if (
@@ -860,8 +908,14 @@ function launchCodexProcess(
860
908
  const completed = new Promise((resolve, reject) => {
861
909
  child.once("error", reject);
862
910
  child.once("close", (code) => {
863
- if (code === 0 && sessionId) resolve({ output: output.slice(-20_000), finalMessage, sessionId });
864
- else if (code === 0) reject(new Error("Codex completed without announcing a resumable session id."));
911
+ if (code === 0 && sessionId)
912
+ resolve({ output: output.slice(-20_000), finalMessage, sessionId });
913
+ else if (code === 0)
914
+ reject(
915
+ new Error(
916
+ "Codex completed without announcing a resumable session id.",
917
+ ),
918
+ );
865
919
  else reject(new Error(codexFailureMessage(output, code)));
866
920
  });
867
921
  });
@@ -937,12 +991,13 @@ function launchAgentProcess(
937
991
  mcpContext,
938
992
  ) {
939
993
  if (config.agent_protocol === "acp") {
940
- if (profile.model || profile.reasoning_effort) {
941
- throw new Error(
942
- "This ACP coding agent does not advertise execution-profile support.",
943
- );
944
- }
945
- return launchAcpAgent(workspace, prompt, config, callbacks);
994
+ return launchAcpAgent(workspace, prompt, config, callbacks, {
995
+ persistent: mcpContext?.persistentAcp === true,
996
+ sessionKey: mcpContext?.sessionKey,
997
+ previousSessionId,
998
+ sandbox,
999
+ profile,
1000
+ });
946
1001
  }
947
1002
  return launchCodexProcess(
948
1003
  workspace,
@@ -0,0 +1,12 @@
1
+ ---
2
+ name: change-planning
3
+ description: Produce a decision-complete implementation plan grounded in the connected repository.
4
+ ---
5
+
6
+ # Change Planning
7
+
8
+ 1. Inspect current behavior, ownership boundaries, call paths, tests, and project instructions before proposing changes.
9
+ 2. Define the intended outcome, affected components, non-goals, risks, and proof of completion.
10
+ 3. Resolve questions answerable from the repository. Label only genuinely unavailable facts as assumptions.
11
+ 4. Sequence bounded implementation steps with the files or symbols each step affects and the verification it requires.
12
+ 5. Stay read-only and hand off a plan that an implementation Agent can execute without rediscovering the problem.
@@ -0,0 +1,12 @@
1
+ ---
2
+ name: change-verification
3
+ description: Independently verify a completed change against its explicit proof contract.
4
+ ---
5
+
6
+ # Change Verification
7
+
8
+ 1. Inspect the exact supplied revision, changed paths, Goal boundaries, constraints, and every Proof item.
9
+ 2. Run or inspect each check independently; do not rely on the implementation Agent's claims.
10
+ 3. Stay read-only. Do not repair failures, edit files, install dependencies, commit, or push.
11
+ 4. Mark a check passed only when directly observed evidence matches its expected result.
12
+ 5. Return the requested structured verification report with concise commands, exit codes, and evidence.
@@ -0,0 +1,12 @@
1
+ ---
2
+ name: codebase-research
3
+ description: Investigate a connected repository and answer from directly observed evidence.
4
+ ---
5
+
6
+ # Codebase Research
7
+
8
+ 1. Define the exact question and inspect the smallest relevant surface first.
9
+ 2. Trace callers, dependencies, data flow, configuration, and tests when they materially affect the answer.
10
+ 3. Separate observed facts from inferences and cite concrete repository paths for important claims.
11
+ 4. Stay read-only. Do not install, generate, edit, delete, commit, or start long-running services.
12
+ 5. Return the answer first, followed by supporting evidence and unresolved gaps only when they matter.
@@ -0,0 +1,12 @@
1
+ ---
2
+ name: goal-execution
3
+ description: Implement one bounded EngineerOS Goal and prove the resulting behavior.
4
+ ---
5
+
6
+ # Goal Execution
7
+
8
+ 1. Read the complete Goal packet, repository instructions, current Git state, and relevant implementation paths.
9
+ 2. Implement the smallest coherent change that satisfies the included outcome and constraints.
10
+ 3. Preserve unrelated user changes and stay inside the stated boundary; stop only for a genuine missing authority or prerequisite.
11
+ 4. Run focused checks while working, then the proportionate final tests, lint, type checks, or build required by the Goal.
12
+ 5. Do not commit or push. EngineerOS creates the isolated run commit after the implementation completes.