bopodev-agent-sdk 0.1.19 → 0.1.22
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/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-typecheck.log +1 -1
- package/dist/contracts/src/index.d.ts +20 -0
- package/package.json +2 -2
- package/src/adapters.ts +91 -5
- package/src/runtime.ts +23 -0
- package/.turbo/turbo-lint.log +0 -4
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
-
> bopodev-agent-sdk@0.1.
|
|
3
|
+
> bopodev-agent-sdk@0.1.22 build /Users/danielkrusenstrahle/Documents/Projects/Monorepo/bopodev/packages/agent-sdk
|
|
4
4
|
> tsc -p tsconfig.json --emitDeclarationOnly
|
|
5
5
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
|
|
2
|
-
> bopodev-agent-sdk@0.1.
|
|
2
|
+
> bopodev-agent-sdk@0.1.20 typecheck /Users/danielkrusenstrahle/Documents/Projects/Monorepo/bopodev/packages/agent-sdk
|
|
3
3
|
> tsc -p tsconfig.json --noEmit
|
|
4
4
|
|
|
@@ -1701,6 +1701,26 @@ export declare const AgentCreateRequestSchema: z.ZodObject<{
|
|
|
1701
1701
|
heartbeatCron: z.ZodString;
|
|
1702
1702
|
monthlyBudgetUsd: z.ZodNumber;
|
|
1703
1703
|
canHireAgents: z.ZodDefault<z.ZodBoolean>;
|
|
1704
|
+
sourceIssueId: z.ZodOptional<z.ZodString>;
|
|
1705
|
+
sourceIssueIds: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1706
|
+
delegationIntent: z.ZodOptional<z.ZodObject<{
|
|
1707
|
+
intentType: z.ZodLiteral<"agent_hiring_request">;
|
|
1708
|
+
requestedRole: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1709
|
+
requestedName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1710
|
+
requestedManagerAgentId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1711
|
+
requestedProviderType: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
1712
|
+
claude_code: "claude_code";
|
|
1713
|
+
codex: "codex";
|
|
1714
|
+
cursor: "cursor";
|
|
1715
|
+
opencode: "opencode";
|
|
1716
|
+
gemini_cli: "gemini_cli";
|
|
1717
|
+
openai_api: "openai_api";
|
|
1718
|
+
anthropic_api: "anthropic_api";
|
|
1719
|
+
http: "http";
|
|
1720
|
+
shell: "shell";
|
|
1721
|
+
}>>>;
|
|
1722
|
+
requestedRuntimeModel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1723
|
+
}, z.core.$strip>>;
|
|
1704
1724
|
requestApproval: z.ZodDefault<z.ZodBoolean>;
|
|
1705
1725
|
runtimeConfig: z.ZodDefault<z.ZodObject<{
|
|
1706
1726
|
runtimeCommand: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bopodev-agent-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.22",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"types": "src/index.ts",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"bopodev-contracts": "0.1.
|
|
9
|
+
"bopodev-contracts": "0.1.22"
|
|
10
10
|
},
|
|
11
11
|
"scripts": {
|
|
12
12
|
"build": "tsc -p tsconfig.json --emitDeclarationOnly",
|
package/src/adapters.ts
CHANGED
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
type DirectApiProvider
|
|
26
26
|
} from "./runtime-http";
|
|
27
27
|
import { homedir } from "node:os";
|
|
28
|
-
import { join, resolve } from "node:path";
|
|
28
|
+
import { basename, join, resolve } from "node:path";
|
|
29
29
|
|
|
30
30
|
function summarizeWork(context: HeartbeatContext) {
|
|
31
31
|
if (context.workItems.length === 0) {
|
|
@@ -660,6 +660,21 @@ export async function testAdapterEnvironment(
|
|
|
660
660
|
level: "info",
|
|
661
661
|
message: `Command is executable: ${command}`
|
|
662
662
|
});
|
|
663
|
+
const providerMismatch = detectProviderCommandMismatch(providerType, command);
|
|
664
|
+
if (providerMismatch) {
|
|
665
|
+
checks.push({
|
|
666
|
+
code: "command_provider_mismatch",
|
|
667
|
+
level: "error",
|
|
668
|
+
message: `Command '${command}' does not match selected provider '${providerType}'.`,
|
|
669
|
+
detail: `The command appears to be for provider '${providerMismatch}'. Select the matching provider or change the command.`
|
|
670
|
+
});
|
|
671
|
+
return {
|
|
672
|
+
providerType,
|
|
673
|
+
status: "fail",
|
|
674
|
+
testedAt: new Date().toISOString(),
|
|
675
|
+
checks
|
|
676
|
+
};
|
|
677
|
+
}
|
|
663
678
|
|
|
664
679
|
if (providerType === "http") {
|
|
665
680
|
return { providerType, status: "pass", testedAt: new Date().toISOString(), checks };
|
|
@@ -687,12 +702,12 @@ export async function testAdapterEnvironment(
|
|
|
687
702
|
message: "Environment probe succeeded."
|
|
688
703
|
});
|
|
689
704
|
} else {
|
|
690
|
-
const detail =
|
|
691
|
-
const
|
|
705
|
+
const detail = summarizeProbeFailureDetail(probe.stdout, probe.stderr);
|
|
706
|
+
const rawEvidence = `${probe.stderr}\n${probe.stdout}`.toLowerCase();
|
|
692
707
|
if (
|
|
693
708
|
providerType === "codex" &&
|
|
694
|
-
|
|
695
|
-
(
|
|
709
|
+
rawEvidence.includes("401 unauthorized") &&
|
|
710
|
+
(rawEvidence.includes("missing bearer") || rawEvidence.includes("authentication"))
|
|
696
711
|
) {
|
|
697
712
|
checks.push({
|
|
698
713
|
code: "codex_auth_required",
|
|
@@ -724,6 +739,77 @@ export async function testAdapterEnvironment(
|
|
|
724
739
|
};
|
|
725
740
|
}
|
|
726
741
|
|
|
742
|
+
function detectProviderCommandMismatch(providerType: AgentProviderType, command: string) {
|
|
743
|
+
const normalized = basename(command).toLowerCase();
|
|
744
|
+
const known: Record<Exclude<AgentProviderType, "http" | "shell" | "openai_api" | "anthropic_api">, string[]> = {
|
|
745
|
+
claude_code: ["claude", "claude.exe", "claude.cmd"],
|
|
746
|
+
codex: ["codex", "codex.exe", "codex.cmd"],
|
|
747
|
+
cursor: ["cursor", "cursor.exe", "cursor.cmd"],
|
|
748
|
+
opencode: ["opencode", "opencode.exe", "opencode.cmd"],
|
|
749
|
+
gemini_cli: ["gemini", "gemini.exe", "gemini.cmd"]
|
|
750
|
+
};
|
|
751
|
+
const expected = known[providerType as keyof typeof known];
|
|
752
|
+
if (!expected) {
|
|
753
|
+
return null;
|
|
754
|
+
}
|
|
755
|
+
if (expected.includes(normalized)) {
|
|
756
|
+
return null;
|
|
757
|
+
}
|
|
758
|
+
for (const [candidateProvider, aliases] of Object.entries(known)) {
|
|
759
|
+
if (candidateProvider === providerType) {
|
|
760
|
+
continue;
|
|
761
|
+
}
|
|
762
|
+
if (aliases.includes(normalized)) {
|
|
763
|
+
return candidateProvider;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
return null;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
function summarizeProbeFailureDetail(stdout: string, stderr: string) {
|
|
770
|
+
const lines = [...stderr.split(/\r?\n/), ...stdout.split(/\r?\n/)].map((line) => line.trim()).filter(Boolean);
|
|
771
|
+
for (const line of lines) {
|
|
772
|
+
const parsed = parseJsonRecord(line);
|
|
773
|
+
if (!parsed) {
|
|
774
|
+
return line.replace(/\s+/g, " ").slice(0, 500);
|
|
775
|
+
}
|
|
776
|
+
const type = asString(parsed.type);
|
|
777
|
+
const subtype = asString(parsed.subtype);
|
|
778
|
+
if (
|
|
779
|
+
type === "thread.started" ||
|
|
780
|
+
type === "item.started" ||
|
|
781
|
+
type === "item.completed" ||
|
|
782
|
+
(type === "system" && subtype === "init")
|
|
783
|
+
) {
|
|
784
|
+
continue;
|
|
785
|
+
}
|
|
786
|
+
if (type === "turn.failed") {
|
|
787
|
+
const failed = asString(parsed.error) || asString(parsed.message) || asString(parsed.result);
|
|
788
|
+
if (failed) {
|
|
789
|
+
return failed.replace(/\s+/g, " ").slice(0, 500);
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
const message = asString(parsed.message) || asString(parsed.result) || asString(parsed.error);
|
|
793
|
+
if (message) {
|
|
794
|
+
return message.replace(/\s+/g, " ").slice(0, 500);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
return "";
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
function asString(value: unknown) {
|
|
801
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
function parseJsonRecord(line: string) {
|
|
805
|
+
try {
|
|
806
|
+
const parsed = JSON.parse(line) as unknown;
|
|
807
|
+
return typeof parsed === "object" && parsed !== null ? (parsed as Record<string, unknown>) : null;
|
|
808
|
+
} catch {
|
|
809
|
+
return null;
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
|
|
727
813
|
export function createSkippedResult(providerLabel: string, providerKey: string, context: HeartbeatContext): AdapterExecutionResult {
|
|
728
814
|
return {
|
|
729
815
|
status: "skipped",
|
package/src/runtime.ts
CHANGED
|
@@ -1403,6 +1403,7 @@ async function ensureCodexSkillsInjected(skillsSourceDir: string, env: NodeJS.Pr
|
|
|
1403
1403
|
const codexHome = resolveCodexHome(env);
|
|
1404
1404
|
const targetRoot = join(codexHome, SKILLS_DIR_NAME);
|
|
1405
1405
|
await mkdir(targetRoot, { recursive: true });
|
|
1406
|
+
await pruneBrokenSkillSymlinks(targetRoot);
|
|
1406
1407
|
|
|
1407
1408
|
const entries = await readdir(skillsSourceDir, { withFileTypes: true });
|
|
1408
1409
|
for (const entry of entries) {
|
|
@@ -1505,6 +1506,7 @@ async function withProviderRuntimeIsolation(
|
|
|
1505
1506
|
|
|
1506
1507
|
async function ensureSkillsInjectedAtHome(skillsSourceDir: string, targetRoot: string) {
|
|
1507
1508
|
await mkdir(targetRoot, { recursive: true });
|
|
1509
|
+
await pruneBrokenSkillSymlinks(targetRoot);
|
|
1508
1510
|
const entries = await readdir(skillsSourceDir, { withFileTypes: true });
|
|
1509
1511
|
for (const entry of entries) {
|
|
1510
1512
|
if (!entry.isDirectory()) continue;
|
|
@@ -1517,6 +1519,27 @@ async function ensureSkillsInjectedAtHome(skillsSourceDir: string, targetRoot: s
|
|
|
1517
1519
|
}
|
|
1518
1520
|
}
|
|
1519
1521
|
|
|
1522
|
+
async function pruneBrokenSkillSymlinks(targetRoot: string) {
|
|
1523
|
+
try {
|
|
1524
|
+
const entries = await readdir(targetRoot, { withFileTypes: true });
|
|
1525
|
+
for (const entry of entries) {
|
|
1526
|
+
const target = join(targetRoot, entry.name);
|
|
1527
|
+
const stats = await lstat(target).catch(() => null);
|
|
1528
|
+
if (!stats?.isSymbolicLink()) {
|
|
1529
|
+
continue;
|
|
1530
|
+
}
|
|
1531
|
+
const resolves = await access(target)
|
|
1532
|
+
.then(() => true)
|
|
1533
|
+
.catch(() => false);
|
|
1534
|
+
if (!resolves) {
|
|
1535
|
+
await rm(target, { recursive: true, force: true }).catch(() => undefined);
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
} catch {
|
|
1539
|
+
return;
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1520
1543
|
function resolveManagedCodexHome(env: NodeJS.ProcessEnv) {
|
|
1521
1544
|
const managedRoot = resolveManagedCodexHomeRoot(env);
|
|
1522
1545
|
const companyId = sanitizePathSegment(resolveControlPlaneEnvValue(env, "COMPANY_ID"));
|
package/.turbo/turbo-lint.log
DELETED