Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
955bf7b
feat(types): add targetClientId to HostBashRequest and PendingInterac…
credence-the-bot[bot] May 3, 2026
96576ed
feat(clients): add machineName label to client registration and assis…
credence-the-bot[bot] May 3, 2026
06a73f2
feat(event-hub): add per-client targeted delivery and targetClientId …
credence-the-bot[bot] May 3, 2026
5a4ec61
feat(host-bash-proxy): resolve and validate target client; pass targe…
credence-the-bot[bot] May 3, 2026
d07adab
feat(host-bash): add target_client_id parameter to tool schema and ex…
credence-the-bot[bot] May 3, 2026
17d89fe
feat(macos): decode targetClientId from HostBashRequest and accept ta…
credence-the-bot[bot] May 3, 2026
ccd6aa9
feat(host-bash-result): reject result submissions from non-targeted c…
credence-the-bot[bot] May 3, 2026
1916eca
feat(tool-projection): include host_bash for non-host interfaces when…
credence-the-bot[bot] May 3, 2026
a68fed4
fix(tool-projection): exclude chrome-extension and hasNoClient from c…
May 3, 2026
b14fb78
fix(targeted-host-proxy): error when targetClientId set but client di…
credence-the-bot[bot] May 3, 2026
1f21e87
Merge remote-tracking branch 'origin/main' into Credence/targeted-hos…
May 3, 2026
fdee79f
fix(targeted-host-proxy): tighten Swift guard to reject mismatched ta…
May 3, 2026
db37b62
fix(targeted-host-proxy): pass targeted host_bash requests through Ev…
May 3, 2026
650dc2a
Merge remote-tracking branch 'origin/main' into Credence/targeted-hos…
May 3, 2026
e0624c0
fix: target cancel messages to originating client + normalize empty t…
May 3, 2026
4fb0c39
Merge remote-tracking branch 'origin/main' into Credence/targeted-hos…
May 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions assistant/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5960,6 +5960,10 @@ paths:
required:
- accepted
additionalProperties: false
"400":
description: x-vellum-client-id header is missing for a targeted host bash request.
"403":
description: Submitting client does not match the targeted client for this request.
requestBody:
required: true
content:
Expand Down
146 changes: 146 additions & 0 deletions assistant/src/__tests__/assistant-event-hub-machine-name.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/**
* Tests for machineName field in AssistantEventHub client registration.
*
* Validates:
* - subscribing with machineName set results in listClients() returning the name
* - subscribing without machineName results in listClients() returning undefined
*/
import { describe, expect, mock, test } from "bun:test";

mock.module("../util/logger.js", () => ({
getLogger: () =>
new Proxy({} as Record<string, unknown>, {
get: () => () => {},
}),
}));

mock.module("../config/loader.js", () => ({
getConfig: () => ({
ui: {},
model: "test",
provider: "test",
memory: { enabled: false },
rateLimit: { maxRequestsPerMinute: 0 },
secretDetection: { enabled: false },
}),
}));

import { initializeDb } from "../memory/db-init.js";
import { AssistantEventHub } from "../runtime/assistant-event-hub.js";
import { handleSubscribeAssistantEvents } from "../runtime/routes/events-routes.js";

initializeDb();

describe("AssistantEventHub — machineName", () => {
test("subscribing with machineName returns it from listClients()", () => {
const ac = new AbortController();
const hub = new AssistantEventHub();

handleSubscribeAssistantEvents(
{
headers: {
"x-vellum-client-id": "client-with-name-001",
"x-vellum-interface-id": "macos",
"x-vellum-machine-name": "alice-mbp.local",
},
abortSignal: ac.signal,
},
{ hub },
);

const clients = hub.listClients();
const entry = clients.find((c) => c.clientId === "client-with-name-001");
expect(entry).toBeDefined();
expect(entry?.machineName).toBe("alice-mbp.local");

ac.abort();
});

test("subscribing without machineName returns undefined from listClients()", () => {
const ac = new AbortController();
const hub = new AssistantEventHub();

handleSubscribeAssistantEvents(
{
headers: {
"x-vellum-client-id": "client-without-name-001",
"x-vellum-interface-id": "macos",
},
abortSignal: ac.signal,
},
{ hub },
);

const clients = hub.listClients();
const entry = clients.find(
(c) => c.clientId === "client-without-name-001",
);
expect(entry).toBeDefined();
expect(entry?.machineName).toBeUndefined();

ac.abort();
});

test("machineName is trimmed when set", () => {
const ac = new AbortController();
const hub = new AssistantEventHub();

handleSubscribeAssistantEvents(
{
headers: {
"x-vellum-client-id": "client-with-trimmed-name-001",
"x-vellum-interface-id": "macos",
"x-vellum-machine-name": " bob-mbp.local ",
},
abortSignal: ac.signal,
},
{ hub },
);

const clients = hub.listClients();
const entry = clients.find(
(c) => c.clientId === "client-with-trimmed-name-001",
);
expect(entry).toBeDefined();
expect(entry?.machineName).toBe("bob-mbp.local");

ac.abort();
});

test("direct hub subscribe with machineName returns it from listClients()", () => {
const hub = new AssistantEventHub();

hub.subscribe({
type: "client",
clientId: "direct-client-001",
interfaceId: "macos",
capabilities: ["host_bash"],
machineName: "charlie-mbp.local",
callback: () => {},
});

const clients = hub.listClients();
const entry = clients.find((c) => c.clientId === "direct-client-001");
expect(entry).toBeDefined();
expect(entry?.machineName).toBe("charlie-mbp.local");
});

test("direct hub subscribe without machineName returns undefined from listClients()", () => {
const hub = new AssistantEventHub();

hub.subscribe({
type: "client",
clientId: "direct-client-no-name-001",
interfaceId: "macos",
capabilities: ["host_bash"],
callback: () => {},
});

const clients = hub.listClients();
const entry = clients.find(
(c) => c.clientId === "direct-client-no-name-001",
);
expect(entry).toBeDefined();
expect(entry?.machineName).toBeUndefined();
});
});
Loading
Loading