|
| 1 | +import type { ProviderActionDefinition } from "../../core/provider-definition.ts"; |
| 2 | + |
| 3 | +import { s } from "../../core/json-schema.ts"; |
| 4 | +import { defineProviderAction } from "../../core/provider-definition.ts"; |
| 5 | + |
| 6 | +const service = "qdrant"; |
| 7 | + |
| 8 | +const collectionNameSchema = s.nonEmptyString("The Qdrant collection name."); |
| 9 | +const pointIdSchema = s.union([s.nonNegativeInteger("A non-negative numeric point ID."), s.uuid("A UUID point ID.")]); |
| 10 | +const vectorSchema = s.array("A dense unnamed vector.", s.number("One vector component."), { minItems: 1 }); |
| 11 | +const payloadSchema = s.looseObject("A JSON object stored with the point."); |
| 12 | +const filterSchema = s.looseObject("A Qdrant filter. Nested conditions are validated by Qdrant.", { |
| 13 | + must: s.unknown("Conditions that must match."), |
| 14 | + must_not: s.unknown("Conditions that must not match."), |
| 15 | + should: s.unknown("Conditions where at least one should match."), |
| 16 | + min_should: s.unknown("Minimum number of should conditions that must match."), |
| 17 | +}); |
| 18 | + |
| 19 | +const pointSchema = s.object( |
| 20 | + "A Qdrant point to insert or update.", |
| 21 | + { |
| 22 | + id: pointIdSchema, |
| 23 | + vector: vectorSchema, |
| 24 | + payload: payloadSchema, |
| 25 | + }, |
| 26 | + { optional: ["payload"] }, |
| 27 | +); |
| 28 | + |
| 29 | +const recordSchema = s.looseRequiredObject( |
| 30 | + "A Qdrant point record.", |
| 31 | + { |
| 32 | + id: pointIdSchema, |
| 33 | + payload: s.nullable(payloadSchema), |
| 34 | + vector: s.nullable(vectorSchema), |
| 35 | + shard_key: s.unknown("The Qdrant shard key when present."), |
| 36 | + order_value: s.unknown("The Qdrant order value when present."), |
| 37 | + }, |
| 38 | + { optional: ["payload", "vector", "shard_key", "order_value"] }, |
| 39 | +); |
| 40 | + |
| 41 | +const scoredPointSchema = s.looseRequiredObject( |
| 42 | + "A Qdrant scored point.", |
| 43 | + { |
| 44 | + id: pointIdSchema, |
| 45 | + version: s.nonNegativeInteger("The point version."), |
| 46 | + score: s.number("The similarity score."), |
| 47 | + payload: s.nullable(payloadSchema), |
| 48 | + vector: s.nullable(vectorSchema), |
| 49 | + shard_key: s.unknown("The Qdrant shard key when present."), |
| 50 | + order_value: s.unknown("The Qdrant order value when present."), |
| 51 | + }, |
| 52 | + { optional: ["payload", "vector", "shard_key", "order_value"] }, |
| 53 | +); |
| 54 | + |
| 55 | +const collectionSchema = s.looseRequiredObject( |
| 56 | + "A Qdrant collection description.", |
| 57 | + { |
| 58 | + status: s.unknown("The collection status."), |
| 59 | + optimizer_status: s.unknown("The collection optimizer status."), |
| 60 | + indexed_vectors_count: s.nullable(s.nonNegativeInteger("The approximate indexed vector count.")), |
| 61 | + points_count: s.nullable(s.nonNegativeInteger("The approximate point count.")), |
| 62 | + segments_count: s.nonNegativeInteger("The number of collection segments."), |
| 63 | + config: s.looseObject("The collection configuration."), |
| 64 | + payload_schema: s.looseObject("The collection payload index schema."), |
| 65 | + warnings: s.array("Collection warnings.", s.looseObject("A collection warning.")), |
| 66 | + }, |
| 67 | + { optional: ["indexed_vectors_count", "points_count", "warnings"] }, |
| 68 | +); |
| 69 | + |
| 70 | +const filterInputFields = { |
| 71 | + filter: filterSchema, |
| 72 | + limit: s.integer("The maximum number of points to return.", { minimum: 1, maximum: 1000 }), |
| 73 | + withPayload: s.boolean("Whether to include point payloads."), |
| 74 | + withVector: s.boolean("Whether to include point vectors."), |
| 75 | +}; |
| 76 | + |
| 77 | +export const qdrantActions: ProviderActionDefinition[] = [ |
| 78 | + defineProviderAction(service, { |
| 79 | + name: "list_collections", |
| 80 | + description: "List the Qdrant collections visible to the authenticated API key.", |
| 81 | + inputSchema: s.actionInput({}, [], "Input parameters for listing Qdrant collections."), |
| 82 | + outputSchema: s.actionOutput( |
| 83 | + { |
| 84 | + collections: s.array( |
| 85 | + "The visible Qdrant collections.", |
| 86 | + s.requiredObject("A Qdrant collection name.", { name: s.nonEmptyString("The collection name.") }), |
| 87 | + ), |
| 88 | + }, |
| 89 | + "The Qdrant collection list response.", |
| 90 | + ), |
| 91 | + followUpActions: ["qdrant.get_collection", "qdrant.create_collection"], |
| 92 | + }), |
| 93 | + defineProviderAction(service, { |
| 94 | + name: "get_collection", |
| 95 | + description: "Retrieve configuration and status information for one Qdrant collection.", |
| 96 | + inputSchema: s.actionInput( |
| 97 | + { collectionName: collectionNameSchema }, |
| 98 | + ["collectionName"], |
| 99 | + "Input parameters for retrieving a Qdrant collection.", |
| 100 | + ), |
| 101 | + outputSchema: s.actionOutput({ collection: collectionSchema }, "The Qdrant collection description response."), |
| 102 | + followUpActions: ["qdrant.query_points", "qdrant.scroll_points", "qdrant.upsert_points"], |
| 103 | + }), |
| 104 | + defineProviderAction(service, { |
| 105 | + name: "create_collection", |
| 106 | + description: "Create a Qdrant Cloud collection with one unnamed dense vector configuration.", |
| 107 | + inputSchema: s.actionInput( |
| 108 | + { |
| 109 | + collectionName: collectionNameSchema, |
| 110 | + vectorSize: s.positiveInteger("The dense vector dimension."), |
| 111 | + distance: s.stringEnum("The distance function used by the collection.", [ |
| 112 | + "Cosine", |
| 113 | + "Euclid", |
| 114 | + "Dot", |
| 115 | + "Manhattan", |
| 116 | + ]), |
| 117 | + }, |
| 118 | + ["collectionName", "vectorSize", "distance"], |
| 119 | + "Input parameters for creating a dense-vector Qdrant collection.", |
| 120 | + ), |
| 121 | + outputSchema: s.actionOutput({ created: s.boolean("Whether Qdrant created the collection.") }), |
| 122 | + followUpActions: ["qdrant.get_collection", "qdrant.upsert_points"], |
| 123 | + }), |
| 124 | + defineProviderAction(service, { |
| 125 | + name: "upsert_points", |
| 126 | + description: "Insert or replace dense-vector points in a Qdrant collection and wait for the write to commit.", |
| 127 | + inputSchema: s.actionInput( |
| 128 | + { |
| 129 | + collectionName: collectionNameSchema, |
| 130 | + points: s.array("The points to upsert.", pointSchema, { minItems: 1, maxItems: 1000 }), |
| 131 | + }, |
| 132 | + ["collectionName", "points"], |
| 133 | + "Input parameters for upserting Qdrant points.", |
| 134 | + ), |
| 135 | + outputSchema: s.actionOutput( |
| 136 | + { |
| 137 | + operationId: s.nullable(s.nonNegativeInteger("The Qdrant operation ID when returned.")), |
| 138 | + status: s.stringEnum("The Qdrant write status.", ["acknowledged", "completed", "wait_timeout"]), |
| 139 | + }, |
| 140 | + "The Qdrant upsert operation result.", |
| 141 | + ), |
| 142 | + followUpActions: ["qdrant.get_point", "qdrant.query_points", "qdrant.scroll_points"], |
| 143 | + }), |
| 144 | + defineProviderAction(service, { |
| 145 | + name: "get_point", |
| 146 | + description: "Retrieve one point by numeric ID or UUID from a Qdrant collection.", |
| 147 | + inputSchema: s.actionInput( |
| 148 | + { collectionName: collectionNameSchema, id: pointIdSchema }, |
| 149 | + ["collectionName", "id"], |
| 150 | + "Input parameters for retrieving a Qdrant point.", |
| 151 | + ), |
| 152 | + outputSchema: s.actionOutput({ point: recordSchema }, "The Qdrant point record response."), |
| 153 | + }), |
| 154 | + defineProviderAction(service, { |
| 155 | + name: "query_points", |
| 156 | + description: "Search a dense-vector Qdrant collection with an optional payload filter.", |
| 157 | + inputSchema: s.actionInput( |
| 158 | + { |
| 159 | + collectionName: collectionNameSchema, |
| 160 | + vector: vectorSchema, |
| 161 | + ...filterInputFields, |
| 162 | + offset: s.nonNegativeInteger("The number of matching points to skip."), |
| 163 | + scoreThreshold: s.number("The minimum score a result must have."), |
| 164 | + }, |
| 165 | + ["collectionName", "vector"], |
| 166 | + "Input parameters for querying Qdrant points.", |
| 167 | + ), |
| 168 | + outputSchema: s.actionOutput( |
| 169 | + { points: s.array("The scored points returned by Qdrant.", scoredPointSchema) }, |
| 170 | + "The Qdrant query response.", |
| 171 | + ), |
| 172 | + followUpActions: ["qdrant.get_point", "qdrant.scroll_points"], |
| 173 | + }), |
| 174 | + defineProviderAction(service, { |
| 175 | + name: "scroll_points", |
| 176 | + description: "Read one page of points from a Qdrant collection with an optional payload filter.", |
| 177 | + inputSchema: s.actionInput( |
| 178 | + { collectionName: collectionNameSchema, offset: pointIdSchema, ...filterInputFields }, |
| 179 | + ["collectionName"], |
| 180 | + "Input parameters for scrolling through Qdrant points.", |
| 181 | + ), |
| 182 | + outputSchema: s.actionOutput( |
| 183 | + { |
| 184 | + points: s.array("The point records returned by Qdrant.", recordSchema), |
| 185 | + nextOffset: s.nullable(pointIdSchema), |
| 186 | + complete: s.boolean("Whether there is no next page."), |
| 187 | + }, |
| 188 | + "One page of Qdrant scroll results.", |
| 189 | + ), |
| 190 | + followUpActions: ["qdrant.scroll_points", "qdrant.get_point"], |
| 191 | + }), |
| 192 | +]; |
0 commit comments