From 5de34c7888575acbd52ae50695c838e509f7afd1 Mon Sep 17 00:00:00 2001 From: Liam Griffiths Date: Mon, 15 Jul 2024 11:18:27 -0400 Subject: [PATCH 1/4] Use `Proxy` to allow for arbitrary property/array access --- examples/arbitrary-future-properties.ts | 46 ++ examples/box.ts | 7 +- examples/bug.ts | 36 ++ examples/if.ts | 15 +- examples/image-generation.ts | 4 +- examples/json.ts | 4 +- examples/large-run.ts | 6 +- examples/qa.ts | 22 - out.json | 0 src/Future.ts | 44 +- src/GEN_VERSION | 2 +- src/Node.ts | 13 +- src/Nodes.ts | 750 +++++++++++++++++++++++- src/ProxiedFuture.ts | 99 ++++ src/index.ts | 2 +- tests/ProxiedFuture.test.ts | 116 ++++ 16 files changed, 1096 insertions(+), 70 deletions(-) create mode 100755 examples/arbitrary-future-properties.ts create mode 100755 examples/bug.ts delete mode 100755 examples/qa.ts create mode 100644 out.json create mode 100644 src/ProxiedFuture.ts create mode 100644 tests/ProxiedFuture.test.ts diff --git a/examples/arbitrary-future-properties.ts b/examples/arbitrary-future-properties.ts new file mode 100755 index 0000000..ee74cda --- /dev/null +++ b/examples/arbitrary-future-properties.ts @@ -0,0 +1,46 @@ +#!/usr/bin/env -S npx ts-node --transpileOnly + +import { Substrate, Box, sb } from "substrate"; + +async function main() { + const SUBSTRATE_API_KEY = process.env["SUBSTRATE_API_KEY"]; + + const substrate = new Substrate({ + apiKey: SUBSTRATE_API_KEY, + }); + + const numbers = new Box( + { + value: [0, 1], + }, + ); + + const latin = new Box( + { + value: ["a", "b"], + }, + ); + + const greek = new Box( + { + value: { + a: "α", + b: "β", + } + }, + ); + + const result = new Box( + { + value: { + a: latin.future.value[numbers.future.value[0]], + b: greek.future.value[latin.future.value[1]], + ab: sb.concat(greek.future.value.a, greek.future.value.b), + }, + } + ); + + const res = await substrate.run(result); + console.log(res.get(result)); +} +main(); diff --git a/examples/box.ts b/examples/box.ts index 03e116b..7a5121f 100755 --- a/examples/box.ts +++ b/examples/box.ts @@ -31,8 +31,13 @@ async function main() { }, {}), }); - const res = await substrate.run(box); + const box2 = new Box({ + value: box.future.value.swedish, + }); + + const res = await substrate.run(box, box2); console.log({ box: res.get(box) }); + console.log({ box2: res.get(box2) }); } main(); diff --git a/examples/bug.ts b/examples/bug.ts new file mode 100755 index 0000000..1dd5be1 --- /dev/null +++ b/examples/bug.ts @@ -0,0 +1,36 @@ +#!/usr/bin/env -S npx ts-node --transpileOnly + +import { Substrate, Box, sb } from "substrate"; + +async function main() { + const SUBSTRATE_API_KEY = process.env["SUBSTRATE_API_KEY"]; + + const substrate = new Substrate({ apiKey: SUBSTRATE_API_KEY }); + + const data = new Box( + { + value: { + letters: ["a", "b"], + index: 0, + }, + } + ); + + const selected = new Box( + { + value: ob4: sb.get( + data.future.value.object, + data.future.value.letters[1], + ), + }, + }, + { id: "selected" }, + ); + + // console.log(JSON.stringify(Substrate.serialize(selected), null, 2)); + // return; + + const res = await substrate.run(selected); + console.log(JSON.stringify(res.json, null, 2)); +} +main(); diff --git a/examples/if.ts b/examples/if.ts index 21e09d7..e6850ff 100755 --- a/examples/if.ts +++ b/examples/if.ts @@ -30,8 +30,7 @@ async function main() { }); const [jupiter, mars] = sizes as [ComputeJSON, ComputeJSON]; - const radius = (p: ComputeJSON) => - p.future.json_object.get("radius") as unknown as number; + const radius = (p: ComputeJSON) => p.future.json_object.radius; const comparison = new ComputeJSON({ prompt: sb.interpolate`Is ${radius(jupiter)} > ${radius(mars)}?`, @@ -45,16 +44,14 @@ async function main() { }, }); - const result = new If({ - condition: comparison.future.json_object.get("isGreaterThan") as any, - value_if_true: jupiter.future.json_object, - value_if_false: mars.future.json_object, + const planetName = new If({ + condition: comparison.future.json_object.isGreaterThan, + value_if_true: jupiter.future.json_object.planetName, + value_if_false: mars.future.json_object.planetName, }); const output = new Box({ - value: sb.interpolate`The bigger planet is ${result.future.result.get( - "planetName", - )}!`, + value: sb.interpolate`The bigger planet is ${planetName.future.result}!`, }); const res = await substrate.run(output); diff --git a/examples/image-generation.ts b/examples/image-generation.ts index c365a3d..0bf3858 100755 --- a/examples/image-generation.ts +++ b/examples/image-generation.ts @@ -1,6 +1,6 @@ #!/usr/bin/env -S npx ts-node --transpileOnly -import { Substrate, ComputeText, GenerateImage } from "substrate"; +import { Substrate, ComputeText, GenerateImage, sb } from "substrate"; async function main() { const SUBSTRATE_API_KEY = process.env["SUBSTRATE_API_KEY"]; @@ -22,7 +22,7 @@ async function main() { const images = styles.map((style) => { return new GenerateImage({ - prompt: scene.future.text.concat(` render in a ((${style})) style`), + prompt: sb.concat(scene.future.text, ` render in a "${style}" style`), store: "hosted", }); }); diff --git a/examples/json.ts b/examples/json.ts index 34694e0..e4cc994 100755 --- a/examples/json.ts +++ b/examples/json.ts @@ -26,8 +26,8 @@ async function main() { max_tokens: 800, }); - const name = author.future.json_object.get("name"); - const bio = author.future.json_object.get("bio"); + const name = author.future.json_object.name; + const bio = author.future.json_object.bio; const report = new ComputeText({ prompt: sb.interpolate`Write a short summary about ${name} and make sure to use the following bio: ${bio}`, diff --git a/examples/large-run.ts b/examples/large-run.ts index 63d04aa..ff46dcb 100755 --- a/examples/large-run.ts +++ b/examples/large-run.ts @@ -1,6 +1,6 @@ #!/usr/bin/env -S npx ts-node --transpileOnly -import { Substrate, ComputeText } from "substrate"; +import { Substrate, ComputeText, sb } from "substrate"; async function main() { const SUBSTRATE_API_KEY = process.env["SUBSTRATE_API_KEY"]; @@ -9,10 +9,10 @@ async function main() { let nodes = []; let prompt: any = "once upon a time..."; - for (let i = 0; i < 50; i++) { + for (let i = 0; i < 25; i++) { const node = new ComputeText({ prompt }); nodes.push(node); - prompt = node.future.text.concat(" and then"); + prompt = sb.concat(node.future.text, " and then"); } const res = await substrate.run(...nodes); diff --git a/examples/qa.ts b/examples/qa.ts deleted file mode 100755 index 039f382..0000000 --- a/examples/qa.ts +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env -S npx ts-node --transpileOnly - -import { Substrate, Box, sb } from "substrate"; - -async function main() { - const SUBSTRATE_API_KEY = process.env["SUBSTRATE_API_KEY"]; - - const substrate = new Substrate({ apiKey: SUBSTRATE_API_KEY }); - - const node = new Box({ - value: { - a: "b", - c: { - d: [1, 2, 3], - }, - }, - }); - const res = await substrate.run(node); - console.log(res.apiResponse.status); - console.log(JSON.stringify(res.json)); -} -main(); diff --git a/out.json b/out.json new file mode 100644 index 0000000..e69de29 diff --git a/src/Future.ts b/src/Future.ts index 97e3199..62f78b0 100644 --- a/src/Future.ts +++ b/src/Future.ts @@ -1,5 +1,6 @@ import { idGenerator } from "substrate/idGenerator"; import { Node } from "substrate/Node"; +import { unproxy } from "./ProxiedFuture"; type Accessor = "item" | "attr"; type TraceOperation = { @@ -8,7 +9,7 @@ type TraceOperation = { accessor: Accessor; }; -type TraceProp = string | Future | number | Future; +export type TraceProp = string | Future | number | Future; type Concatable = string | Future; type JQCompatible = Record | any[] | string | number; type JQDirectiveTarget = Future | JQCompatible; @@ -33,7 +34,11 @@ abstract class Directive { // @ts-ignore return this.items .filter((p) => p instanceof Future) - .flatMap((p) => [p, ...p.referencedFutures()]); + .map((p) => unproxy(p) as Future) + .flatMap((p) => + // @ts-ignore + [p, ...p.referencedFutures()] + ); } } @@ -92,6 +97,11 @@ export class Trace extends Directive { // @ts-expect-error (accessing protected prop: _id) return Trace.Operation.future("attr", item._id); } else if (typeof item === "string") { + if (/^\d+$/.test(item)) { + // When item is a number (as a string) we're going to assume it's an array index + let index = parseInt(item); + return Trace.Operation.key("item", index); + } return Trace.Operation.key("attr", item); } return Trace.Operation.key("item", item); @@ -117,7 +127,7 @@ export class JQ extends Directive { rawValue: (val: JQCompatible) => ({ future_id: null, val }), }; - override next(...items: TraceProp[]) { + override next(..._items: TraceProp[]) { return new JQ(this.query, this.target); } @@ -184,7 +194,7 @@ export class StringConcat extends Directive { } } -export class Future { +export class Future { protected _directive: Directive; protected _id: string = ""; protected _runtimeHint: @@ -228,7 +238,8 @@ export class Future { * let newFuture = concat("string", node.future.someString, "!") */ export const concat = (...items: (string | Future)[]) => { - return new Future(new StringConcat(items)); + const uitems = items.map((item) => item instanceof Future ? unproxy(item) : item); + return new Future(new StringConcat(uitems)); }; /** @@ -245,7 +256,13 @@ export const interpolate = ( return concat( ...strings.flatMap((s: string, i: number) => { const expr = exprs[i]; - return expr ? [s, expr instanceof Future ? expr : expr.toString()] : [s]; + if (expr instanceof Future) { + return [s, unproxy(expr)]; + } else if (!expr) { + return [s]; + } else { + return [s, expr.toString()]; + } }), ); }; @@ -279,15 +296,17 @@ export const get = ( future: Future, path: string | Future, ) => { + const ufuture = unproxy(future); + const upath = path instanceof Future ? unproxy(path) : path; // @ts-ignore (protected _runtimeHint) - if (path instanceof Future) index._runtimeHint = "string"; + if (upath instanceof Future) upath._runtimeHint = "string"; const d = - typeof path === "string" + typeof upath === "string" ? // @ts-ignore (protected _directive) - future._directive.next(...parsePath(path)) + ufuture._directive.next(...parsePath(upath)) : // @ts-ignore (protected _directive) - future._directive.next(path); + ufuture._directive.next(upath); return new Future(d); }; @@ -299,7 +318,10 @@ export const get = ( * let newFuture = at(node.future.strings, 0); * */ -export const at = (future: Future, index: number | Future) => { +export const at = ( + future: Future, + index: number | Future, +) => { // @ts-ignore (protected _runtimeHint) if (index instanceof Future) index._runtimeHint = "number"; // @ts-ignore (protected _directive) diff --git a/src/GEN_VERSION b/src/GEN_VERSION index 349bed5..5d0c985 100644 --- a/src/GEN_VERSION +++ b/src/GEN_VERSION @@ -1 +1 @@ -20240617.20240711 \ No newline at end of file +20240617.20240715 \ No newline at end of file diff --git a/src/Node.ts b/src/Node.ts index dd28c3e..b63e821 100644 --- a/src/Node.ts +++ b/src/Node.ts @@ -3,6 +3,7 @@ import { Future, Trace } from "substrate/Future"; import { SubstrateResponse } from "substrate/SubstrateResponse"; import { NodeError, SubstrateError } from "substrate/Error"; import { AnyNode } from "substrate/Nodes"; +import { unproxy } from "substrate/ProxiedFuture"; const generator = idGenerator("node"); @@ -109,7 +110,7 @@ export abstract class Node { if (obj instanceof Future) { // @ts-expect-error (accessing protected method toPlaceholder) - return obj.toPlaceholder(); + return unproxy(obj).toPlaceholder(); } if (obj && typeof obj === "object") { @@ -161,11 +162,15 @@ export abstract class Node { } if (obj instanceof Future) { - futures.add(obj); + // Because some Future instances may be proxied, we need to "un-proxy" + // them to avoid treating it's methods as property accessors. + const future = unproxy(obj); + + futures.add(future); // @ts-expect-error (accessing protected method referencedFutures) - for (let future of obj.referencedFutures()) { - futures.add(future); + for (let f of future.referencedFutures()) { + futures.add(f); } return; } diff --git a/src/Nodes.ts b/src/Nodes.ts index af33d85..2a098ce 100644 --- a/src/Nodes.ts +++ b/src/Nodes.ts @@ -1,12 +1,13 @@ /** * 𐃏 Substrate * @generated file - * 20240617.20240711 + * 20240617.20240715 */ import * as OpenAPI from "substrate/OpenAPI"; import { Node, Options } from "substrate/Node"; import { Trace, Future } from "substrate/Future"; +import { proxyFactory } from "substrate/ProxiedFuture"; // The following type helpers are used to "expand" Node input types to allow them to also accept // instances of their corresponding "Future" types. @@ -969,21 +970,35 @@ export class QueryVectorStoreOutResultsItem extends Future< /** ErrorOut */ export class ErrorOut extends Future { + // prop = type + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** The type of error returned. */ get type() { // @ts-ignore const future = new Future(this._directive.next("type")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = message + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** A message providing more details about the error. */ get message() { // @ts-ignore const future = new Future(this._directive.next("message")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -995,13 +1010,20 @@ export class ErrorOut extends Future { /** ExperimentalOut */ export class ExperimentalOut extends Future { + // prop = output + // prop.type = object + // prop.ref = None + // prop_return_class = Future + // use_proxy = True + /** Response. */ get output() { // @ts-ignore const future = new Future(this._directive.next("output")); // @ts-ignore future._runtimeHint = "object"; - return future; + + return proxyFactory.makeProxy(future); } /** @internal returns the result for `ExperimentalOut` once it's node has been run. */ @@ -1012,13 +1034,20 @@ export class ExperimentalOut extends Future { /** BoxOut */ export class BoxOut extends Future { + // prop = value + // prop.type = None + // prop.ref = None + // prop_return_class = Future + // use_proxy = True + /** The evaluated result. */ get value() { // @ts-ignore const future = new Future(this._directive.next("value")); // @ts-ignore future._runtimeHint = "object"; - return future; + + return proxyFactory.makeProxy(future); } /** @internal returns the result for `BoxOut` once it's node has been run. */ @@ -1029,13 +1058,20 @@ export class BoxOut extends Future { /** IfOut */ export class IfOut extends Future { + // prop = result + // prop.type = None + // prop.ref = None + // prop_return_class = Future + // use_proxy = True + /** Result. Null if `value_if_false` is not provided and `condition` is false. */ get result() { // @ts-ignore const future = new Future(this._directive.next("result")); // @ts-ignore future._runtimeHint = "object"; - return future; + + return proxyFactory.makeProxy(future); } /** @internal returns the result for `IfOut` once it's node has been run. */ @@ -1046,12 +1082,19 @@ export class IfOut extends Future { /** ComputeTextOut */ export class ComputeTextOut extends Future { + // prop = text + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Text response. */ get text() { // @ts-ignore const future = new Future(this._directive.next("text")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -1063,21 +1106,35 @@ export class ComputeTextOut extends Future { /** ComputeJSONOut */ export class ComputeJSONOut extends Future { + // prop = json_object + // prop.type = object + // prop.ref = None + // prop_return_class = Future + // use_proxy = True + /** JSON response. */ get json_object() { // @ts-ignore const future = new Future(this._directive.next("json_object")); // @ts-ignore future._runtimeHint = "object"; - return future; + + return proxyFactory.makeProxy(future); } + // prop = text + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** If the model output could not be parsed to JSON, this is the raw text output. */ get text() { // @ts-ignore const future = new Future(this._directive.next("text")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -1089,6 +1146,12 @@ export class ComputeJSONOut extends Future { /** MultiComputeTextOut */ export class MultiComputeTextOut extends Future { + // prop = choices + // prop.type = array + // prop.ref = None + // prop_return_class = MultiComputeTextOutChoices + // use_proxy = False + /** Response choices. */ get choices() { // @ts-ignore @@ -1097,6 +1160,7 @@ export class MultiComputeTextOut extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -1108,6 +1172,12 @@ export class MultiComputeTextOut extends Future { /** BatchComputeTextOut */ export class BatchComputeTextOut extends Future { + // prop = outputs + // prop.type = array + // prop.ref = None + // prop_return_class = BatchComputeTextOutOutputs + // use_proxy = False + /** Batch outputs. */ get outputs() { // @ts-ignore @@ -1116,6 +1186,7 @@ export class BatchComputeTextOut extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -1127,6 +1198,12 @@ export class BatchComputeTextOut extends Future { /** MultiComputeJSONOut */ export class MultiComputeJSONOut extends Future { + // prop = choices + // prop.type = array + // prop.ref = None + // prop_return_class = MultiComputeJSONOutChoices + // use_proxy = False + /** Response choices. */ get choices() { // @ts-ignore @@ -1135,6 +1212,7 @@ export class MultiComputeJSONOut extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -1146,6 +1224,12 @@ export class MultiComputeJSONOut extends Future { /** BatchComputeJSONOut */ export class BatchComputeJSONOut extends Future { + // prop = outputs + // prop.type = array + // prop.ref = None + // prop_return_class = BatchComputeJSONOutOutputs + // use_proxy = False + /** Batch outputs. */ get outputs() { // @ts-ignore @@ -1154,6 +1238,7 @@ export class BatchComputeJSONOut extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -1165,22 +1250,36 @@ export class BatchComputeJSONOut extends Future { /** Mistral7BInstructChoice */ export class Mistral7BInstructChoice extends Future { + // prop = text + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Text response, if `json_schema` was not provided. */ get text() { // @ts-ignore const future = new Future(this._directive.next("text")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = json_object + // prop.type = object + // prop.ref = None + // prop_return_class = Future + // use_proxy = True + /** JSON response, if `json_schema` was provided. */ get json_object() { // @ts-ignore const future = new Future(this._directive.next("json_object")); // @ts-ignore future._runtimeHint = "object"; - return future; + + return proxyFactory.makeProxy(future); } /** @internal returns the result for `Mistral7BInstructChoice` once it's node has been run. */ @@ -1191,6 +1290,12 @@ export class Mistral7BInstructChoice extends Future { /** Mistral7BInstructOut */ export class Mistral7BInstructOut extends Future { + // prop = choices + // prop.type = array + // prop.ref = None + // prop_return_class = Mistral7BInstructOutChoices + // use_proxy = False + /** Response choices. */ get choices() { // @ts-ignore @@ -1199,6 +1304,7 @@ export class Mistral7BInstructOut extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -1210,22 +1316,36 @@ export class Mistral7BInstructOut extends Future { /** Mixtral8x7BChoice */ export class Mixtral8x7BChoice extends Future { + // prop = text + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Text response, if `json_schema` was not provided. */ get text() { // @ts-ignore const future = new Future(this._directive.next("text")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = json_object + // prop.type = object + // prop.ref = None + // prop_return_class = Future + // use_proxy = True + /** JSON response, if `json_schema` was provided. */ get json_object() { // @ts-ignore const future = new Future(this._directive.next("json_object")); // @ts-ignore future._runtimeHint = "object"; - return future; + + return proxyFactory.makeProxy(future); } /** @internal returns the result for `Mixtral8x7BChoice` once it's node has been run. */ @@ -1236,6 +1356,12 @@ export class Mixtral8x7BChoice extends Future { /** Mixtral8x7BInstructOut */ export class Mixtral8x7BInstructOut extends Future { + // prop = choices + // prop.type = array + // prop.ref = None + // prop_return_class = Mixtral8x7BInstructOutChoices + // use_proxy = False + /** Response choices. */ get choices() { // @ts-ignore @@ -1244,6 +1370,7 @@ export class Mixtral8x7BInstructOut extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -1255,22 +1382,36 @@ export class Mixtral8x7BInstructOut extends Future { /** Llama3Instruct8BChoice */ export class Llama3Instruct8BChoice extends Future { + // prop = text + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Text response. */ get text() { // @ts-ignore const future = new Future(this._directive.next("text")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = json_object + // prop.type = object + // prop.ref = None + // prop_return_class = Future + // use_proxy = True + /** JSON response, if `json_schema` was provided. */ get json_object() { // @ts-ignore const future = new Future(this._directive.next("json_object")); // @ts-ignore future._runtimeHint = "object"; - return future; + + return proxyFactory.makeProxy(future); } /** @internal returns the result for `Llama3Instruct8BChoice` once it's node has been run. */ @@ -1281,6 +1422,12 @@ export class Llama3Instruct8BChoice extends Future { /** Llama3Instruct8BOut */ export class Llama3Instruct8BOut extends Future { + // prop = choices + // prop.type = array + // prop.ref = None + // prop_return_class = Llama3Instruct8BOutChoices + // use_proxy = False + /** Response choices. */ get choices() { // @ts-ignore @@ -1289,6 +1436,7 @@ export class Llama3Instruct8BOut extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -1300,12 +1448,19 @@ export class Llama3Instruct8BOut extends Future { /** Llama3Instruct70BChoice */ export class Llama3Instruct70BChoice extends Future { + // prop = text + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Text response. */ get text() { // @ts-ignore const future = new Future(this._directive.next("text")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -1317,6 +1472,12 @@ export class Llama3Instruct70BChoice extends Future { /** Llama3Instruct70BOut */ export class Llama3Instruct70BOut extends Future { + // prop = choices + // prop.type = array + // prop.ref = None + // prop_return_class = Llama3Instruct70BOutChoices + // use_proxy = False + /** Response choices. */ get choices() { // @ts-ignore @@ -1325,6 +1486,7 @@ export class Llama3Instruct70BOut extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -1336,12 +1498,19 @@ export class Llama3Instruct70BOut extends Future { /** Firellava13BOut */ export class Firellava13BOut extends Future { + // prop = text + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Text response. */ get text() { // @ts-ignore const future = new Future(this._directive.next("text")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -1353,12 +1522,19 @@ export class Firellava13BOut extends Future { /** GenerateImageOut */ export class GenerateImageOut extends Future { + // prop = image_uri + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Base 64-encoded JPEG image bytes, or a hosted image url if `store` is provided. */ get image_uri() { // @ts-ignore const future = new Future(this._directive.next("image_uri")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -1370,6 +1546,12 @@ export class GenerateImageOut extends Future { /** MultiGenerateImageOut */ export class MultiGenerateImageOut extends Future { + // prop = outputs + // prop.type = array + // prop.ref = None + // prop_return_class = MultiGenerateImageOutOutputs + // use_proxy = False + /** Generated images. */ get outputs() { // @ts-ignore @@ -1378,6 +1560,7 @@ export class MultiGenerateImageOut extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -1389,21 +1572,35 @@ export class MultiGenerateImageOut extends Future { /** StableDiffusionImage */ export class StableDiffusionImage extends Future { + // prop = image_uri + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Base 64-encoded JPEG image bytes, or a hosted image url if `store` is provided. */ get image_uri() { // @ts-ignore const future = new Future(this._directive.next("image_uri")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = seed + // prop.type = integer + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** The random noise seed used for generation. */ get seed() { // @ts-ignore const future = new Future(this._directive.next("seed")); // @ts-ignore future._runtimeHint = "number"; + return future; } @@ -1415,6 +1612,12 @@ export class StableDiffusionImage extends Future { /** StableDiffusionXLOut */ export class StableDiffusionXLOut extends Future { + // prop = outputs + // prop.type = array + // prop.ref = None + // prop_return_class = StableDiffusionXLOutOutputs + // use_proxy = False + /** Generated images. */ get outputs() { // @ts-ignore @@ -1423,6 +1626,7 @@ export class StableDiffusionXLOut extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -1434,6 +1638,12 @@ export class StableDiffusionXLOut extends Future { /** StableDiffusionXLLightningOut */ export class StableDiffusionXLLightningOut extends Future { + // prop = outputs + // prop.type = array + // prop.ref = None + // prop_return_class = StableDiffusionXLLightningOutOutputs + // use_proxy = False + /** Generated images. */ get outputs() { // @ts-ignore @@ -1442,6 +1652,7 @@ export class StableDiffusionXLLightningOut extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -1453,6 +1664,12 @@ export class StableDiffusionXLLightningOut extends Future { /** StableDiffusionXLIPAdapterOut */ export class StableDiffusionXLIPAdapterOut extends Future { + // prop = outputs + // prop.type = array + // prop.ref = None + // prop_return_class = StableDiffusionXLIPAdapterOutOutputs + // use_proxy = False + /** Generated images. */ get outputs() { // @ts-ignore @@ -1461,6 +1678,7 @@ export class StableDiffusionXLIPAdapterOut extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -1472,6 +1690,12 @@ export class StableDiffusionXLIPAdapterOut extends Future { /** StableDiffusionXLControlNetOut */ export class StableDiffusionXLControlNetOut extends Future { + // prop = outputs + // prop.type = array + // prop.ref = None + // prop_return_class = StableDiffusionXLControlNetOutOutputs + // use_proxy = False + /** Generated images. */ get outputs() { // @ts-ignore @@ -1480,6 +1704,7 @@ export class StableDiffusionXLControlNetOut extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -1491,12 +1716,19 @@ export class StableDiffusionXLControlNetOut extends Future { /** InpaintImageOut */ export class InpaintImageOut extends Future { + // prop = image_uri + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Base 64-encoded JPEG image bytes, or a hosted image url if `store` is provided. */ get image_uri() { // @ts-ignore const future = new Future(this._directive.next("image_uri")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -1508,6 +1740,12 @@ export class InpaintImageOut extends Future { /** MultiInpaintImageOut */ export class MultiInpaintImageOut extends Future { + // prop = outputs + // prop.type = array + // prop.ref = None + // prop_return_class = MultiInpaintImageOutOutputs + // use_proxy = False + /** Generated images. */ get outputs() { // @ts-ignore @@ -1516,6 +1754,7 @@ export class MultiInpaintImageOut extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -1527,6 +1766,12 @@ export class MultiInpaintImageOut extends Future { /** StableDiffusionXLInpaintOut */ export class StableDiffusionXLInpaintOut extends Future { + // prop = outputs + // prop.type = array + // prop.ref = None + // prop_return_class = StableDiffusionXLInpaintOutOutputs + // use_proxy = False + /** Generated images. */ get outputs() { // @ts-ignore @@ -1535,6 +1780,7 @@ export class StableDiffusionXLInpaintOut extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -1546,39 +1792,67 @@ export class StableDiffusionXLInpaintOut extends Future { /** BoundingBox */ export class BoundingBox extends Future { + // prop = x1 + // prop.type = number + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Top left corner x. */ get x1() { // @ts-ignore const future = new Future(this._directive.next("x1")); // @ts-ignore future._runtimeHint = "number"; + return future; } + // prop = y1 + // prop.type = number + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Top left corner y. */ get y1() { // @ts-ignore const future = new Future(this._directive.next("y1")); // @ts-ignore future._runtimeHint = "number"; + return future; } + // prop = x2 + // prop.type = number + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Bottom right corner x. */ get x2() { // @ts-ignore const future = new Future(this._directive.next("x2")); // @ts-ignore future._runtimeHint = "number"; + return future; } + // prop = y2 + // prop.type = number + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Bottom right corner y. */ get y2() { // @ts-ignore const future = new Future(this._directive.next("y2")); // @ts-ignore future._runtimeHint = "number"; + return future; } @@ -1590,21 +1864,35 @@ export class BoundingBox extends Future { /** Point */ export class Point extends Future { + // prop = x + // prop.type = integer + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** X position. */ get x() { // @ts-ignore const future = new Future(this._directive.next("x")); // @ts-ignore future._runtimeHint = "number"; + return future; } + // prop = y + // prop.type = integer + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Y position. */ get y() { // @ts-ignore const future = new Future(this._directive.next("y")); // @ts-ignore future._runtimeHint = "number"; + return future; } @@ -1616,12 +1904,19 @@ export class Point extends Future { /** EraseImageOut */ export class EraseImageOut extends Future { + // prop = image_uri + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Base 64-encoded JPEG image bytes, or a hosted image url if `store` is provided. */ get image_uri() { // @ts-ignore const future = new Future(this._directive.next("image_uri")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -1633,12 +1928,19 @@ export class EraseImageOut extends Future { /** BigLaMaOut */ export class BigLaMaOut extends Future { + // prop = image_uri + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Base 64-encoded JPEG image bytes, or a hosted image url if `store` is provided. */ get image_uri() { // @ts-ignore const future = new Future(this._directive.next("image_uri")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -1650,12 +1952,19 @@ export class BigLaMaOut extends Future { /** RemoveBackgroundOut */ export class RemoveBackgroundOut extends Future { + // prop = image_uri + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Base 64-encoded JPEG image bytes, or a hosted image url if `store` is provided. */ get image_uri() { // @ts-ignore const future = new Future(this._directive.next("image_uri")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -1667,12 +1976,19 @@ export class RemoveBackgroundOut extends Future { /** DISISNetOut */ export class DISISNetOut extends Future { + // prop = image_uri + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Base 64-encoded JPEG image bytes, or a hosted image url if `store` is provided. */ get image_uri() { // @ts-ignore const future = new Future(this._directive.next("image_uri")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -1684,12 +2000,19 @@ export class DISISNetOut extends Future { /** UpscaleImageOut */ export class UpscaleImageOut extends Future { + // prop = image_uri + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Base 64-encoded JPEG image bytes, or a hosted image url if `store` is provided. */ get image_uri() { // @ts-ignore const future = new Future(this._directive.next("image_uri")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -1701,12 +2024,19 @@ export class UpscaleImageOut extends Future { /** SegmentUnderPointOut */ export class SegmentUnderPointOut extends Future { + // prop = mask_image_uri + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Detected segments in 'mask image' format. Base 64-encoded JPEG image bytes, or a hosted image url if `store` is provided. */ get mask_image_uri() { // @ts-ignore const future = new Future(this._directive.next("mask_image_uri")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -1718,12 +2048,19 @@ export class SegmentUnderPointOut extends Future { /** SegmentAnythingOut */ export class SegmentAnythingOut extends Future { + // prop = mask_image_uri + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Detected segments in 'mask image' format. Base 64-encoded JPEG image bytes, or a hosted image url if `store` is provided. */ get mask_image_uri() { // @ts-ignore const future = new Future(this._directive.next("mask_image_uri")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -1735,39 +2072,67 @@ export class SegmentAnythingOut extends Future { /** TranscribedWord */ export class TranscribedWord extends Future { + // prop = word + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Text of word. */ get word() { // @ts-ignore const future = new Future(this._directive.next("word")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = start + // prop.type = number + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** (Optional) Start time of word, in seconds. */ get start() { // @ts-ignore const future = new Future(this._directive.next("start")); // @ts-ignore future._runtimeHint = "number"; + return future; } + // prop = end + // prop.type = number + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** (Optional) End time of word, in seconds. */ get end() { // @ts-ignore const future = new Future(this._directive.next("end")); // @ts-ignore future._runtimeHint = "number"; + return future; } + // prop = speaker + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** (Optional) ID of speaker, if `diarize` is enabled. */ get speaker() { // @ts-ignore const future = new Future(this._directive.next("speaker")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -1779,48 +2144,83 @@ export class TranscribedWord extends Future { /** TranscribedSegment */ export class TranscribedSegment extends Future { + // prop = text + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Text of segment. */ get text() { // @ts-ignore const future = new Future(this._directive.next("text")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = start + // prop.type = number + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Start time of segment, in seconds. */ get start() { // @ts-ignore const future = new Future(this._directive.next("start")); // @ts-ignore future._runtimeHint = "number"; + return future; } + // prop = end + // prop.type = number + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** End time of segment, in seconds. */ get end() { // @ts-ignore const future = new Future(this._directive.next("end")); // @ts-ignore future._runtimeHint = "number"; + return future; } + // prop = speaker + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** (Optional) ID of speaker, if `diarize` is enabled. */ get speaker() { // @ts-ignore const future = new Future(this._directive.next("speaker")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = words + // prop.type = array + // prop.ref = None + // prop_return_class = TranscribedSegmentWords + // use_proxy = False + /** (Optional) Aligned words, if `align` is enabled. */ get words() { // @ts-ignore const future = new TranscribedSegmentWords(this._directive.next("words")); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -1832,21 +2232,35 @@ export class TranscribedSegment extends Future { /** ChapterMarker */ export class ChapterMarker extends Future { + // prop = title + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Chapter title. */ get title() { // @ts-ignore const future = new Future(this._directive.next("title")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = start + // prop.type = number + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Start time of chapter, in seconds. */ get start() { // @ts-ignore const future = new Future(this._directive.next("start")); // @ts-ignore future._runtimeHint = "number"; + return future; } @@ -1858,15 +2272,28 @@ export class ChapterMarker extends Future { /** TranscribeSpeechOut */ export class TranscribeSpeechOut extends Future { + // prop = text + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Transcribed text. */ get text() { // @ts-ignore const future = new Future(this._directive.next("text")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = segments + // prop.type = array + // prop.ref = None + // prop_return_class = TranscribeSpeechOutSegments + // use_proxy = False + /** (Optional) Transcribed segments, if `segment` is enabled. */ get segments() { // @ts-ignore @@ -1875,9 +2302,16 @@ export class TranscribeSpeechOut extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } + // prop = chapters + // prop.type = array + // prop.ref = None + // prop_return_class = TranscribeSpeechOutChapters + // use_proxy = False + /** (Optional) Chapter markers, if `suggest_chapters` is enabled. */ get chapters() { // @ts-ignore @@ -1886,6 +2320,7 @@ export class TranscribeSpeechOut extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -1897,12 +2332,19 @@ export class TranscribeSpeechOut extends Future { /** GenerateSpeechOut */ export class GenerateSpeechOut extends Future { + // prop = audio_uri + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Base 64-encoded WAV audio bytes, or a hosted audio url if `store` is provided. */ get audio_uri() { // @ts-ignore const future = new Future(this._directive.next("audio_uri")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -1914,12 +2356,19 @@ export class GenerateSpeechOut extends Future { /** XTTSV2Out */ export class XTTSV2Out extends Future { + // prop = audio_uri + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Base 64-encoded WAV audio bytes, or a hosted audio url if `store` is provided. */ get audio_uri() { // @ts-ignore const future = new Future(this._directive.next("audio_uri")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -1931,31 +2380,52 @@ export class XTTSV2Out extends Future { /** Embedding */ export class Embedding extends Future { + // prop = vector + // prop.type = array + // prop.ref = None + // prop_return_class = EmbeddingVector + // use_proxy = False + /** Embedding vector. */ get vector() { // @ts-ignore const future = new EmbeddingVector(this._directive.next("vector")); // @ts-ignore future._runtimeHint = "array"; + return future; } + // prop = doc_id + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** (Optional) Vector store document ID. */ get doc_id() { // @ts-ignore const future = new Future(this._directive.next("doc_id")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = metadata + // prop.type = object + // prop.ref = None + // prop_return_class = Future + // use_proxy = True + /** (Optional) Vector store document metadata. */ get metadata() { // @ts-ignore const future = new Future(this._directive.next("metadata")); // @ts-ignore future._runtimeHint = "object"; - return future; + + return proxyFactory.makeProxy(future); } /** @internal returns the result for `Embedding` once it's node has been run. */ @@ -1966,12 +2436,19 @@ export class Embedding extends Future { /** EmbedTextOut */ export class EmbedTextOut extends Future { + // prop = embedding + // prop.type = object + // prop.ref = #/components/schemas/Embedding + // prop_return_class = Embedding + // use_proxy = False + /** Generated embedding. */ get embedding() { // @ts-ignore const future = new Embedding(this._directive.next("embedding")); // @ts-ignore future._runtimeHint = "object"; + return future; } @@ -1983,30 +2460,51 @@ export class EmbedTextOut extends Future { /** EmbedTextItem */ export class EmbedTextItem extends Future { + // prop = text + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Text to embed. */ get text() { // @ts-ignore const future = new Future(this._directive.next("text")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = metadata + // prop.type = object + // prop.ref = None + // prop_return_class = Future + // use_proxy = True + /** (Optional) Metadata that can be used to query the vector store. Ignored if `collection_name` is unset. */ get metadata() { // @ts-ignore const future = new Future(this._directive.next("metadata")); // @ts-ignore future._runtimeHint = "object"; - return future; + + return proxyFactory.makeProxy(future); } + // prop = doc_id + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** (Optional) Vector store document ID. Ignored if `collection_name` is unset. */ get doc_id() { // @ts-ignore const future = new Future(this._directive.next("doc_id")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -2018,6 +2516,12 @@ export class EmbedTextItem extends Future { /** MultiEmbedTextOut */ export class MultiEmbedTextOut extends Future { + // prop = embeddings + // prop.type = array + // prop.ref = None + // prop_return_class = MultiEmbedTextOutEmbeddings + // use_proxy = False + /** Generated embeddings. */ get embeddings() { // @ts-ignore @@ -2026,6 +2530,7 @@ export class MultiEmbedTextOut extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -2037,12 +2542,19 @@ export class MultiEmbedTextOut extends Future { /** JinaV2Out */ export class JinaV2Out extends Future { + // prop = embeddings + // prop.type = array + // prop.ref = None + // prop_return_class = JinaV2OutEmbeddings + // use_proxy = False + /** Generated embeddings. */ get embeddings() { // @ts-ignore const future = new JinaV2OutEmbeddings(this._directive.next("embeddings")); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -2054,12 +2566,19 @@ export class JinaV2Out extends Future { /** EmbedImageOut */ export class EmbedImageOut extends Future { + // prop = embedding + // prop.type = object + // prop.ref = #/components/schemas/Embedding + // prop_return_class = Embedding + // use_proxy = False + /** Generated embedding. */ get embedding() { // @ts-ignore const future = new Embedding(this._directive.next("embedding")); // @ts-ignore future._runtimeHint = "object"; + return future; } @@ -2071,21 +2590,35 @@ export class EmbedImageOut extends Future { /** EmbedImageItem */ export class EmbedImageItem extends Future { + // prop = image_uri + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Image to embed. */ get image_uri() { // @ts-ignore const future = new Future(this._directive.next("image_uri")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = doc_id + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** (Optional) Vector store document ID. Ignored if `collection_name` is unset. */ get doc_id() { // @ts-ignore const future = new Future(this._directive.next("doc_id")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -2097,39 +2630,67 @@ export class EmbedImageItem extends Future { /** EmbedTextOrImageItem */ export class EmbedTextOrImageItem extends Future { + // prop = image_uri + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Image to embed. */ get image_uri() { // @ts-ignore const future = new Future(this._directive.next("image_uri")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = text + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Text to embed. */ get text() { // @ts-ignore const future = new Future(this._directive.next("text")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = metadata + // prop.type = object + // prop.ref = None + // prop_return_class = Future + // use_proxy = True + /** Metadata that can be used to query the vector store. Ignored if `collection_name` is unset. */ get metadata() { // @ts-ignore const future = new Future(this._directive.next("metadata")); // @ts-ignore future._runtimeHint = "object"; - return future; + + return proxyFactory.makeProxy(future); } + // prop = doc_id + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Vector store document ID. Ignored if `collection_name` is unset. */ get doc_id() { // @ts-ignore const future = new Future(this._directive.next("doc_id")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -2141,6 +2702,12 @@ export class EmbedTextOrImageItem extends Future { /** MultiEmbedImageOut */ export class MultiEmbedImageOut extends Future { + // prop = embeddings + // prop.type = array + // prop.ref = None + // prop_return_class = MultiEmbedImageOutEmbeddings + // use_proxy = False + /** Generated embeddings. */ get embeddings() { // @ts-ignore @@ -2149,6 +2716,7 @@ export class MultiEmbedImageOut extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -2160,12 +2728,19 @@ export class MultiEmbedImageOut extends Future { /** CLIPOut */ export class CLIPOut extends Future { + // prop = embeddings + // prop.type = array + // prop.ref = None + // prop_return_class = CLIPOutEmbeddings + // use_proxy = False + /** Generated embeddings. */ get embeddings() { // @ts-ignore const future = new CLIPOutEmbeddings(this._directive.next("embeddings")); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -2177,21 +2752,35 @@ export class CLIPOut extends Future { /** FindOrCreateVectorStoreOut */ export class FindOrCreateVectorStoreOut extends Future { + // prop = collection_name + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Vector store name. */ get collection_name() { // @ts-ignore const future = new Future(this._directive.next("collection_name")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = model + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Selected embedding model. */ get model() { // @ts-ignore const future = new Future(this._directive.next("model")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -2203,12 +2792,19 @@ export class FindOrCreateVectorStoreOut extends Future { /** ListVectorStoresOut */ export class ListVectorStoresOut extends Future { + // prop = items + // prop.type = array + // prop.ref = None + // prop_return_class = ListVectorStoresOutItems + // use_proxy = False + /** List of vector stores. */ get items() { // @ts-ignore const future = new ListVectorStoresOutItems(this._directive.next("items")); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -2220,21 +2816,35 @@ export class ListVectorStoresOut extends Future { /** DeleteVectorStoreOut */ export class DeleteVectorStoreOut extends Future { + // prop = collection_name + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Vector store name. */ get collection_name() { // @ts-ignore const future = new Future(this._directive.next("collection_name")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = model + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Selected embedding model. */ get model() { // @ts-ignore const future = new Future(this._directive.next("model")); // @ts-ignore future._runtimeHint = "string"; + return future; } @@ -2246,31 +2856,52 @@ export class DeleteVectorStoreOut extends Future { /** Canonical representation of document with embedding vector. */ export class Vector extends Future { + // prop = id + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Document ID. */ get id() { // @ts-ignore const future = new Future(this._directive.next("id")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = vector + // prop.type = array + // prop.ref = None + // prop_return_class = VectorVector + // use_proxy = False + /** Embedding vector. */ get vector() { // @ts-ignore const future = new VectorVector(this._directive.next("vector")); // @ts-ignore future._runtimeHint = "array"; + return future; } + // prop = metadata + // prop.type = object + // prop.ref = None + // prop_return_class = Future + // use_proxy = True + /** Document metadata. */ get metadata() { // @ts-ignore const future = new Future(this._directive.next("metadata")); // @ts-ignore future._runtimeHint = "object"; - return future; + + return proxyFactory.makeProxy(future); } /** @internal returns the result for `Vector` once it's node has been run. */ @@ -2281,12 +2912,19 @@ export class Vector extends Future { /** FetchVectorsOut */ export class FetchVectorsOut extends Future { + // prop = vectors + // prop.type = array + // prop.ref = None + // prop_return_class = FetchVectorsOutVectors + // use_proxy = False + /** Retrieved vectors. */ get vectors() { // @ts-ignore const future = new FetchVectorsOutVectors(this._directive.next("vectors")); // @ts-ignore future._runtimeHint = "array"; + return future; } @@ -2298,12 +2936,19 @@ export class FetchVectorsOut extends Future { /** UpdateVectorsOut */ export class UpdateVectorsOut extends Future { + // prop = count + // prop.type = integer + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Number of vectors modified. */ get count() { // @ts-ignore const future = new Future(this._directive.next("count")); // @ts-ignore future._runtimeHint = "number"; + return future; } @@ -2315,12 +2960,19 @@ export class UpdateVectorsOut extends Future { /** DeleteVectorsOut */ export class DeleteVectorsOut extends Future { + // prop = count + // prop.type = integer + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Number of vectors modified. */ get count() { // @ts-ignore const future = new Future(this._directive.next("count")); // @ts-ignore future._runtimeHint = "number"; + return future; } @@ -2332,31 +2984,52 @@ export class DeleteVectorsOut extends Future { /** UpdateVectorParams */ export class UpdateVectorParams extends Future { + // prop = id + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Document ID. */ get id() { // @ts-ignore const future = new Future(this._directive.next("id")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = vector + // prop.type = array + // prop.ref = None + // prop_return_class = UpdateVectorParamsVector + // use_proxy = False + /** (Optional) Embedding vector. */ get vector() { // @ts-ignore const future = new UpdateVectorParamsVector(this._directive.next("vector")); // @ts-ignore future._runtimeHint = "array"; + return future; } + // prop = metadata + // prop.type = object + // prop.ref = None + // prop_return_class = Future + // use_proxy = True + /** (Optional) Document metadata. */ get metadata() { // @ts-ignore const future = new Future(this._directive.next("metadata")); // @ts-ignore future._runtimeHint = "object"; - return future; + + return proxyFactory.makeProxy(future); } /** @internal returns the result for `UpdateVectorParams` once it's node has been run. */ @@ -2367,24 +3040,44 @@ export class UpdateVectorParams extends Future { /** VectorStoreQueryResult */ export class VectorStoreQueryResult extends Future { + // prop = id + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Document ID. */ get id() { // @ts-ignore const future = new Future(this._directive.next("id")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = distance + // prop.type = number + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** Similarity score. */ get distance() { // @ts-ignore const future = new Future(this._directive.next("distance")); // @ts-ignore future._runtimeHint = "number"; + return future; } + // prop = vector + // prop.type = array + // prop.ref = None + // prop_return_class = VectorStoreQueryResultVector + // use_proxy = False + /** (Optional) Embedding vector. */ get vector() { // @ts-ignore @@ -2393,16 +3086,24 @@ export class VectorStoreQueryResult extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } + // prop = metadata + // prop.type = object + // prop.ref = None + // prop_return_class = Future + // use_proxy = True + /** (Optional) Document metadata. */ get metadata() { // @ts-ignore const future = new Future(this._directive.next("metadata")); // @ts-ignore future._runtimeHint = "object"; - return future; + + return proxyFactory.makeProxy(future); } /** @internal returns the result for `VectorStoreQueryResult` once it's node has been run. */ @@ -2413,6 +3114,12 @@ export class VectorStoreQueryResult extends Future { /** QueryVectorStoreOut */ export class QueryVectorStoreOut extends Future { + // prop = results + // prop.type = array + // prop.ref = None + // prop_return_class = QueryVectorStoreOutResults + // use_proxy = False + /** Query results. */ get results() { // @ts-ignore @@ -2421,24 +3128,39 @@ export class QueryVectorStoreOut extends Future { ); // @ts-ignore future._runtimeHint = "array"; + return future; } + // prop = collection_name + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** (Optional) Vector store name. */ get collection_name() { // @ts-ignore const future = new Future(this._directive.next("collection_name")); // @ts-ignore future._runtimeHint = "string"; + return future; } + // prop = model + // prop.type = string + // prop.ref = None + // prop_return_class = Future + // use_proxy = False + /** (Optional) Selected embedding model. */ get model() { // @ts-ignore const future = new Future(this._directive.next("model")); // @ts-ignore future._runtimeHint = "string"; + return future; } diff --git a/src/ProxiedFuture.ts b/src/ProxiedFuture.ts new file mode 100644 index 0000000..fddc534 --- /dev/null +++ b/src/ProxiedFuture.ts @@ -0,0 +1,99 @@ +import { Future, Trace } from "substrate/Future"; + +// Only Futures that resolve to string | number are legal property accessors +type FutureTable = Record>; + +export const ID_PREFIX = "$$ID:"; +export const GET_TARGET = "$$GET_TARGET"; + +/** + * @internal + */ +export const makeProxyFactory = (futureTable: FutureTable = {}) => { + const futureId = (future: Future): string => { + // @ts-ignore (accessing protected property: _id) + return `${ID_PREFIX}${future._id}`; + }; + + const makeProxy = (future: Future): any => { + return new Proxy(future, { + has(target: Future, prop: any) { + // We're using a *special* property (GET_TARGET) as a means to + // test whether the target object is a Proxied Future or not. + if (prop === GET_TARGET) return true; + + // Otherwise, behave normally. + return prop in target; + }, + + get(target: Future, prop: any, _receiver: any) { + // We're using a *special* property (GET_TARGET) as a means to + // retrieve the underlying Future (unproxied) + if (prop === GET_TARGET) return target; + + if (prop === Symbol.toPrimitive) { + // When the prop is not a primitive (number, string, Symbol) it will be attempted + // to be converted into one. This case will happen when the prop is a Future. + // + // Because only primitive types can be used as property accessors, what we're doing + // here is returning a Future ID, which is a string. We use this specially formatted + // ID to store the original Future in a lookup table we maintain as some hidden + // state in the SDK. + // + // When the prop (Future ID) is used as an accessor (eg. in the case of "bracket" + // access) we will use the returned Future ID here and look up the referenced Future + // when constructing new proxied Futures (in it's TraceProps). + return () => { + const utarget = unproxy(target); + const id = futureId(utarget); + futureTable[id] = utarget; // store in lookup table + return id; + }; + } + + const nextProp = prop.startsWith(ID_PREFIX) + ? // When the prop is a Future ID, we will lookup the corresponding Future + // so that we can use it as a TraceProp in the resulting new Future. + futureTable[prop]! + : // Otherwise the prop is not a future (always converted to string) + (prop as string); + + // @ts-ignore (access protected prop: _directive) + const trace = target._directive.next(nextProp); + if (!(trace instanceof Trace)) throw "something's not right."; + + return makeProxy(new Future(trace)); + }, + }); + }; + + return { + makeProxy, + }; +}; + +/** + * @internal + * Returns `true` when `Future` is proxied. + */ +export const isProxy = (future: Future) => { + // We return true when checking for this property on Proxied Futures. + return GET_TARGET in future; +}; + +/** + * @internal + * Returns the un-proxied `Future` when it is proxied. + */ +export const unproxy = (maybeProxiedFuture: Future): Future => { + if (!isProxy(maybeProxiedFuture)) return maybeProxiedFuture; + // @ts-ignore (using "virtual" property to access underlying proxy target) + return maybeProxiedFuture.$$GET_TARGET as Future; +}; + +/** + * @internal + * We instantiate a proxyFactory as a side effect of importing this file so that we can + * share the hidden-state of the `FutureTable` across the the SDK + */ +export const proxyFactory = makeProxyFactory(); diff --git a/src/index.ts b/src/index.ts index bf76dd9..7d39e7a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ /** * 𐃏 Substrate TypeScript SDK * @generated file - * 20240617.20240711 + * 20240617.20240715 */ export { SubstrateError } from "substrate/Error"; diff --git a/tests/ProxiedFuture.test.ts b/tests/ProxiedFuture.test.ts new file mode 100644 index 0000000..d6b1b45 --- /dev/null +++ b/tests/ProxiedFuture.test.ts @@ -0,0 +1,116 @@ +import { expect, describe, test } from "vitest"; +import { Future, Trace } from "substrate/Future"; +import { Node } from "substrate/Node"; +import { makeProxyFactory, isProxy, unproxy } from "substrate/ProxiedFuture"; + +class FooFuture extends Future {} +class FooNode extends Node {} + +const node = (id: string = "") => new FooNode({}, { id }); + +describe("ProxiedFuture", () => { + describe("ProxyFactory", () => { + test("makeProxy", () => { + const proxyFactory = makeProxyFactory(); + const f = new FooFuture(new Trace([], node())); + const p = proxyFactory.makeProxy(f); + // Proxy is an instance of Future + expect(p).instanceof(Future); + }); + + test("isProxy", () => { + const proxyFactory = makeProxyFactory(); + const f = new FooFuture(new Trace([], node())); + const p = proxyFactory.makeProxy(f); + // We can detect whether the proxied Future is a proxy + expect(isProxy(f)).toEqual(false); + expect(isProxy(p)).toEqual(true); + }); + }); + + describe("Proxy", () => { + test("unproxy (returns unproxied Future)", () => { + const proxyFactory = makeProxyFactory(); + const f = new FooFuture(new Trace([], node())); + const p = proxyFactory.makeProxy(f); + const up = unproxy(p); + expect(up).instanceof(Future); + expect(isProxy(up)).toEqual(false); + }); + + test("arbitrary property access (. notation)", () => { + const proxyFactory = makeProxyFactory(); + const f = new FooFuture(new Trace([], node("123"))); + const p = proxyFactory.makeProxy(f); + + // @ts-ignore (properties don't exist) + const f1 = p.a.b.c; + expect(f1).instanceof(Future); + expect(isProxy(f1)).toEqual(true); + + // @ts-ignore ("virtual property" doesn't exist) + const up = unproxy(f1); + const json = up.toJSON(); + + expect(json.directive).toEqual({ + op_stack: [ + { accessor: "attr", future_id: null, key: "a" }, + { accessor: "attr", future_id: null, key: "b" }, + { accessor: "attr", future_id: null, key: "c" }, + ], + origin_node_id: "123", + type: "trace", + }); + }); + + test("arbitrary property and index access (brackets)", () => { + const proxyFactory = makeProxyFactory(); + const f = new FooFuture(new Trace([], node("123"))); + const p = proxyFactory.makeProxy(f); + + const f1 = p["a"][0][1]; + expect(f1).instanceof(Future); + expect(isProxy(f1)).toEqual(true); + + const up = unproxy(f1); + const json = up.toJSON(); + + expect(json.directive).toEqual({ + op_stack: [ + { accessor: "attr", future_id: null, key: "a" }, + { accessor: "item", future_id: null, key: 0 }, + { accessor: "item", future_id: null, key: 1 }, + ], + origin_node_id: "123", + type: "trace", + }); + }); + + // TODO(liam): I'm not sure why this test doesn't work yet, but it does work in example code + test.skip("using Future values as proxy accessors", () => { + const proxyFactory = makeProxyFactory(); + const f = new FooFuture(new Trace([], node("123"))); + const p = proxyFactory.makeProxy(f); + + const a = new FooFuture(new Trace([], node("456"))); + + // non index-types are illegal in the type system, so we're casting to any here. + const f1 = p[a as any]; + + expect(f1).instanceof(Future); + expect(isProxy(f1)).toEqual(true); + + const up = unproxy(f1); + const json = up.toJSON(); + + expect(json.directive).toEqual({ + op_stack: [ + // @ts-ignore + { accessor: "attr", future_id: a._id, key: null }, + ], + origin_node_id: "123", + type: "trace", + }); + }); + }); +}); From ee03c537cdcc280253334aec8e42d9546ab3302e Mon Sep 17 00:00:00 2001 From: Liam Griffiths Date: Tue, 16 Jul 2024 13:15:50 -0400 Subject: [PATCH 2/4] Remove debug example --- out.json | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 out.json diff --git a/out.json b/out.json deleted file mode 100644 index e69de29..0000000 From 3e146bad9545d99bc36140eeda2b92d5ce61d45d Mon Sep 17 00:00:00 2001 From: Liam Griffiths Date: Tue, 16 Jul 2024 13:53:42 -0400 Subject: [PATCH 3/4] Update bug example --- examples/arbitrary-future-properties.ts | 1 + examples/bug.ts | 34 ++++++++++--------------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/examples/arbitrary-future-properties.ts b/examples/arbitrary-future-properties.ts index ee74cda..ebc5ffb 100755 --- a/examples/arbitrary-future-properties.ts +++ b/examples/arbitrary-future-properties.ts @@ -33,6 +33,7 @@ async function main() { const result = new Box( { value: { + x: latin.future.value.xyz, a: latin.future.value[numbers.future.value[0]], b: greek.future.value[latin.future.value[1]], ab: sb.concat(greek.future.value.a, greek.future.value.b), diff --git a/examples/bug.ts b/examples/bug.ts index 1dd5be1..c47484c 100755 --- a/examples/bug.ts +++ b/examples/bug.ts @@ -7,28 +7,22 @@ async function main() { const substrate = new Substrate({ apiKey: SUBSTRATE_API_KEY }); - const data = new Box( - { - value: { - letters: ["a", "b"], - index: 0, - }, - } - ); - - const selected = new Box( - { - value: ob4: sb.get( - data.future.value.object, - data.future.value.letters[1], - ), - }, + const data = new Box({ + value: { + letters: ["a", "b"], + index: 0, }, - { id: "selected" }, - ); + }); - // console.log(JSON.stringify(Substrate.serialize(selected), null, 2)); - // return; + const selected = new Box({ + value: { + example1: sb.get( + data.future.value.object, + data.future.value.letters[1], + ), + example2: data.future.value.letters[data.future.value.index], + }, + }); const res = await substrate.run(selected); console.log(JSON.stringify(res.json, null, 2)); From 4f1685cc6c9e1bc07f1db6bf1c3d6ee98b7ef56d Mon Sep 17 00:00:00 2001 From: Liam Griffiths Date: Wed, 17 Jul 2024 10:14:48 -0400 Subject: [PATCH 4/4] Allow non-proxied `Futures` to be used a "bracket" index types --- examples/arbitrary-future-properties.ts | 76 ++++++++++++++++--------- examples/bug.ts | 6 +- src/Future.ts | 11 +++- src/ProxiedFuture.ts | 38 ++++++------- src/index.ts | 4 ++ tests/ProxiedFuture.test.ts | 20 +++---- 6 files changed, 92 insertions(+), 63 deletions(-) diff --git a/examples/arbitrary-future-properties.ts b/examples/arbitrary-future-properties.ts index ebc5ffb..2c9675d 100755 --- a/examples/arbitrary-future-properties.ts +++ b/examples/arbitrary-future-properties.ts @@ -1,6 +1,6 @@ #!/usr/bin/env -S npx ts-node --transpileOnly -import { Substrate, Box, sb } from "substrate"; +import { Substrate, Box, ComputeText, ComputeJSON, sb } from "substrate"; async function main() { const SUBSTRATE_API_KEY = process.env["SUBSTRATE_API_KEY"]; @@ -9,37 +9,59 @@ async function main() { apiKey: SUBSTRATE_API_KEY, }); - const numbers = new Box( - { - value: [0, 1], - }, - ); + const numbers = new Box({ + value: [0, 1], + }); + + const latin = new Box({ + value: ["a", "b"], + }); - const latin = new Box( - { - value: ["a", "b"], + const greek = new Box({ + value: { + a: "α", + b: "β", }, - ); + }); + + const proxyAccessor = new Box({ value: { property: "text" } }); + + const d = new ComputeText({ + prompt: "What is the character for the Latin 'D' in the Cyrillic alphabet? (just tell me the character only)", + max_tokens: 1, + }); - const greek = new Box( - { - value: { - a: "α", - b: "β", + const three = new ComputeText({ + prompt: "What number comes after '2'? (just tell me the character only)", + max_tokens: 1, + }); + const number3 = sb.jq(three.future, ".text | tonumber"); + + const hebrew = new ComputeJSON({ + prompt: "what are the characters of the Hebrew alphabet (in unicode, eg. א )?", + json_schema: { + type: "object", + properties: { + characters: { + type: "array", + items: { + type: "string", + description: "single character", + } + } } - }, - ); - - const result = new Box( - { - value: { - x: latin.future.value.xyz, - a: latin.future.value[numbers.future.value[0]], - b: greek.future.value[latin.future.value[1]], - ab: sb.concat(greek.future.value.a, greek.future.value.b), - }, } - ); + }); + + const result = new Box({ + value: { + a: latin.future.value[numbers.future.value[0]], + b: greek.future.value[latin.future.value[1]], + c: hebrew.future.json_object.characters[number3 as any], + ab: sb.concat(greek.future.value.a, greek.future.value.b), + d: sb.get(d.future, proxyAccessor.future.value.property), + }, + }); const res = await substrate.run(result); console.log(res.get(result)); diff --git a/examples/bug.ts b/examples/bug.ts index c47484c..01060f8 100755 --- a/examples/bug.ts +++ b/examples/bug.ts @@ -16,11 +16,11 @@ async function main() { const selected = new Box({ value: { - example1: sb.get( - data.future.value.object, + example1: sb.concat( + data.future.value.letters[0], data.future.value.letters[1], ), - example2: data.future.value.letters[data.future.value.index], + // example2: data.future.value.letters[data.future.value.index], }, }); diff --git a/src/Future.ts b/src/Future.ts index 62f78b0..da166da 100644 --- a/src/Future.ts +++ b/src/Future.ts @@ -1,6 +1,6 @@ import { idGenerator } from "substrate/idGenerator"; import { Node } from "substrate/Node"; -import { unproxy } from "./ProxiedFuture"; +import { unproxy, proxyFactory } from "./ProxiedFuture"; type Accessor = "item" | "attr"; type TraceOperation = { @@ -222,6 +222,15 @@ export class Future { return this._directive.result(); } + [Symbol.toPrimitive]() { + // Because we would like to use `Future` values as accessors with bracket-notation on proxied `Future` values + // we need to ensure that when a `Future` instance is being converted into a primitive (as all values are when + // used with bracket-access are) we track a reference to the value and use a special ID that can be used + // later on in the proxy to look up and use the original `Future` when constructing the `Trace` used in the + // resulting proxied `Future`. + return proxyFactory.futureToPrimitive(this); + } + toJSON() { return { id: this._id, diff --git a/src/ProxiedFuture.ts b/src/ProxiedFuture.ts index fddc534..424073f 100644 --- a/src/ProxiedFuture.ts +++ b/src/ProxiedFuture.ts @@ -9,12 +9,22 @@ export const GET_TARGET = "$$GET_TARGET"; /** * @internal */ -export const makeProxyFactory = (futureTable: FutureTable = {}) => { +const makeProxyFactory = (futureTable: FutureTable = {}) => { + // Converts a future into an internal-ID that we use in the `FutureTable`. We're using this special + // format to mitigate potential conflicts with actual user-provided strings. const futureId = (future: Future): string => { // @ts-ignore (accessing protected property: _id) return `${ID_PREFIX}${future._id}`; }; + // Transforms a `Future` into an internal-ID to be used in the `FutureTable` and stores the `Future` + // in this table as a side-effect. Should be called when a `[Symbol.toPrimitive]()` is called on a `Future`. + const futureToPrimitive = (future: Future): string => { + const id = futureId(future); + futureTable[id] = future; // store in lookup table + return id; + } + const makeProxy = (future: Future): any => { return new Proxy(future, { has(target: Future, prop: any) { @@ -32,30 +42,19 @@ export const makeProxyFactory = (futureTable: FutureTable = {}) => { if (prop === GET_TARGET) return target; if (prop === Symbol.toPrimitive) { - // When the prop is not a primitive (number, string, Symbol) it will be attempted - // to be converted into one. This case will happen when the prop is a Future. - // - // Because only primitive types can be used as property accessors, what we're doing - // here is returning a Future ID, which is a string. We use this specially formatted - // ID to store the original Future in a lookup table we maintain as some hidden - // state in the SDK. - // - // When the prop (Future ID) is used as an accessor (eg. in the case of "bracket" - // access) we will use the returned Future ID here and look up the referenced Future - // when constructing new proxied Futures (in it's TraceProps). - return () => { - const utarget = unproxy(target); - const id = futureId(utarget); - futureTable[id] = utarget; // store in lookup table - return id; - }; + // Because we would like to use `Future` values as accessors with bracket-notation on proxied `Future` values + // we need to ensure that when a `Future` instance is being converted into a primitive (as all values are when + // used with bracket-access are) we track a reference to the value and use a special ID that can be used + // later on in the proxy to look up and use the original `Future` when constructing the `Trace` used in the + // resulting proxied `Future`. + return () => futureToPrimitive(unproxy(target)); } const nextProp = prop.startsWith(ID_PREFIX) ? // When the prop is a Future ID, we will lookup the corresponding Future // so that we can use it as a TraceProp in the resulting new Future. futureTable[prop]! - : // Otherwise the prop is not a future (always converted to string) + : // Otherwise the prop is not a future (converted to string at this point) (prop as string); // @ts-ignore (access protected prop: _directive) @@ -69,6 +68,7 @@ export const makeProxyFactory = (futureTable: FutureTable = {}) => { return { makeProxy, + futureToPrimitive, }; }; diff --git a/src/index.ts b/src/index.ts index 7d39e7a..9179c45 100644 --- a/src/index.ts +++ b/src/index.ts @@ -52,4 +52,8 @@ export { export { sb } from "substrate/sb"; export { Substrate }; import { Substrate } from "substrate/Substrate"; + + +export { Future, Trace } from "substrate/Future"; +export { Node } from "substrate/Node"; export default Substrate; diff --git a/tests/ProxiedFuture.test.ts b/tests/ProxiedFuture.test.ts index d6b1b45..8304058 100644 --- a/tests/ProxiedFuture.test.ts +++ b/tests/ProxiedFuture.test.ts @@ -1,7 +1,7 @@ import { expect, describe, test } from "vitest"; import { Future, Trace } from "substrate/Future"; import { Node } from "substrate/Node"; -import { makeProxyFactory, isProxy, unproxy } from "substrate/ProxiedFuture"; +import { proxyFactory, isProxy, unproxy } from "substrate/ProxiedFuture"; class FooFuture extends Future {} class FooNode extends Node {} @@ -11,7 +11,6 @@ const node = (id: string = "") => new FooNode({}, { id }); describe("ProxiedFuture", () => { describe("ProxyFactory", () => { test("makeProxy", () => { - const proxyFactory = makeProxyFactory(); const f = new FooFuture(new Trace([], node())); const p = proxyFactory.makeProxy(f); // Proxy is an instance of Future @@ -19,7 +18,6 @@ describe("ProxiedFuture", () => { }); test("isProxy", () => { - const proxyFactory = makeProxyFactory(); const f = new FooFuture(new Trace([], node())); const p = proxyFactory.makeProxy(f); // We can detect whether the proxied Future is a proxy @@ -30,7 +28,6 @@ describe("ProxiedFuture", () => { describe("Proxy", () => { test("unproxy (returns unproxied Future)", () => { - const proxyFactory = makeProxyFactory(); const f = new FooFuture(new Trace([], node())); const p = proxyFactory.makeProxy(f); const up = unproxy(p); @@ -39,16 +36,13 @@ describe("ProxiedFuture", () => { }); test("arbitrary property access (. notation)", () => { - const proxyFactory = makeProxyFactory(); const f = new FooFuture(new Trace([], node("123"))); const p = proxyFactory.makeProxy(f); - // @ts-ignore (properties don't exist) const f1 = p.a.b.c; expect(f1).instanceof(Future); expect(isProxy(f1)).toEqual(true); - // @ts-ignore ("virtual property" doesn't exist) const up = unproxy(f1); const json = up.toJSON(); @@ -64,7 +58,6 @@ describe("ProxiedFuture", () => { }); test("arbitrary property and index access (brackets)", () => { - const proxyFactory = makeProxyFactory(); const f = new FooFuture(new Trace([], node("123"))); const p = proxyFactory.makeProxy(f); @@ -86,27 +79,28 @@ describe("ProxiedFuture", () => { }); }); - // TODO(liam): I'm not sure why this test doesn't work yet, but it does work in example code - test.skip("using Future values as proxy accessors", () => { - const proxyFactory = makeProxyFactory(); + test("using Future values as proxy accessors", () => { const f = new FooFuture(new Trace([], node("123"))); const p = proxyFactory.makeProxy(f); const a = new FooFuture(new Trace([], node("456"))); + const b = new FooFuture(new Trace([], node("789"))); - // non index-types are illegal in the type system, so we're casting to any here. - const f1 = p[a as any]; + const f1 = p[a as any][b as any]; expect(f1).instanceof(Future); expect(isProxy(f1)).toEqual(true); const up = unproxy(f1); + const json = up.toJSON(); expect(json.directive).toEqual({ op_stack: [ // @ts-ignore { accessor: "attr", future_id: a._id, key: null }, + // @ts-ignore + { accessor: "attr", future_id: b._id, key: null }, ], origin_node_id: "123", type: "trace",