mirror of
https://github.com/kennethnym/aris.git
synced 2026-06-14 03:21:18 +01:00
feat: add exa web search source (#124)
This commit is contained in:
@@ -186,6 +186,18 @@ function put(app: Hono, sourceId: string, body: unknown) {
|
||||
})
|
||||
}
|
||||
|
||||
function listActions(app: Hono, sourceId: string) {
|
||||
return app.request(`/api/sources/${sourceId}/actions`, { method: "GET" })
|
||||
}
|
||||
|
||||
function executeAction(app: Hono, sourceId: string, actionId: string, body: unknown) {
|
||||
return app.request(`/api/sources/${sourceId}/actions/${actionId}`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(body),
|
||||
})
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Tests
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -781,6 +793,168 @@ describe("PUT /api/sources/:sourceId", () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("GET /api/sources/:sourceId/actions", () => {
|
||||
test("returns 401 without auth", async () => {
|
||||
activeStore = createInMemoryStore()
|
||||
const { app } = createApp([createStubProvider("freya.location")])
|
||||
|
||||
const res = await listActions(app, "freya.location")
|
||||
|
||||
expect(res.status).toBe(401)
|
||||
})
|
||||
|
||||
test("returns 404 for source that is not enabled in the user session", async () => {
|
||||
activeStore = createInMemoryStore()
|
||||
const { app } = createApp([createStubProvider("freya.location")], MOCK_USER_ID)
|
||||
|
||||
const res = await listActions(app, "freya.location")
|
||||
|
||||
expect(res.status).toBe(404)
|
||||
})
|
||||
|
||||
test("returns serializable action definitions", async () => {
|
||||
activeStore = createInMemoryStore()
|
||||
activeStore.seed(MOCK_USER_ID, "test.actions")
|
||||
const provider: FeedSourceProvider = {
|
||||
sourceId: "test.actions",
|
||||
async feedSourceForUser() {
|
||||
return {
|
||||
id: "test.actions",
|
||||
async listActions() {
|
||||
return {
|
||||
search: {
|
||||
id: "search",
|
||||
description: "Search something",
|
||||
input: tflConfig,
|
||||
},
|
||||
}
|
||||
},
|
||||
async executeAction() {
|
||||
return undefined
|
||||
},
|
||||
async fetchContext() {
|
||||
return null
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
const { app } = createApp([provider], MOCK_USER_ID)
|
||||
|
||||
const res = await listActions(app, "test.actions")
|
||||
|
||||
expect(res.status).toBe(200)
|
||||
const body = (await res.json()) as {
|
||||
actions: Record<string, { id: string; description?: string; input?: unknown }>
|
||||
}
|
||||
expect(body.actions.search).toEqual({
|
||||
id: "search",
|
||||
description: "Search something",
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /api/sources/:sourceId/actions/:actionId", () => {
|
||||
test("returns 401 without auth", async () => {
|
||||
activeStore = createInMemoryStore()
|
||||
const { app } = createApp([createStubProvider("freya.location")])
|
||||
|
||||
const res = await executeAction(app, "freya.location", "update-location", {})
|
||||
|
||||
expect(res.status).toBe(401)
|
||||
})
|
||||
|
||||
test("executes source action with request body as params", async () => {
|
||||
activeStore = createInMemoryStore()
|
||||
activeStore.seed(MOCK_USER_ID, "test.actions")
|
||||
let receivedParams: unknown
|
||||
const provider: FeedSourceProvider = {
|
||||
sourceId: "test.actions",
|
||||
async feedSourceForUser() {
|
||||
return {
|
||||
id: "test.actions",
|
||||
async listActions() {
|
||||
return {
|
||||
search: { id: "search", description: "Search something" },
|
||||
}
|
||||
},
|
||||
async executeAction(_actionId: string, params: unknown) {
|
||||
receivedParams = params
|
||||
return { ok: true, count: 2 }
|
||||
},
|
||||
async fetchContext() {
|
||||
return null
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
const { app } = createApp([provider], MOCK_USER_ID)
|
||||
|
||||
const res = await executeAction(app, "test.actions", "search", { query: "exa" })
|
||||
|
||||
expect(res.status).toBe(200)
|
||||
expect(receivedParams).toEqual({ query: "exa" })
|
||||
const body = (await res.json()) as { result: unknown }
|
||||
expect(body.result).toEqual({ ok: true, count: 2 })
|
||||
})
|
||||
|
||||
test("returns 404 for unknown action", async () => {
|
||||
activeStore = createInMemoryStore()
|
||||
activeStore.seed(MOCK_USER_ID, "freya.location")
|
||||
const { app } = createApp([createStubProvider("freya.location")], MOCK_USER_ID)
|
||||
|
||||
const res = await executeAction(app, "freya.location", "missing", {})
|
||||
|
||||
expect(res.status).toBe(404)
|
||||
})
|
||||
|
||||
test("returns 400 for invalid JSON", async () => {
|
||||
activeStore = createInMemoryStore()
|
||||
activeStore.seed(MOCK_USER_ID, "freya.location")
|
||||
const { app } = createApp([createStubProvider("freya.location")], MOCK_USER_ID)
|
||||
|
||||
const res = await app.request("/api/sources/freya.location/actions/search", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: "not-json",
|
||||
})
|
||||
|
||||
expect(res.status).toBe(400)
|
||||
const body = (await res.json()) as { error: string }
|
||||
expect(body.error).toBe("Invalid JSON")
|
||||
})
|
||||
|
||||
test("returns 400 when source rejects params", async () => {
|
||||
activeStore = createInMemoryStore()
|
||||
activeStore.seed(MOCK_USER_ID, "test.actions")
|
||||
const provider: FeedSourceProvider = {
|
||||
sourceId: "test.actions",
|
||||
async feedSourceForUser() {
|
||||
return {
|
||||
id: "test.actions",
|
||||
async listActions() {
|
||||
return {
|
||||
search: { id: "search" },
|
||||
}
|
||||
},
|
||||
async executeAction() {
|
||||
throw new Error("query must not be empty")
|
||||
},
|
||||
async fetchContext() {
|
||||
return null
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
const { app } = createApp([provider], MOCK_USER_ID)
|
||||
|
||||
const res = await executeAction(app, "test.actions", "search", { query: "" })
|
||||
|
||||
expect(res.status).toBe(400)
|
||||
const body = (await res.json()) as { error: string }
|
||||
expect(body.error).toBe("query must not be empty")
|
||||
})
|
||||
})
|
||||
|
||||
describe("PUT /api/sources/:sourceId/credentials", () => {
|
||||
test("returns 401 without auth", async () => {
|
||||
activeStore = createInMemoryStore()
|
||||
|
||||
Reference in New Issue
Block a user