@koda-sl/baker-bridge 0.118.0-dev.fc1af4da8 → 0.118.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/README.md +2 -0
- package/dist/broker/baker-api.d.ts +9 -0
- package/dist/broker/baker-api.d.ts.map +1 -1
- package/dist/broker/baker-api.js +14 -0
- package/dist/broker/baker-api.js.map +1 -1
- package/dist/broker/ca.d.ts +8 -0
- package/dist/broker/ca.d.ts.map +1 -1
- package/dist/broker/ca.js +13 -2
- package/dist/broker/ca.js.map +1 -1
- package/dist/broker/ca.test.js +18 -2
- package/dist/broker/ca.test.js.map +1 -1
- package/dist/broker/credential-cache.d.ts +2 -7
- package/dist/broker/credential-cache.d.ts.map +1 -1
- package/dist/broker/credential-cache.js +45 -12
- package/dist/broker/credential-cache.js.map +1 -1
- package/dist/broker/credential-cache.test.js +47 -1
- package/dist/broker/credential-cache.test.js.map +1 -1
- package/dist/broker/credential-text.d.ts.map +1 -1
- package/dist/broker/credential-text.js +3 -0
- package/dist/broker/credential-text.js.map +1 -1
- package/dist/broker/credential-text.test.js +2 -0
- package/dist/broker/credential-text.test.js.map +1 -1
- package/dist/broker/proxy.d.ts.map +1 -1
- package/dist/broker/proxy.integration.test.js +73 -0
- package/dist/broker/proxy.integration.test.js.map +1 -1
- package/dist/broker/proxy.js +28 -18
- package/dist/broker/proxy.js.map +1 -1
- package/dist/broker/rewrite.d.ts +7 -1
- package/dist/broker/rewrite.d.ts.map +1 -1
- package/dist/broker/rewrite.js +21 -5
- package/dist/broker/rewrite.js.map +1 -1
- package/dist/broker/socket-service.d.ts.map +1 -1
- package/dist/broker/socket-service.js +20 -1
- package/dist/broker/socket-service.js.map +1 -1
- package/dist/broker/socket-service.test.js +13 -2
- package/dist/broker/socket-service.test.js.map +1 -1
- package/dist/hono/agent.d.ts.map +1 -1
- package/dist/hono/agent.js +1 -0
- package/dist/hono/agent.js.map +1 -1
- package/dist/hono/avatar-casting.d.ts.map +1 -1
- package/dist/hono/avatar-casting.js +3 -2
- package/dist/hono/avatar-casting.js.map +1 -1
- package/dist/hono/baker-ui-tool-schemas.test.js +26 -5
- package/dist/hono/baker-ui-tool-schemas.test.js.map +1 -1
- package/dist/hono/blocking-card.d.ts +12 -0
- package/dist/hono/blocking-card.d.ts.map +1 -0
- package/dist/hono/blocking-card.js +12 -0
- package/dist/hono/blocking-card.js.map +1 -0
- package/dist/hono/bridge-job.d.ts +29 -1
- package/dist/hono/bridge-job.d.ts.map +1 -1
- package/dist/hono/bridge-job.js +73 -3
- package/dist/hono/bridge-job.js.map +1 -1
- package/dist/hono/bridge-job.test.js +130 -0
- package/dist/hono/bridge-job.test.js.map +1 -1
- package/dist/hono/connection-input.d.ts +155 -12
- package/dist/hono/connection-input.d.ts.map +1 -1
- package/dist/hono/connection-input.js +131 -15
- package/dist/hono/connection-input.js.map +1 -1
- package/dist/hono/connection-input.test.js +78 -9
- package/dist/hono/connection-input.test.js.map +1 -1
- package/dist/hono/credential-input.d.ts.map +1 -1
- package/dist/hono/credential-input.js +3 -2
- package/dist/hono/credential-input.js.map +1 -1
- package/dist/hono/flow-input.d.ts.map +1 -1
- package/dist/hono/flow-input.js +3 -2
- package/dist/hono/flow-input.js.map +1 -1
- package/dist/hono/mcp-servers.d.ts +8 -1
- package/dist/hono/mcp-servers.d.ts.map +1 -1
- package/dist/hono/mcp-servers.js +17 -6
- package/dist/hono/mcp-servers.js.map +1 -1
- package/dist/hono/mcp-servers.test.js +25 -0
- package/dist/hono/mcp-servers.test.js.map +1 -1
- package/dist/hono/prompt-context.test.js +4 -1
- package/dist/hono/prompt-context.test.js.map +1 -1
- package/dist/hono/tag-input.d.ts +41 -2
- package/dist/hono/tag-input.d.ts.map +1 -1
- package/dist/hono/tag-input.js +8 -4
- package/dist/hono/tag-input.js.map +1 -1
- package/dist/hono/tag-input.test.js +5 -1
- package/dist/hono/tag-input.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -2136,6 +2136,136 @@ describe("BridgeJobExecutor", () => {
|
|
|
2136
2136
|
expect(connectionRequests).toHaveLength(1);
|
|
2137
2137
|
expect(decision).toMatchObject({ behavior: "allow" });
|
|
2138
2138
|
});
|
|
2139
|
+
it("loads a server the user connected from the card into this same turn, and tells the agent it is ready", async () => {
|
|
2140
|
+
const relay = recordingRelay();
|
|
2141
|
+
relay.connectionInputRequest = () => Promise.resolve(true);
|
|
2142
|
+
const controls = activeControls();
|
|
2143
|
+
const acme = { type: "http", url: "https://acme.dev/mcp" };
|
|
2144
|
+
const asks = [];
|
|
2145
|
+
const loaded = [];
|
|
2146
|
+
let decision;
|
|
2147
|
+
const executor = new BridgeJobExecutor({
|
|
2148
|
+
sdk: {
|
|
2149
|
+
query: (input) => ({
|
|
2150
|
+
async *[Symbol.asyncIterator]() {
|
|
2151
|
+
const asked = input.options.canUseTool?.(CONNECTION_INPUT_TOOL_NAME, { connections: [{ server: { name: "acme", url: "https://acme.dev/mcp", auth: "none" }, reason: "r" }] }, { toolUseID: "t1", requestId: "req_t1", signal: new AbortController().signal });
|
|
2152
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
2153
|
+
for (const [, pending] of controls.pendingConnectionInputs) {
|
|
2154
|
+
pending.resolve({ results: [{ status: "connected", server: "acme", scope: "company" }] });
|
|
2155
|
+
}
|
|
2156
|
+
decision = await asked;
|
|
2157
|
+
yield resultMessage(0, "session_after_connect");
|
|
2158
|
+
},
|
|
2159
|
+
setMcpServers: (servers) => {
|
|
2160
|
+
loaded.push(servers);
|
|
2161
|
+
return Promise.resolve({ added: ["acme"], removed: [], errors: {} });
|
|
2162
|
+
},
|
|
2163
|
+
}),
|
|
2164
|
+
},
|
|
2165
|
+
model: "claude-test",
|
|
2166
|
+
sessionStore: { load: async () => undefined, save: async () => undefined, clear: async () => undefined },
|
|
2167
|
+
relay,
|
|
2168
|
+
mcpServersProvider: (_threadId, _actor, options) => {
|
|
2169
|
+
asks.push(options ?? {});
|
|
2170
|
+
const servers = options?.fresh ? { acme } : {};
|
|
2171
|
+
return Promise.resolve(servers);
|
|
2172
|
+
},
|
|
2173
|
+
});
|
|
2174
|
+
await executor.execute({ threadId: "thread_mcp", turnId: "turn_mcp", prompt: "Connect Acme" }, controls);
|
|
2175
|
+
expect(asks).toEqual([{}, { fresh: true }]);
|
|
2176
|
+
expect(Object.keys(loaded[0] ?? {}).sort()).toEqual(["acme", "baker_ui"]);
|
|
2177
|
+
expect(decision).toMatchObject({ behavior: "allow", updatedInput: { resolution: { toolsReady: true } } });
|
|
2178
|
+
});
|
|
2179
|
+
it("names a server that would not start, so the agent does not promise it for the next message", async () => {
|
|
2180
|
+
const relay = recordingRelay();
|
|
2181
|
+
relay.connectionInputRequest = () => Promise.resolve(true);
|
|
2182
|
+
const controls = activeControls();
|
|
2183
|
+
let decision;
|
|
2184
|
+
const executor = new BridgeJobExecutor({
|
|
2185
|
+
sdk: {
|
|
2186
|
+
query: (input) => ({
|
|
2187
|
+
async *[Symbol.asyncIterator]() {
|
|
2188
|
+
const asked = input.options.canUseTool?.(CONNECTION_INPUT_TOOL_NAME, { connections: [{ server: { name: "acme", url: "https://acme.dev/mcp" }, reason: "r" }] }, { toolUseID: "t1", requestId: "req_t1", signal: new AbortController().signal });
|
|
2189
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
2190
|
+
for (const [, pending] of controls.pendingConnectionInputs) {
|
|
2191
|
+
pending.resolve({ results: [{ status: "connected", server: "acme", scope: "company" }] });
|
|
2192
|
+
}
|
|
2193
|
+
decision = await asked;
|
|
2194
|
+
yield resultMessage(0, "session_after_failed_load");
|
|
2195
|
+
},
|
|
2196
|
+
setMcpServers: () => Promise.resolve({ added: [], removed: [], errors: { acme: "401 Unauthorized" } }),
|
|
2197
|
+
}),
|
|
2198
|
+
},
|
|
2199
|
+
model: "claude-test",
|
|
2200
|
+
sessionStore: { load: async () => undefined, save: async () => undefined, clear: async () => undefined },
|
|
2201
|
+
relay,
|
|
2202
|
+
mcpServersProvider: () => Promise.resolve({ acme: { type: "http", url: "https://acme.dev/mcp" } }),
|
|
2203
|
+
});
|
|
2204
|
+
await executor.execute({ threadId: "thread_bad", turnId: "turn_bad", prompt: "Connect Acme" }, controls);
|
|
2205
|
+
expect(decision).toMatchObject({
|
|
2206
|
+
updatedInput: { resolution: { toolsReady: false, failedToLoad: ["acme"] } },
|
|
2207
|
+
});
|
|
2208
|
+
});
|
|
2209
|
+
it("does not call an app ready when the reloaded tools do not include it", async () => {
|
|
2210
|
+
const relay = recordingRelay();
|
|
2211
|
+
relay.connectionInputRequest = () => Promise.resolve(true);
|
|
2212
|
+
const controls = activeControls();
|
|
2213
|
+
let decision;
|
|
2214
|
+
const executor = new BridgeJobExecutor({
|
|
2215
|
+
sdk: {
|
|
2216
|
+
query: (input) => ({
|
|
2217
|
+
async *[Symbol.asyncIterator]() {
|
|
2218
|
+
const asked = input.options.canUseTool?.(CONNECTION_INPUT_TOOL_NAME, { connections: [{ app: "notion", reason: "r" }] }, { toolUseID: "t1", requestId: "req_t1", signal: new AbortController().signal });
|
|
2219
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
2220
|
+
for (const [, pending] of controls.pendingConnectionInputs) {
|
|
2221
|
+
pending.resolve({ results: [{ status: "connected", app: "notion", scope: "company" }] });
|
|
2222
|
+
}
|
|
2223
|
+
decision = await asked;
|
|
2224
|
+
yield resultMessage(0, "session_after_missing_app");
|
|
2225
|
+
},
|
|
2226
|
+
setMcpServers: () => Promise.resolve({ added: [], removed: [], errors: {} }),
|
|
2227
|
+
}),
|
|
2228
|
+
},
|
|
2229
|
+
model: "claude-test",
|
|
2230
|
+
sessionStore: { load: async () => undefined, save: async () => undefined, clear: async () => undefined },
|
|
2231
|
+
relay,
|
|
2232
|
+
mcpServersProvider: () => Promise.resolve({}),
|
|
2233
|
+
});
|
|
2234
|
+
await executor.execute({ threadId: "thread_app", turnId: "turn_app", prompt: "Connect Notion" }, controls);
|
|
2235
|
+
expect(decision).toMatchObject({
|
|
2236
|
+
updatedInput: { resolution: { toolsReady: false, failedToLoad: ["notion"] } },
|
|
2237
|
+
});
|
|
2238
|
+
});
|
|
2239
|
+
it("leaves the turn's tools alone when only a platform was connected", async () => {
|
|
2240
|
+
const relay = recordingRelay();
|
|
2241
|
+
relay.connectionInputRequest = () => Promise.resolve(true);
|
|
2242
|
+
const controls = activeControls();
|
|
2243
|
+
let reloads = 0;
|
|
2244
|
+
const executor = new BridgeJobExecutor({
|
|
2245
|
+
sdk: {
|
|
2246
|
+
query: (input) => ({
|
|
2247
|
+
async *[Symbol.asyncIterator]() {
|
|
2248
|
+
const asked = input.options.canUseTool?.(CONNECTION_INPUT_TOOL_NAME, { connections: [{ platform: "hubspot", reason: "r" }] }, { toolUseID: "t1", requestId: "req_t1", signal: new AbortController().signal });
|
|
2249
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
2250
|
+
for (const [, pending] of controls.pendingConnectionInputs) {
|
|
2251
|
+
pending.resolve({ results: [{ status: "connected", platform: "hubspot", selected: [] }] });
|
|
2252
|
+
}
|
|
2253
|
+
await asked;
|
|
2254
|
+
yield resultMessage(0, "session_after_platform");
|
|
2255
|
+
},
|
|
2256
|
+
setMcpServers: () => {
|
|
2257
|
+
reloads += 1;
|
|
2258
|
+
return Promise.resolve({ added: [], removed: [], errors: {} });
|
|
2259
|
+
},
|
|
2260
|
+
}),
|
|
2261
|
+
},
|
|
2262
|
+
model: "claude-test",
|
|
2263
|
+
sessionStore: { load: async () => undefined, save: async () => undefined, clear: async () => undefined },
|
|
2264
|
+
relay,
|
|
2265
|
+
});
|
|
2266
|
+
await executor.execute({ threadId: "thread_pl", turnId: "turn_pl", prompt: "Connect HubSpot" }, controls);
|
|
2267
|
+
expect(reloads).toBe(0);
|
|
2268
|
+
});
|
|
2139
2269
|
it("turns request_credential away in a Runtime without Credentials", async () => {
|
|
2140
2270
|
const relay = recordingRelay();
|
|
2141
2271
|
const requests = [];
|