Skip to content

Commit

Permalink
[core-kit] Build all nodes.
Browse files Browse the repository at this point in the history
  • Loading branch information
dglazkov committed Oct 19, 2023
1 parent 05e4263 commit 3743ccf
Show file tree
Hide file tree
Showing 9 changed files with 426 additions and 1 deletion.
3 changes: 3 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion seeds/core-kit/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@google-labs/breadboard-core-kit",
"name": "@google-labs/core-kit",
"private": true,
"version": "0.0.1",
"description": "A Breadboard Kit containing nodes that enable composition and reuse of boards.",
Expand Down Expand Up @@ -46,5 +46,8 @@
"ava": "^5.2.0",
"typescript": "^5.0.4",
"@google-labs/tsconfig": "*"
},
"dependencies": {
"@google-labs/breadboard": "*"
}
}
72 changes: 72 additions & 0 deletions seeds/core-kit/src/nodes/import.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import { Board } from "@google-labs/breadboard";
import { SchemaBuilder } from "@google-labs/breadboard/kits";
import type {
InputValues,
BreadboardCapability,
NodeHandlerContext,
GraphDescriptor,
} from "@google-labs/breadboard";
import { LambdaNodeOutputs } from "./lambda.js";

export type ImportNodeInputs = InputValues & {
path?: string;
graph?: GraphDescriptor;
args: InputValues;
};

export default {
describe: async (inputs?: InputValues) => {
return {
inputSchema: new SchemaBuilder()
.addInputs(inputs)
.addProperties({
path: {
title: "path",
description: "The path to the board to import.",
type: "string",
},
graph: {
title: "graph",
description: "The graph descriptor of the board to import.",
type: "object",
},
})
.setAdditionalProperties(true)
.build(),
outputSchema: new SchemaBuilder().addProperties({
board: {
title: "board",
description: "The imported board.",
type: "object",
},
}),
};
},
invoke: async (
inputs: InputValues,
context: NodeHandlerContext
): Promise<LambdaNodeOutputs> => {
const { path, graph, ...args } = inputs as ImportNodeInputs;

const board = graph
? (graph as Board).runOnce // TODO: Hack! Use JSON schema or so instead.
? ({ ...graph } as Board)
: await Board.fromGraphDescriptor(graph)
: path
? await Board.load(path, {
base: context.board.url,
outerGraph: context.parent,
})
: undefined;
if (!board) throw Error("No board provided");
board.args = args;

return { board: { kind: "board", board } as BreadboardCapability };
},
};
88 changes: 88 additions & 0 deletions seeds/core-kit/src/nodes/include.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import type {
InputValues,
OutputValues,
BreadboardSlotSpec,
NodeHandlerContext,
BreadboardCapability,
GraphDescriptor,
} from "@google-labs/breadboard";
import { Board } from "@google-labs/breadboard";
import { SchemaBuilder } from "@google-labs/breadboard/kits";

export type IncludeNodeInputs = InputValues & {
path?: string;
$ref?: string;
board?: BreadboardCapability;
graph?: GraphDescriptor;
slotted?: BreadboardSlotSpec;
args: InputValues;
};

export default {
describe: async (inputs?: InputValues) => ({
inputSchema: new SchemaBuilder()
.setAdditionalProperties(true)
.addInputs(inputs)
.addProperties({
path: {
title: "path",
description: "The path to the board to include.",
type: "string",
},
$ref: {
title: "$ref",
description: "The $ref to the board to include.",
type: "string",
},
graph: {
title: "graph",
description: "The graph descriptor of the board to include.",
type: "object",
},
slotted: {
title: "slotted",
description: "The slotted graphs to include.",
type: "object",
},
})
.build(),
outputSchema: new SchemaBuilder().setAdditionalProperties(true).build(),
}),
invoke: async (
inputs: InputValues,
context: NodeHandlerContext
): Promise<OutputValues> => {
const { path, $ref, board, graph, slotted, ...args } =
inputs as IncludeNodeInputs;

// Add the current graph's URL as the url of the slotted graph,
// if there isn't an URL already.
const slottedWithUrls: BreadboardSlotSpec = {};
if (slotted) {
for (const key in slotted) {
slottedWithUrls[key] = { url: context.board.url, ...slotted[key] };
}
}

// TODO: Please fix the $ref/path mess.
const source = path || $ref || "";

const runnableBoard = board
? await Board.fromBreadboardCapability(board)
: graph
? await Board.fromGraphDescriptor(graph)
: await Board.load(source, {
slotted: slottedWithUrls,
base: context.board.url,
outerGraph: context.parent,
});

return await runnableBoard.runOnce(args, context);
},
};
69 changes: 69 additions & 0 deletions seeds/core-kit/src/nodes/invoke.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import type {
InputValues,
OutputValues,
NodeHandlerContext,
BreadboardCapability,
GraphDescriptor,
} from "@google-labs/breadboard";
import { Board } from "@google-labs/breadboard";
import { SchemaBuilder } from "@google-labs/breadboard/kits";

