You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
5.6 KiB
112 lines
5.6 KiB
import assert from "node:assert/strict";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import test from "node:test";
|
|
|
|
const root = path.resolve(import.meta.dirname, "..");
|
|
const read = (...parts) => fs.readFileSync(path.join(root, ...parts), "utf8");
|
|
|
|
const {
|
|
SuperAgentApiError,
|
|
assertAgentUuid,
|
|
isAgentUuid,
|
|
parseAgentErrorPayload,
|
|
parseAgentPage,
|
|
shouldSendIdempotencyKey,
|
|
} = await import("../client/src/sections/superAgent/utils/agentApiParse.js");
|
|
const { superAgentServiceApiTable } = await import("../client/src/utils/superAgentApiTable.js");
|
|
const {
|
|
isUploadIntentExpired,
|
|
normalizeAttachmentUploadIntent,
|
|
} = await import("../client/src/sections/superAgent/utils/attachmentUpload.js");
|
|
|
|
test("new api table uses live agent paths", () => {
|
|
assert.equal(superAgentServiceApiTable.tasksets, "/tasksets");
|
|
assert.equal(superAgentServiceApiTable.conversations, "/conversations");
|
|
assert.equal(
|
|
superAgentServiceApiTable.attachmentUploadIntents,
|
|
"/conversations/:conversationId/attachments/upload-intents",
|
|
);
|
|
assert.equal(superAgentServiceApiTable.threadCommands, "/threads/:threadId/commands");
|
|
assert.equal(superAgentServiceApiTable.threadEvents, "/threads/:threadId/stream/events");
|
|
assert.equal(superAgentServiceApiTable.threadCancel, "/threads/:threadId/runs/:runId/cancel");
|
|
assert.equal(superAgentServiceApiTable.artifacts, "/conversations/:conversationId/artifacts");
|
|
assert.doesNotMatch(JSON.stringify(superAgentServiceApiTable), /\/api\/v1/);
|
|
});
|
|
|
|
test("uuid and page helpers normalize agent payloads", () => {
|
|
assert.equal(isAgentUuid("2c1f3c0e-1a2b-4c5d-8e9f-0123456789ab"), true);
|
|
assert.equal(isAgentUuid("task-1"), false);
|
|
assert.equal(assertAgentUuid("2c1f3c0e-1a2b-4c5d-8e9f-0123456789ab"), "2c1f3c0e-1a2b-4c5d-8e9f-0123456789ab");
|
|
assert.throws(
|
|
() => assertAgentUuid("task-1", "conversation_id"),
|
|
(error) => error instanceof SuperAgentApiError && error.status === 422,
|
|
);
|
|
assert.deepEqual(parseAgentPage({ items: [{ id: "a" }], next_cursor: "c1" }), {
|
|
items: [{ id: "a" }],
|
|
nextCursor: "c1",
|
|
});
|
|
assert.deepEqual(parseAgentPage({}), { items: [], nextCursor: null });
|
|
const error = parseAgentErrorPayload(
|
|
{ code: "AUTHENTICATION_REQUIRED", message: "missing", request_id: "req_1" },
|
|
401,
|
|
"fallback",
|
|
);
|
|
assert.equal(error.code, "AUTHENTICATION_REQUIRED");
|
|
assert.equal(error.requestId, "req_1");
|
|
assert.equal(shouldSendIdempotencyKey("POST", "k"), true);
|
|
assert.equal(shouldSendIdempotencyKey("GET", "k"), false);
|
|
});
|
|
|
|
test("attachment upload intent follows the v2 three-stage payload", () => {
|
|
const intent = normalizeAttachmentUploadIntent({
|
|
attachment: { id: "2c1f3c0e-1a2b-4c5d-8e9f-0123456789ab" },
|
|
upload: {
|
|
method: "POST",
|
|
url: "https://upload.example.test",
|
|
fields: { token: "opaque", key: "uploads/file.txt" },
|
|
expires_at: "2030-01-01T00:00:00Z",
|
|
},
|
|
});
|
|
assert.equal(intent.attachmentId, "2c1f3c0e-1a2b-4c5d-8e9f-0123456789ab");
|
|
assert.equal(intent.upload.method, "POST");
|
|
assert.equal(intent.upload.fields.key, "uploads/file.txt");
|
|
assert.equal(isUploadIntentExpired(intent, Date.parse("2029-01-01T00:00:00Z")), false);
|
|
assert.equal(isUploadIntentExpired(intent, Date.parse("2031-01-01T00:00:00Z")), true);
|
|
});
|
|
|
|
test("adapter source exchanges login token for agent jwt and omits identity headers", () => {
|
|
const table = read("client", "src", "utils", "superAgentApiTable.js");
|
|
const agentApi = read("client", "src", "sections", "superAgent", "utils", "agentApi.js");
|
|
const streamHook = read("client", "src", "sections", "superAgent", "hooks", "useSuperAgentStream.js");
|
|
const protocol = read("..", "api", "app", "controllers", "superAgentProtocol.js");
|
|
const actions = read("client", "src", "sections", "superAgent", "actions", "api.js");
|
|
const resources = read("client", "src", "sections", "superAgent", "actions", "agentResources.js");
|
|
const chatHook = read("client", "src", "sections", "superAgent", "hooks", "useSuperAgentChat.js");
|
|
const uploadUtils = read("client", "src", "sections", "superAgent", "utils", "attachmentUpload.js");
|
|
assert.doesNotMatch(table, /\/api\/v1\/tasks/);
|
|
assert.match(agentApi, /ACCESS_TOKEN_PATH = "\/_api\/super-agent\/access-token"/);
|
|
assert.match(agentApi, /Authorization: `Bearer \$\{token\}`/);
|
|
assert.match(agentApi, /headers\.delete\("X-User-Id"\)/);
|
|
assert.match(agentApi, /headers\.delete\("X-Search-Token"\)/);
|
|
assert.match(agentApi, /Idempotency-Key/);
|
|
assert.match(streamHook, /withAgentAuthorization/);
|
|
assert.doesNotMatch(streamHook, /X-User-Id/);
|
|
assert.doesNotMatch(streamHook, /\/api\/v1/);
|
|
assert.match(protocol, /issueAgentAccessToken/);
|
|
assert.doesNotMatch(protocol, /'X-User-Id'/);
|
|
assert.match(protocol, /\/threads\/\$\{encodeURIComponent/);
|
|
assert.match(actions, /requestAgentJson/);
|
|
assert.match(resources, /createAttachmentUploadIntent/);
|
|
assert.match(resources, /completeAttachmentUpload/);
|
|
assert.match(resources, /listAttachments/);
|
|
assert.match(chatHook, /createAttachmentUploadIntent\(conversationId/);
|
|
assert.match(chatHook, /completeAttachmentUpload\(uploadIntent\.attachmentId\)/);
|
|
assert.match(chatHook, /listAttachments\(conversationId\)/);
|
|
assert.match(chatHook, /attachment\.status === "ready" && !attachment\.message_id/);
|
|
assert.match(chatHook, /handleCancelUpload/);
|
|
assert.doesNotMatch(chatHook, /uploadSuperAgentFile/);
|
|
assert.match(uploadUtils, /FormData/);
|
|
assert.match(uploadUtils, /xhr\.send\(file\)/);
|
|
assert.match(resources, /cancelThreadRun/);
|
|
});
|
|
|