From 08c297dfd3df929d504439b3357115663bf0afeb Mon Sep 17 00:00:00 2001 From: Liam Griffiths Date: Thu, 1 Aug 2024 11:57:25 -0400 Subject: [PATCH 1/8] Implement `Module` node for running subgraphs --- examples/module.ts | 76 ++++++++++++++++++++++++++++++++++++++++++++++ examples/types.ts | 21 +++++++++++++ package-lock.json | 6 ++++ package.json | 1 + src/Future.ts | 54 +++++++++++++++++++++++++++++++- src/Module.ts | 25 +++++++++++++++ src/Substrate.ts | 47 ++++++++++++++++++++++++++++ src/index.ts | 2 ++ src/sb.ts | 3 +- 9 files changed, 233 insertions(+), 2 deletions(-) create mode 100755 examples/module.ts create mode 100755 examples/types.ts create mode 100644 src/Module.ts diff --git a/examples/module.ts b/examples/module.ts new file mode 100755 index 0000000..cadeada --- /dev/null +++ b/examples/module.ts @@ -0,0 +1,76 @@ +#!/usr/bin/env -S npx ts-node --transpileOnly + +import { Substrate, Box, Module, sb } from "substrate"; + +async function main() { + const SUBSTRATE_API_KEY = process.env["SUBSTRATE_API_KEY"]; + + const substrate = new Substrate({ apiKey: SUBSTRATE_API_KEY }); + + const x = sb.input({ type: "string", default: "hello" }); + const y = sb.input({ type: "string" }); + const z = sb.input({ type: "object", properties: {} }); + + const a = new Box({ value: { a: x, z: z, array: [x, x, x] } }, { id: "A" }); + const b = new Box( + { value: { b: sb.interpolate`x=${a.future.value.get("a")}, y=${y}` } }, + { id: "B" }, + ); + + // publish the module on substrate.run + // const publication = await substrate.module.publish({ + // name: "my reusable graph", + // nodes: [a, b], + // inputs: { x, y, z }, + // }); + + // update the module on substrate.run + // const updated = await substrate.module.publish({ + // id: publication.id, + // name: "my reusable graph (edited)", + // nodes: [a, b], + // inputs: { x, y, z }, + // }); + + // using the module from JSON + const mod = new Module({ + module_json: substrate.module.serialize({ + nodes: [a, b], + inputs: { x, y, z }, + }), + inputs: { + // when commented will use "hello" because it is defined as the default above + // x: 123, + y: "yyy", + z: { + arr: ["123"], + }, + }, + }); + + // using the module from publication/module id + // const mod = new Module({ + // module_id: publication.id, + // inputs: { y: "yyy", z: { arr: ["123"] } }, + // }); + + // using the module from publication/module uri + // const mod = new Module({ + // module_uri: publication.uri, + // inputs: { y: "yyy", z: { arr: ["123"] } }, + // }); + + const c = new Box( + { + value: { + "1": mod.future.get("A.value.z.arr[0]"), + "2": mod.future.get("B.value.b"), + }, + }, + { id: "C" }, + ); + + const res = await substrate.run(mod, c); + console.log(JSON.stringify(res.json, null, 2)); +} +main(); diff --git a/examples/types.ts b/examples/types.ts new file mode 100755 index 0000000..725bef7 --- /dev/null +++ b/examples/types.ts @@ -0,0 +1,21 @@ +#!/usr/bin/env -S npx ts-node --transpileOnly + + +class Foo any> { + f: F; + + constructor(f: F) { + this.f = f; + } + + run(...args: Parameters): ReturnType { + return this.f(...args); + } +} + +// (a: number, b: number) => number +const add = (a: number, b: number) => a + b; + +const foo = new Foo(add); +// run(a: number, b: number): ReturnType<(a: number, b: number) => number> +const res = foo.run(1, 2); diff --git a/package-lock.json b/package-lock.json index c11e188..f8879ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "120240617.1.7", "license": "MIT", "dependencies": { + "@types/json-schema": "^7.0.15", "@types/node-fetch": "^2.6.11", "node-fetch": "2.7.0", "pako": "^2.1.0" @@ -798,6 +799,11 @@ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + }, "node_modules/@types/node": { "version": "20.14.11", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz", diff --git a/package.json b/package.json index f778af3..234dbe5 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "vitest": "^1.0.4" }, "dependencies": { + "@types/json-schema": "^7.0.15", "@types/node-fetch": "^2.6.11", "node-fetch": "2.7.0", "pako": "^2.1.0" diff --git a/src/Future.ts b/src/Future.ts index 75559a5..336f991 100644 --- a/src/Future.ts +++ b/src/Future.ts @@ -1,5 +1,6 @@ import { idGenerator } from "substrate/idGenerator"; import { Node } from "substrate/Node"; +import { type JSONSchema7 } from "json-schema"; type Accessor = "item" | "attr"; type TraceOperation = { @@ -26,6 +27,7 @@ const parsePath = (path: string): TraceProp[] => { }; const newFutureId = idGenerator("future"); +const newInputId = idGenerator("input"); abstract class Directive { abstract items: any[]; @@ -122,7 +124,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); } @@ -315,3 +317,53 @@ export class FutureAnyObject extends Future { return super._result(); } } + +export class Input extends Directive { + items: any[]; // NOTE: unused field (will remove this from direcitve in a later refactor) + name: string | null; + + constructor(items: any[]) { + super(); + this.items = items; + } + + override next(...args: any[]) { + return new Input(args); + } + + override async result(): Promise { + return; + } + + override toJSON() { + return { + type: "input", + name: this.name, + }; + } +} + +export class FutureInput extends Future { + declare _directive: Input; + schema: JSONSchema7; + + constructor(schema?: JSONSchema7, id: string = newInputId()) { + super(new Input([]), id); + this.schema = schema ?? {}; + } +} + +/** + * Specify an `input` future that can be assigned a name when create a new module. + * Input types and validation paramters may optionally be described using a JSON Schema object. + * + * Default values may also be specified here and will be used if user input is not provided for this input. + */ +export function input(schema?: FutureInput["schema"]) { + // NOTE: using `any` as the return type here for now to ease using + // this in general node input args or helper functions. + // + // Once we ship our Future type reorganization work, we can just + // use this as-is (Future) + return new FutureInput(schema) as any; +} diff --git a/src/Module.ts b/src/Module.ts new file mode 100644 index 0000000..009ff2b --- /dev/null +++ b/src/Module.ts @@ -0,0 +1,25 @@ +import { Node, Options } from "substrate/Node"; +import { FutureInput } from "substrate/Future"; + +export type ModuleInputs = Record; + +type ModuleIn = + | { + module_json: any; + inputs: Record; + } + | { + module_id: any; + inputs: Record; + } + | { + module_uri: any; + inputs: Record; + }; + +export class Module extends Node { + constructor(args: ModuleIn, options?: Options) { + super(args, options); + this.node = "Module"; + } +} diff --git a/src/Substrate.ts b/src/Substrate.ts index e123c9f..cb691aa 100644 --- a/src/Substrate.ts +++ b/src/Substrate.ts @@ -8,6 +8,7 @@ import { Future } from "substrate/Future"; import { getPlatformProperties } from "substrate/Platform"; import { deflate } from "pako"; import { randomString } from "substrate/idGenerator"; +import { ModuleInputs } from "./Module"; type Configuration = { /** @@ -291,4 +292,50 @@ export class Substrate { return headers; } + + module = { + /** + * Returns an object that represents a publishable "module" or code that can be used to construct + * a `Module` node. + */ + serialize: ({ nodes, inputs }: { nodes: Node[]; inputs: ModuleInputs }) => { + const inputIdToName = {}; + const inputNameToSchema = {}; + + for (let name in inputs) { + let input = inputs[name]; + // @ts-ignore + inputIdToName[input._id] = name; + // @ts-ignore + inputNameToSchema[name] = input.schema; + } + + const dag = Substrate.serialize(...nodes); + + // update variable name bindings in dag using inputs + dag.futures = dag.futures.map((future: any) => { + if (future.directive.type === "input" && !future.directive.name) { + // @ts-ignore + future.directive.name = inputIdToName[future.id]; + } + return future; + }); + + return { + dag, + inputs: inputNameToSchema, + api_version: this.apiVersion, + }; + }, + + /** + * Publishes a module on substrate.run + * A successful response will contain the module id and web uri + */ + publish: async (_publishable: any) => { + console.log("not implemented yet"); + let publication; + return publication; + }, + }; } diff --git a/src/index.ts b/src/index.ts index bf57663..2120dd7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -51,6 +51,8 @@ export { DeleteVectors, } from "substrate/Nodes"; +export { Module } from "substrate/Module"; + export { sb } from "substrate/sb"; export { Substrate }; import { Substrate } from "substrate/Substrate"; diff --git a/src/sb.ts b/src/sb.ts index f94848c..0e1bffd 100644 --- a/src/sb.ts +++ b/src/sb.ts @@ -1,10 +1,11 @@ -import { FutureAnyObject, FutureString } from "substrate/Future"; +import { FutureAnyObject, FutureString, input } from "substrate/Future"; import { StreamingResponse } from "substrate/SubstrateStreamingResponse"; export const sb = { concat: FutureString.concat, jq: FutureAnyObject.jq, interpolate: FutureString.interpolate, + input, streaming: { fromSSEResponse: StreamingResponse.fromReponse, }, From e39fdcf9c1d94620c65062d034f0d2aa2c431f63 Mon Sep 17 00:00:00 2001 From: Liam Griffiths Date: Mon, 5 Aug 2024 15:00:47 -0400 Subject: [PATCH 2/8] Formatting --- examples/mixture-of-agents/index.html | 4 ++-- examples/types.ts | 1 - src/Substrate.ts | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/mixture-of-agents/index.html b/examples/mixture-of-agents/index.html index a35d275..e971b73 100644 --- a/examples/mixture-of-agents/index.html +++ b/examples/mixture-of-agents/index.html @@ -165,7 +165,7 @@ "GPT-4o Mini", "Llama 3.1 8B", "Mixtral 8x7B", - ] + ]; const individualResults = "{{ individual }}"; const aggResults = "{{ summaries }}"; @@ -190,7 +190,7 @@ contentArea.textContent = individualResults[currentLayer][currentIndex].trim(); - cardTitle.textContent = `${modelNames[currentIndex]} - Layer ${ currentLayer + 1 }`; + cardTitle.textContent = `${modelNames[currentIndex]} - Layer ${currentLayer + 1}`; } else { contentArea.textContent = aggResults[currentLayer].trim(); cardTitle.textContent = `MoA Layer ${currentLayer + 1}`; diff --git a/examples/types.ts b/examples/types.ts index 725bef7..5a6958b 100755 --- a/examples/types.ts +++ b/examples/types.ts @@ -1,6 +1,5 @@ #!/usr/bin/env -S npx ts-node --transpileOnly - class Foo any> { f: F; diff --git a/src/Substrate.ts b/src/Substrate.ts index cb691aa..81d7850 100644 --- a/src/Substrate.ts +++ b/src/Substrate.ts @@ -295,7 +295,7 @@ export class Substrate { module = { /** - * Returns an object that represents a publishable "module" or code that can be used to construct + * Returns an object that represents a publishable "module" or code that can be used to construct * a `Module` node. */ serialize: ({ nodes, inputs }: { nodes: Node[]; inputs: ModuleInputs }) => { From 5863abaa39bdf006ec519c360c866167ca3aa25c Mon Sep 17 00:00:00 2001 From: Liam Griffiths Date: Wed, 7 Aug 2024 16:06:22 -0400 Subject: [PATCH 3/8] Implements module publishing (create only) --- src/Module.ts | 17 +++++++++++++- src/Substrate.ts | 48 +++++++++++++++++++++++++++++++++------- src/SubstrateResponse.ts | 17 ++++++++++++++ 3 files changed, 73 insertions(+), 9 deletions(-) diff --git a/src/Module.ts b/src/Module.ts index 009ff2b..1cc119f 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -1,6 +1,21 @@ import { Node, Options } from "substrate/Node"; import { FutureInput } from "substrate/Future"; +type ModuleId = `mod_${string}`; + +export type SerializableModule = { + nodes: Node[]; + inputs: ModuleInputs; +}; + +export type NewModule = SerializableModule & { name: string }; +export type UpdateModule = NewModule & { id: ModuleId }; +export type PublishableModule = NewModule; // | UpdateModule; (TODO: implement update module) +export type PublishedModule = { + id: ModuleId; + uri: string; +}; + export type ModuleInputs = Record; type ModuleIn = @@ -9,7 +24,7 @@ type ModuleIn = inputs: Record; } | { - module_id: any; + module_id: ModuleId; inputs: Record; } | { diff --git a/src/Substrate.ts b/src/Substrate.ts index 81d7850..045e6d8 100644 --- a/src/Substrate.ts +++ b/src/Substrate.ts @@ -1,14 +1,17 @@ import { SubstrateError, RequestTimeoutError } from "substrate/Error"; import { VERSION } from "substrate/version"; import OpenAPIjson from "substrate/openapi.json"; -import { SubstrateResponse } from "substrate/SubstrateResponse"; +import { + asSubstratePublishedModuleResponse, + SubstrateResponse, +} from "substrate/SubstrateResponse"; import { SubstrateStreamingResponse } from "substrate/SubstrateStreamingResponse"; import { Node } from "substrate/Node"; import { Future } from "substrate/Future"; import { getPlatformProperties } from "substrate/Platform"; import { deflate } from "pako"; import { randomString } from "substrate/idGenerator"; -import { ModuleInputs } from "./Module"; +import { SerializableModule, PublishableModule } from "substrate/Module"; type Configuration = { /** @@ -298,7 +301,7 @@ export class Substrate { * Returns an object that represents a publishable "module" or code that can be used to construct * a `Module` node. */ - serialize: ({ nodes, inputs }: { nodes: Node[]; inputs: ModuleInputs }) => { + serialize: ({ nodes, inputs }: SerializableModule) => { const inputIdToName = {}; const inputNameToSchema = {}; @@ -330,12 +333,41 @@ export class Substrate { /** * Publishes a module on substrate.run - * A successful response will contain the module id and web uri */ - publish: async (_publishable: any) => { - console.log("not implemented yet"); - let publication; - return publication; + publish: async ( + publishable: PublishableModule, + // endpoint: string = "https://substrate.run/api/modules", + endpoint: string = "http://localhost:3000/api/modules", + ) => { + const serialized = this.module.serialize({ + nodes: publishable.nodes, + inputs: publishable.inputs, + }); + + const body = { + module: { name: publishable.name }, + module_version: serialized, + }; + + const requestOptions = { + method: "POST", + headers: this.headers(), + body: JSON.stringify(body), + }; + + const request = new Request(endpoint, requestOptions); + const requestId = request.headers.get("x-substrate-request-id"); + const apiResponse = await fetch(request); + + if (apiResponse.ok) { + const json = await apiResponse.json(); + const res = new SubstrateResponse(request, apiResponse, json); + return asSubstratePublishedModuleResponse(res); + } else { + throw new SubstrateError( + `[Request failed] status=${apiResponse.status} statusText=${apiResponse.statusText} requestId=${requestId}`, + ); + } }, }; } diff --git a/src/SubstrateResponse.ts b/src/SubstrateResponse.ts index 65d00cf..61f67e6 100644 --- a/src/SubstrateResponse.ts +++ b/src/SubstrateResponse.ts @@ -1,5 +1,6 @@ import { AnyNode, NodeOutput } from "substrate/Nodes"; import { NodeError } from "substrate/Error"; +import { PublishedModule } from "substrate/Module"; /** * Response to a run request. @@ -39,3 +40,19 @@ export class SubstrateResponse { return node.output() as NodeOutput; } } + +// TODO: create an alternate SubstrateResponse for non-compose responses +// For now using a type assertions and modifying the object. +export type SubstratePublishModuleResponse = Omit< + SubstrateResponse, + "get" | "getError" +> & { json: PublishedModule }; +export const asSubstratePublishedModuleResponse = ( + res: SubstrateResponse, +): SubstratePublishModuleResponse => { + // @ts-ignore + delete res.get; + // @ts-ignore + delete res.getError; + return res as SubstratePublishModuleResponse; +}; From ebd1e8e32d06af10157837501993aed640b77fd3 Mon Sep 17 00:00:00 2001 From: Liam Griffiths Date: Wed, 7 Aug 2024 16:06:59 -0400 Subject: [PATCH 4/8] Delete examples/types.ts --- examples/types.ts | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100755 examples/types.ts diff --git a/examples/types.ts b/examples/types.ts deleted file mode 100755 index 5a6958b..0000000 --- a/examples/types.ts +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env -S npx ts-node --transpileOnly - -class Foo any> { - f: F; - - constructor(f: F) { - this.f = f; - } - - run(...args: Parameters): ReturnType { - return this.f(...args); - } -} - -// (a: number, b: number) => number -const add = (a: number, b: number) => a + b; - -const foo = new Foo(add); -// run(a: number, b: number): ReturnType<(a: number, b: number) => number> -const res = foo.run(1, 2); From 3cbcd5b25b9b728e45daf96d0b589885c8718b4b Mon Sep 17 00:00:00 2001 From: Liam Griffiths Date: Thu, 8 Aug 2024 11:08:49 -0400 Subject: [PATCH 5/8] Change `sb.input` to `sb.var` and some internal names from `input` to `variable` --- src/Future.ts | 31 ++++++++----------------------- src/Module.ts | 4 ++-- src/Substrate.ts | 2 +- src/sb.ts | 16 ++++++++++++++-- 4 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/Future.ts b/src/Future.ts index 336f991..601f81c 100644 --- a/src/Future.ts +++ b/src/Future.ts @@ -27,7 +27,6 @@ const parsePath = (path: string): TraceProp[] => { }; const newFutureId = idGenerator("future"); -const newInputId = idGenerator("input"); abstract class Directive { abstract items: any[]; @@ -318,7 +317,7 @@ export class FutureAnyObject extends Future { } } -export class Input extends Directive { +export class Variable extends Directive { items: any[]; // NOTE: unused field (will remove this from direcitve in a later refactor) name: string | null; @@ -328,7 +327,7 @@ export class Input extends Directive { } override next(...args: any[]) { - return new Input(args); + return new Variable(args); } override async result(): Promise { @@ -337,33 +336,19 @@ export class Input extends Directive { override toJSON() { return { - type: "input", + type: "variable", + source: "input", name: this.name, }; } } -export class FutureInput extends Future { - declare _directive: Input; +export class FutureVariable extends Future { + declare _directive: Variable; schema: JSONSchema7; - constructor(schema?: JSONSchema7, id: string = newInputId()) { - super(new Input([]), id); + constructor(schema?: JSONSchema7, id: string = newFutureId()) { + super(new Variable([]), id); this.schema = schema ?? {}; } } - -/** - * Specify an `input` future that can be assigned a name when create a new module. - * Input types and validation paramters may optionally be described using a JSON Schema object. - * - * Default values may also be specified here and will be used if user input is not provided for this input. - */ -export function input(schema?: FutureInput["schema"]) { - // NOTE: using `any` as the return type here for now to ease using - // this in general node input args or helper functions. - // - // Once we ship our Future type reorganization work, we can just - // use this as-is (Future) - return new FutureInput(schema) as any; -} diff --git a/src/Module.ts b/src/Module.ts index 1cc119f..0a0411c 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -1,5 +1,5 @@ import { Node, Options } from "substrate/Node"; -import { FutureInput } from "substrate/Future"; +import { FutureVariable } from "substrate/Future"; type ModuleId = `mod_${string}`; @@ -16,7 +16,7 @@ export type PublishedModule = { uri: string; }; -export type ModuleInputs = Record; +export type ModuleInputs = Record; type ModuleIn = | { diff --git a/src/Substrate.ts b/src/Substrate.ts index 045e6d8..6a18f98 100644 --- a/src/Substrate.ts +++ b/src/Substrate.ts @@ -317,7 +317,7 @@ export class Substrate { // update variable name bindings in dag using inputs dag.futures = dag.futures.map((future: any) => { - if (future.directive.type === "input" && !future.directive.name) { + if (future.directive.type === "variable" && !future.directive.name) { // @ts-ignore future.directive.name = inputIdToName[future.id]; } diff --git a/src/sb.ts b/src/sb.ts index 0e1bffd..acd80e6 100644 --- a/src/sb.ts +++ b/src/sb.ts @@ -1,11 +1,23 @@ -import { FutureAnyObject, FutureString, input } from "substrate/Future"; +import { FutureAnyObject, FutureVariable, FutureString } from "substrate/Future"; import { StreamingResponse } from "substrate/SubstrateStreamingResponse"; export const sb = { concat: FutureString.concat, jq: FutureAnyObject.jq, interpolate: FutureString.interpolate, - input, + /** + * `var` is used to specify a variable that can be bound to a name when creating a `module` (re-usable Substrate Graph) + * * Input types and validation paramters may optionally be described using a JSON Schema object. + * * Default values may also be specified here and will be used if user input is not provided for this input. + */ + var: (schema: FutureVariable["schema"]) => { + // NOTE: using `any` as the return type here for now to ease using + // this in general node input args or helper functions. + // + // Once we ship our Future type reorganization work, we can just + // use this as-is (Future) + return new FutureVariable(schema) as any; + }, streaming: { fromSSEResponse: StreamingResponse.fromReponse, }, From f95ff0a89851960752a76903695e2df075acf806 Mon Sep 17 00:00:00 2001 From: Liam Griffiths Date: Wed, 21 Aug 2024 11:11:16 -0400 Subject: [PATCH 6/8] Formatting --- src/sb.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/sb.ts b/src/sb.ts index acd80e6..9e41861 100644 --- a/src/sb.ts +++ b/src/sb.ts @@ -1,4 +1,8 @@ -import { FutureAnyObject, FutureVariable, FutureString } from "substrate/Future"; +import { + FutureAnyObject, + FutureVariable, + FutureString, +} from "substrate/Future"; import { StreamingResponse } from "substrate/SubstrateStreamingResponse"; export const sb = { From aad7e3ab5e852752a47b234a423a244a212cc3a2 Mon Sep 17 00:00:00 2001 From: Liam Griffiths Date: Wed, 21 Aug 2024 12:23:33 -0400 Subject: [PATCH 7/8] Update sdk code, example --- examples/module.ts | 32 +++++++++----------------------- src/Substrate.ts | 8 ++++++-- 2 files changed, 15 insertions(+), 25 deletions(-) diff --git a/examples/module.ts b/examples/module.ts index cadeada..8411089 100755 --- a/examples/module.ts +++ b/examples/module.ts @@ -4,12 +4,11 @@ import { Substrate, Box, Module, sb } from "substrate"; async function main() { const SUBSTRATE_API_KEY = process.env["SUBSTRATE_API_KEY"]; - const substrate = new Substrate({ apiKey: SUBSTRATE_API_KEY }); - const x = sb.input({ type: "string", default: "hello" }); - const y = sb.input({ type: "string" }); - const z = sb.input({ type: "object", properties: {} }); + const x = sb.var({ type: "string", default: "hello" }); + const y = sb.var({ type: "string" }); + const z = sb.var({ type: "object", properties: {} }); const a = new Box({ value: { a: x, z: z, array: [x, x, x] } }, { id: "A" }); const b = new Box( @@ -18,19 +17,12 @@ async function main() { ); // publish the module on substrate.run - // const publication = await substrate.module.publish({ - // name: "my reusable graph", - // nodes: [a, b], - // inputs: { x, y, z }, - // }); - - // update the module on substrate.run - // const updated = await substrate.module.publish({ - // id: publication.id, - // name: "my reusable graph (edited)", - // nodes: [a, b], - // inputs: { x, y, z }, - // }); + const publication = await substrate.module.publish({ + name: "my reusable graph", + nodes: [a, b], + inputs: { x, y, z }, + }); + console.log("published:", publication.json); // using the module from JSON const mod = new Module({ @@ -54,12 +46,6 @@ async function main() { // inputs: { y: "yyy", z: { arr: ["123"] } }, // }); - // using the module from publication/module uri - // const mod = new Module({ - // module_uri: publication.uri, - // inputs: { y: "yyy", z: { arr: ["123"] } }, - // }); - const c = new Box( { value: { diff --git a/src/Substrate.ts b/src/Substrate.ts index 6a18f98..6523dd6 100644 --- a/src/Substrate.ts +++ b/src/Substrate.ts @@ -333,12 +333,16 @@ export class Substrate { /** * Publishes a module on substrate.run + * */ publish: async ( publishable: PublishableModule, - // endpoint: string = "https://substrate.run/api/modules", - endpoint: string = "http://localhost:3000/api/modules", + endpoint: string = "https://www.substrate.run/api/modules", ) => { + /** + * NOTE: Because the Module publishing API lives in another app and subdomain, the `baseUrl` configuration + * will not be applied to this request like we do with `.run` + */ const serialized = this.module.serialize({ nodes: publishable.nodes, inputs: publishable.inputs, From 281680b73ad19977716444f559e6bd67b435b930 Mon Sep 17 00:00:00 2001 From: Liam Griffiths Date: Wed, 21 Aug 2024 12:24:13 -0400 Subject: [PATCH 8/8] Remove uri option --- src/Module.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Module.ts b/src/Module.ts index 0a0411c..9950e50 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -26,10 +26,6 @@ type ModuleIn = | { module_id: ModuleId; inputs: Record; - } - | { - module_uri: any; - inputs: Record; }; export class Module extends Node {