export type InvokeNodeInputs = InputValues & {
path?: string;
board?: BreadboardCapability;
graph?: GraphDescriptor;
};

export default {
describe: async (inputs?: InputValues) => ({
inputSchema: new SchemaBuilder()
.setAdditionalProperties(true)
.addInputs(inputs)
.addProperties({
path: {
title: "path",
description: "The path to the board to invoke.",
type: "string",
},
$ref: {
title: "board",
description: "The board to invoke, created by `lambda` or `import`",
type: "BoardCapability",
},
graph: {
title: "graph",
description: "The graph descriptor of the board to invoke.",
type: "object",
},
})
.build(),
outputSchema: new SchemaBuilder().setAdditionalProperties(true).build(),
}),
invoke: async (
inputs: InputValues,
context: NodeHandlerContext
): Promise<OutputValues> => {
const { path, board, graph, ...args } = inputs as InvokeNodeInputs;

const runnableBoard = board
? await Board.fromBreadboardCapability(board)
: graph
? await Board.fromGraphDescriptor(graph)
: path
? await Board.load(path, {
base: context.board.url,
outerGraph: context.parent,
})
: undefined;

if (!runnableBoard) throw new Error("No board provided");

return await runnableBoard.runOnce(args, context);
},
};
73 changes: 73 additions & 0 deletions seeds/core-kit/src/nodes/lambda.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import {
BreadboardCapability,
GraphDescriptor,
InputValues,
OutputValues,
} from "@google-labs/breadboard";
import { Board } from "@google-labs/breadboard";
import { SchemaBuilder } from "@google-labs/breadboard/kits";

export type LambdaNodeInputs = InputValues & {
/**
* The (lambda) board this node represents. The purpose of the this node is to
* allow wiring data into the lambda board, outside of where it's called.
* This is useful when passing a lambda to a map node or as a slot.
*
* Note that (for now) each board can only be represented by one node.
*/
board: BreadboardCapability;

/**
* All other inputs will be bound to the board.
*/
args: InputValues;
};

export type LambdaNodeOutputs = OutputValues & {
/**
* The lambda board that can be run.
*/
board: BreadboardCapability;
};

export default {
describe: async (inputs?: InputValues) => ({
inputSchema: new SchemaBuilder()
.setAdditionalProperties(true)
.addInputs(inputs)
.addProperty("board", {
title: "board",
description: "The board to run.",
type: "object",
})
.build(),
outputSchema: new SchemaBuilder()
.addProperty("board", {
title: "board",
description: "The now-runnable board.",
type: "object",
})
.build(),
}),
invoke: async (inputs: InputValues): Promise<LambdaNodeOutputs> => {
const { board, ...args } = inputs as LambdaNodeInputs;
if (!board || board.kind !== "board" || !board.board)
throw new Error(
`Lambda node requires a BoardCapability as "board" input`
);
const runnableBoard = {
...(await Board.fromBreadboardCapability(board)),
args,
};

return {
board: { ...board, board: runnableBoard as GraphDescriptor },
};
},
};
29 changes: 29 additions & 0 deletions seeds/core-kit/src/nodes/passthrough.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import type { InputValues, OutputValues } from "@google-labs/breadboard";
import { SchemaBuilder } from "@google-labs/breadboard/kits";

export default {
desribe: async (inputs?: InputValues) => {
if (!inputs) {
return {
inputSchema: SchemaBuilder.empty(true),
outputSchema: SchemaBuilder.empty(true),
};
}
return {
inputSchema: new SchemaBuilder()
.addInputs(inputs)
.setAdditionalProperties(true)
.build(),
outputSchema: new SchemaBuilder().addInputs(inputs).build(),
};
},
invoke: async (inputs: InputValues): Promise<OutputValues> => {
return inputs;
},
};
Loading

0 comments on commit 3743ccf

Please sign in to comment.