import { describe, expect, it } from "@effect/vitest";
import { ConnectionName, IntegrationSlug, type ArtifactBinding } from "@executor-js/sdk";
import {
extractArtifactRoles,
oldStyleAddressRejection,
resolveArtifactBindings,
resolveCallAddress,
type BindableConnection,
} from "./artifact-bindings";
const connection = (
integration: string,
owner: "user" | "org",
name: string,
): BindableConnection => ({ integration, owner, name });
const binding = (integration: string, owner: "user" | "org", name: string): ArtifactBinding => ({
integration: IntegrationSlug.make(integration),
owner,
connection: ConnectionName.make(name),
});
describe("extractArtifactRoles", () => {
it("reads the implicit role from a bare integration reference", () => {
const roles = extractArtifactRoles(
`function App(){ const q = useQuery(tools.vercel.domains.getDomains.queryOptions({ limit: 100 })); return null; }`,
);
expect(roles).toEqual([{ role: "vercel", integration: "vercel" }]);
});
it("collapses repeated references to one role", () => {
const roles = extractArtifactRoles(
`useQuery(tools.linear.issues.list.queryOptions({}));
useMutation(tools.linear.issues.create.mutationOptions({}));
queryClient.invalidateQueries(tools.linear.issues.list.queryFilter({}));`,
);
expect(roles).toEqual([{ role: "linear", integration: "linear" }]);
});
it("reads explicit roles from the call form, both quote flavours", () => {
const roles = extractArtifactRoles(
`useQuery(tools.linear("prod").issues.list.queryOptions({}));
useQuery(tools.linear('staging').issues.list.queryOptions({}));`,
);
expect(roles).toEqual([
{ role: "prod", integration: "linear" },
{ role: "staging", integration: "linear" },
]);
});
it("mixes implicit and explicit roles across integrations", () => {
const roles = extractArtifactRoles(
`useQuery(tools.vercel.domains.getDomains.queryOptions({}));
useQuery(tools.linear("prod").issues.list.queryOptions({}));
useQuery(tools.github.issues.list.queryOptions({}));`,
);
expect(roles).toEqual([
{ role: "vercel", integration: "vercel" },
{ role: "prod", integration: "linear" },
{ role: "github", integration: "github" },
]);
});
it("ignores executor's own system tool roots", () => {
const roles = extractArtifactRoles(
`tools.search({ query: "x" }); tools.describe.tool({ path: "y" });
tools.executor.coreTools.connections.list({});
useQuery(tools.stripe.charges.list.queryOptions({}));`,
);
expect(roles).toEqual([{ role: "stripe", integration: "stripe" }]);
});
it("ignores references inside comments", () => {
const roles = extractArtifactRoles(
`// useQuery(tools.github.issues.list.queryOptions({}))
/* tools.slack.chat.post */
useQuery(tools.vercel.domains.getDomains.queryOptions({}));`,
);
expect(roles).toEqual([{ role: "vercel", integration: "vercel" }]);
});
it("does not read a property access that merely ends in tools", () => {
expect(extractArtifactRoles(`const x = myTools.github.list();`)).toEqual([]);
expect(extractArtifactRoles(`const x = a.tools.github.list();`)).toEqual([]);
});
it("finds nothing in code that calls no integration", () => {
expect(extractArtifactRoles(`function App(){ return
hi
; }`)).toEqual([]);
});
});
describe("oldStyleAddressRejection", () => {
it("rejects a user-tier address and explains the short form", () => {
const message = oldStyleAddressRejection(
`useQuery(tools.vercel.user.personalVercel.domains.getDomains.queryOptions({}));`,
);
expect(message).toContain("tools.vercel.user.");
expect(message).toContain("tools.vercel.(args)");
expect(message).toContain("connections:");
});
it("rejects an org-tier address", () => {
expect(
oldStyleAddressRejection(`useQuery(tools.inventory.org.main.listItems.queryOptions({}));`),
).toContain("tools.inventory.org.");
});
it("accepts the short form", () => {
expect(
oldStyleAddressRejection(`useQuery(tools.vercel.domains.getDomains.queryOptions({}));`),
).toBeNull();
});
it("accepts the role form", () => {
expect(
oldStyleAddressRejection(`useQuery(tools.linear("prod").issues.list.queryOptions({}));`),
).toBeNull();
});
it("accepts a tool path whose later segments happen to be user or org", () => {
expect(
oldStyleAddressRejection(`useQuery(tools.acme.admin.user.get.queryOptions({}));`),
).toBeNull();
});
it("ignores an old-style address left in a comment", () => {
expect(
oldStyleAddressRejection(`// old: tools.vercel.user.personalVercel.domains.getDomains`),
).toBeNull();
});
});
describe("resolveArtifactBindings", () => {
it("binds a role silently when the author has exactly one connection", () => {
const result = resolveArtifactBindings({
roles: [{ role: "vercel", integration: "vercel" }],
available: [connection("vercel", "user", "personalVercel")],
});
expect(result).toEqual({
ok: true,
bindings: { vercel: { integration: "vercel", owner: "user", connection: "personalVercel" } },
});
});
it("infers each integration independently", () => {
const result = resolveArtifactBindings({
roles: [
{ role: "vercel", integration: "vercel" },
{ role: "linear", integration: "linear" },
],
available: [
connection("vercel", "user", "personalVercel"),
connection("linear", "org", "workspaceLinear"),
],
});
expect(result.ok).toBe(true);
if (!result.ok) return;
expect(result.bindings.linear).toEqual({
integration: "linear",
owner: "org",
connection: "workspaceLinear",
});
});
it("refuses an ambiguous integration and lists the candidates", () => {
const result = resolveArtifactBindings({
roles: [{ role: "linear", integration: "linear" }],
available: [
connection("linear", "org", "linearProd"),
connection("linear", "org", "linearStaging"),
],
});
expect(result.ok).toBe(false);
if (result.ok) return;
expect(result.message).toContain("linear.org.linearProd");
expect(result.message).toContain("linear.org.linearStaging");
expect(result.message).toContain("connections");
});
it("refuses when the integration has no connection at all", () => {
const result = resolveArtifactBindings({
roles: [{ role: "stripe", integration: "stripe" }],
available: [connection("vercel", "user", "personalVercel")],
});
expect(result.ok).toBe(false);
if (result.ok) return;
expect(result.message).toContain("No stripe connection");
});
it("takes a supplied connection over inference", () => {
const result = resolveArtifactBindings({
roles: [{ role: "linear", integration: "linear" }],
connections: { linear: "linear.org.linearStaging" },
available: [
connection("linear", "org", "linearProd"),
connection("linear", "org", "linearStaging"),
],
});
expect(result.ok).toBe(true);
if (!result.ok) return;
expect(result.bindings.linear).toEqual({
integration: "linear",
owner: "org",
connection: "linearStaging",
});
});
it("accepts a supplied address that carries the tools. prefix", () => {
const result = resolveArtifactBindings({
roles: [{ role: "linear", integration: "linear" }],
connections: { linear: "tools.linear.org.linearProd" },
available: [connection("linear", "org", "linearProd")],
});
expect(result.ok).toBe(true);
});
it("binds two roles of one integration to different connections", () => {
const result = resolveArtifactBindings({
roles: [
{ role: "prod", integration: "linear" },
{ role: "staging", integration: "linear" },
],
connections: { prod: "linear.org.linearProd", staging: "linear.user.myLinear" },
available: [
connection("linear", "org", "linearProd"),
connection("linear", "user", "myLinear"),
],
});
expect(result).toEqual({
ok: true,
bindings: {
prod: { integration: "linear", owner: "org", connection: "linearProd" },
staging: { integration: "linear", owner: "user", connection: "myLinear" },
},
});
});
it("refuses a connections key that names no role in the code", () => {
const result = resolveArtifactBindings({
roles: [{ role: "vercel", integration: "vercel" }],
connections: { linear: "linear.org.linearProd" },
available: [connection("vercel", "user", "personalVercel")],
});
expect(result.ok).toBe(false);
if (result.ok) return;
expect(result.message).toContain('role "linear"');
expect(result.message).toContain('"vercel"');
});
it("refuses a supplied connection that does not exist, with candidates", () => {
const result = resolveArtifactBindings({
roles: [{ role: "linear", integration: "linear" }],
connections: { linear: "linear.org.gone" },
available: [connection("linear", "org", "linearProd")],
});
expect(result.ok).toBe(false);
if (result.ok) return;
expect(result.message).toContain("linear.org.gone");
expect(result.message).toContain("linear.org.linearProd");
});
it("refuses a supplied connection belonging to another integration", () => {
const result = resolveArtifactBindings({
roles: [{ role: "prod", integration: "linear" }],
connections: { prod: "vercel.user.personalVercel" },
available: [
connection("vercel", "user", "personalVercel"),
connection("linear", "org", "linearProd"),
],
});
expect(result.ok).toBe(false);
if (result.ok) return;
expect(result.message).toContain("vercel");
});
it("refuses a malformed connection address", () => {
const result = resolveArtifactBindings({
roles: [{ role: "linear", integration: "linear" }],
connections: { linear: "linearProd" },
available: [connection("linear", "org", "linearProd")],
});
expect(result.ok).toBe(false);
if (result.ok) return;
expect(result.message).toContain("not a connection address");
});
it("refuses one role used for two integrations", () => {
const result = resolveArtifactBindings({
roles: [
{ role: "prod", integration: "linear" },
{ role: "prod", integration: "vercel" },
],
available: [],
});
expect(result.ok).toBe(false);
if (result.ok) return;
expect(result.message).toContain("two different integrations");
});
it("binds nothing for code that calls no integration", () => {
expect(resolveArtifactBindings({ roles: [], available: [] })).toEqual({
ok: true,
bindings: {},
});
});
});
describe("resolveCallAddress", () => {
const bindings = {
vercel: binding("vercel", "user", "personalVercel"),
prod: binding("linear", "org", "linearProd"),
staging: binding("linear", "user", "myLinear"),
};
it("expands a short path through the implicit role", () => {
const result = resolveCallAddress({
path: ["vercel", "domains", "getDomains"],
bindings,
});
expect(result).toEqual({
ok: true,
path: ["vercel", "user", "personalVercel", "domains", "getDomains"],
});
});
it("routes each explicit role to its own connection", () => {
expect(
resolveCallAddress({ path: ["linear", "issues", "list"], role: "prod", bindings }),
).toEqual({ ok: true, path: ["linear", "org", "linearProd", "issues", "list"] });
expect(
resolveCallAddress({ path: ["linear", "issues", "list"], role: "staging", bindings }),
).toEqual({ ok: true, path: ["linear", "user", "myLinear", "issues", "list"] });
});
it("passes system tools through untouched", () => {
expect(resolveCallAddress({ path: ["search"], bindings })).toEqual({
ok: true,
path: ["search"],
});
expect(resolveCallAddress({ path: ["describe", "tool"], bindings })).toEqual({
ok: true,
path: ["describe", "tool"],
});
});
it("fails with binding_unresolved when the role is not bound", () => {
const result = resolveCallAddress({ path: ["stripe", "charges", "list"], bindings });
expect(result.ok).toBe(false);
if (result.ok) return;
expect(result.error).toBe("binding_unresolved");
expect(result.role).toBe("stripe");
expect(result.integration).toBe("stripe");
expect(result.message).toContain('"vercel"');
});
it("fails when a tagged role was never bound", () => {
const result = resolveCallAddress({ path: ["linear", "issues", "list"], role: "qa", bindings });
expect(result.ok).toBe(false);
if (result.ok) return;
expect(result.role).toBe("qa");
});
// Grandfather path: artifacts saved before bindings existed stored
// five-segment paths and carry `bindings: null`.
it("executes an old five-segment path when the artifact has no bindings", () => {
expect(
resolveCallAddress({
path: ["inventory", "org", "main", "listItems"],
bindings: null,
}),
).toEqual({ ok: true, path: ["inventory", "org", "main", "listItems"] });
});
it("does not grandfather a short path", () => {
const result = resolveCallAddress({ path: ["vercel", "getDomains"], bindings: null });
expect(result.ok).toBe(false);
});
it("does not grandfather once the artifact has bindings", () => {
const result = resolveCallAddress({
path: ["inventory", "org", "main", "listItems"],
bindings: { vercel: binding("vercel", "user", "personalVercel") },
});
expect(result.ok).toBe(false);
if (result.ok) return;
expect(result.error).toBe("binding_unresolved");
});
it("does not grandfather a role-tagged call", () => {
const result = resolveCallAddress({
path: ["inventory", "org", "main", "listItems"],
role: "inv",
bindings: null,
});
expect(result.ok).toBe(false);
});
});